Vim-style window management: command mode, split windows, per-window live channels#87
Open
gammons wants to merge 29 commits into
Open
Vim-style window management: command mode, split windows, per-window live channels#87gammons wants to merge 29 commits into
gammons wants to merge 29 commits into
Conversation
…rder-inclusive Width) lipgloss v2's Style.Width is border-inclusive, so renderUnfocusedWindow's UnfocusedBorder.Width(W-2).Render(view) gave the model's exactly (W-2)-cell lines a (W-4)-cell budget. Any line with real content in its last 2 cells re-wrapped onto an injected remainder row — and the scrollbar puts a glyph in the LAST cell of every line, garbling every scrolled-back unfocused pane; exactSize's MaxHeight clamp then ate the bottom border and masked the row-count blowup. Lines ending in blank padding were silently truncated by 2 cells instead (trailing-whitespace overflow is dropped, not wrapped), which is why sparse panes and the dimension tests looked fine. Mirror the focused path: refactor borderedTopPane's body into borderedPaneCore(bottomEdge bool) and add borderedPane, the fully-enclosed sibling that emits exactly Rect.W x Rect.H by concatenation around the model's width-padded lines — no lipgloss re-measure (terminal-probed emoji widths can disagree with x/ansi), no exactSize pass, per-window cache unchanged. Tests: regression pinning that every model line survives intact between the side verticals with the bottom edge present (RED on HEAD), TestBorderedPane_MatchesLipgloss equivalence gate against the corrected Width(innerWidth+2) lipgloss form, and per-row width assertions in TestRegion_SplitOutputDimensionsStable.
This was referenced Jun 11, 2026
…nagement Integration decisions: - keys.go/mode_normal.go: union of search bindings (/ n N ctrl+f) and window-command bindings (ctrl+w prefix, keyless :ws WorkspaceFinder) - statusbar: the :command prompt owns the left side while active; search segment renders otherwise - OlderMessagesLoadedMsg: main's AnchorTS replaced-buffer guard applied PER WINDOW inside the phase-3 fan-out loop (strictly safer: siblings with the original buffer still receive the block); fetchingOlder stays the per-channel map, cleared even when no window views the channel - focusWindow clears active in-channel search before the pane pointer swap (search match list + highlights are focused-pane state) + test - main's live-reaction tests adapted to phase-3 channel routing (pane must view the channel); fanout backfill test supplies AnchorTS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Combined PR for the full vim-style window-management feature (supersedes #81 and #86, which will be closed). Spec:
docs/superpowers/specs/2026-06-11-window-management-design.md.Summary
:command mode (phase 1):opens a status-bar prompt with vim semantics (Esc / backspace-past-:cancel, Enter executes, unknown commands toast); command registry as the extension pointctrl+wreclaimed from the workspace finder (now:ws;1-9still switch directly)Window tree (phase 2)
internal/ui/wintreepackage: vim-style split tree, exact-tiling geometry, simulate-and-check minimum-size refusal, geometricctrl+w h/j/k/lnavigation:sp:vsp:q:only/:on+ctrl+wchords (s v h j k l w q c o) behind a pending-key state with status-bar hintPer-window live channels (phase 3)
messages.Model; splits seed deep-copied clones; focus changes are instant pointer swapsNotable fixes hardened along the way: render-cache window-identity keys (wrong-frame-after-focus-swap), reaction-array aliasing across clones, workspace-switch state leak, resize-after-split crash clamps, frozen spinner in unfocused loading panes, stranded syncing indicator, and the lipgloss border-inclusive-
Widthre-wrap bug in unfocused panes (zero-measurement border assembly, matching the focused hot path).Deferred to phase 4 (tracked in the spec): per-window mouse routing & drag-resize (split-mode clicks are guarded off), resize chords (
ctrl+w = < > + -), Tab focus-cycle window-walk, mark-read on window focus, typing rows in unfocused panes.Test Plan
go test ./... -count=1),go vetclean,-raceclean on the new paths, every commit builds