feat(editor): implement multi-pane split layout#2416
Conversation
- added vertical pane creation too - vscode style keybinds - resizing of pane - few bug fixes
Greptile SummaryThis PR introduces a full multi-pane split-screen editor layout, adding per-pane tab bars, a recursive layout tree for arbitrary horizontal/vertical splits, drag-to-pane tab transfer, resize handles, and directional keyboard navigation between panes.
Confidence Score: 4/5Large but well-structured feature addition; previously identified multi-pane race conditions appear addressed in this revision. Remaining concerns are interaction-edge-case quality issues rather than data-loss paths. The pane lifecycle, layout tree, drag-to-pane transfer, and per-file debounce isolation are implemented carefully. The blur-event gap in makeActive is fixed, LSP tokens are now per-pane, and timers use a WeakMap keyed on the file. clearScrollbarScrollLock is wired to every pane's scroller with no active-pane guard, concurrent createPane calls both pass the size check before either is registered, and all keyboard pane-focus commands skip editor DOM focus. src/lib/editorManager.js deserves the closest review pass — it carries the full pane engine, the Proxy-based open-file-list mirror, and the withPaneEditorContext context-swap pattern. src/handlers/editorFileTab.js is worth a second look for the drag-session-id stale-cleanup fix under rapid drag sequences. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant U as User
participant KB as KeyBinding
participant EM as EditorManager
participant PL as PaneLayout
participant EF as EditorFile
U->>KB: Ctrl-\ (split right)
KB->>EM: splitPaneRight()
EM->>EM: canCreatePane(horizontal, sourcePane)?
EM->>EM: createPaneShell(false)
EM->>EM: await createPaneEditor(pane)
EM->>PL: insertPaneIntoLayout(source, newPane, horizontal)
EM->>EM: animatePaneEntry(pane)
EM->>EF: createUntitledPaneFile(pane)
EF->>EM: makeActive() to switchFile(id, pane)
EM->>EM: setActivePane(pane)
U->>U: Drag tab from Pane A to Pane B
Note over U,EM: moveDragToParent of tabList of Pane B
U->>EM: releaseDrag to commitPaneTransfer()
EM->>EM: moveFileToPane(file, targetPane)
EM->>EF: file.makeActive() in targetPane
EM->>EM: syncOpenFileList()
U->>KB: Ctrl-Alt-W (close pane)
KB->>EM: closeActivePane()
EM->>EM: moveFileToPane each file to targetPane
EM->>EM: pane.touchSelectionController.destroy()
EM->>EM: pane.editor.destroy()
EM->>PL: removePaneFromLayout(pane)
EM->>EF: fileToActivate.makeActive()
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant U as User
participant KB as KeyBinding
participant EM as EditorManager
participant PL as PaneLayout
participant EF as EditorFile
U->>KB: Ctrl-\ (split right)
KB->>EM: splitPaneRight()
EM->>EM: canCreatePane(horizontal, sourcePane)?
EM->>EM: createPaneShell(false)
EM->>EM: await createPaneEditor(pane)
EM->>PL: insertPaneIntoLayout(source, newPane, horizontal)
EM->>EM: animatePaneEntry(pane)
EM->>EF: createUntitledPaneFile(pane)
EF->>EM: makeActive() to switchFile(id, pane)
EM->>EM: setActivePane(pane)
U->>U: Drag tab from Pane A to Pane B
Note over U,EM: moveDragToParent of tabList of Pane B
U->>EM: releaseDrag to commitPaneTransfer()
EM->>EM: moveFileToPane(file, targetPane)
EM->>EF: file.makeActive() in targetPane
EM->>EM: syncOpenFileList()
U->>KB: Ctrl-Alt-W (close pane)
KB->>EM: closeActivePane()
EM->>EM: moveFileToPane each file to targetPane
EM->>EM: pane.touchSelectionController.destroy()
EM->>EM: pane.editor.destroy()
EM->>PL: removePaneFromLayout(pane)
EM->>EF: fileToActivate.makeActive()
Reviews (19): Last reviewed commit: "fix: address multi-pane review concerns ..." | Re-trigger Greptile |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment has been minimized.
This comment has been minimized.
This comment was marked as outdated.
This comment was marked as outdated.
187dad6 to
1c478aa
Compare
|
@greptile_apps |
This PR introduces support for a Multi-Pane (Split-Screen) Editor Layout, allowing users to open multiple editor panes and view files/tabs side-by-side (similar to desktop code editors). Each pane acts as a self-contained editor workspace with its own tab bar, and tabs things. And it is not limited to editor tabs, it can work with any editor tabs such as terminal, custom, editor, media etc.
It adds few commands for this multi pane, which you can search in command palette with
panekeyword.And some keybinds: