Skip to content

feat(editor): implement multi-pane split layout#2416

Merged
deadlyjack merged 27 commits into
mainfrom
feat/multi-pane-view
Jul 4, 2026
Merged

feat(editor): implement multi-pane split layout#2416
deadlyjack merged 27 commits into
mainfrom
feat/multi-pane-view

Conversation

@bajrangCoder

@bajrangCoder bajrangCoder commented Jun 28, 2026

Copy link
Copy Markdown
Member

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 pane keyword.
And some keybinds:

  • Ctrl-\ : Split editor pane right
  • Ctrl-Shift-\ : Split editor pane down
  • Ctrl-Alt-W : Close active editor pane
  • Ctrl-Alt-Left : Focus editor pane to the left
  • Ctrl-Alt-Right : Focus editor pane to the right
  • Ctrl-Alt-Up : Focus editor pane above
  • Ctrl-Alt-Down : Focus editor pane below
  • Ctrl-Alt-\ : Move current tab to new pane
Screenshot 2026-06-28 at 11 03 22 PM image

@github-actions github-actions Bot added the enhancement New feature or request label Jun 28, 2026
@bajrangCoder bajrangCoder changed the title feat: add multi pane view feat(editor): implement multi-pane split layout Jun 28, 2026
@bajrangCoder bajrangCoder moved this from Backlog to In progress in The Code Board - Acode Jun 29, 2026
@bajrangCoder bajrangCoder marked this pull request as ready for review June 29, 2026 08:50
@greptile-apps

greptile-apps Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This 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.

  • Core pane engine (editorManager.js): ~2,200 lines added to implement pane lifecycle (create/close/resize/focus/move), a binary layout tree with split nodes, per-pane LSP request token isolation, per-file debounce timer WeakMap replacing the previous shared module-level timers, and a Proxy-based global open-file list mirror so existing sidebar consumers continue to see all files across panes.
  • Drag system (editorFileTab.js): FLIP animations migrated to Motion; stale safety-net cleanup bug addressed via dragSessionId snapshot; contentEditable file-path drop replaced with proper Range/Selection API insertion.
  • File lifecycle (editorFile.js): makeActive now correctly calls removeActive() on both the previous pane's active file and the globally active file; per-pane placeholder tabs manage empty-pane state.

Confidence Score: 4/5

Large 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

Filename Overview
src/lib/editorManager.js Core of the multi-pane implementation: adds pane lifecycle (create/close/resize/focus), a pane-aware layout tree, per-pane LSP token management, per-file timer WeakMap for debounce, and a mirror/proxy layer for the global open-file list. Previously identified async race conditions for LSP, timer collision, and setTheme appear fixed. New concerns: animation safety-net gap, concurrent createPane size bypass, and clearScrollbarScrollLock registered on all pane scrollers without a guard.
src/lib/editorFile.js makeActive now calls removeActive() on both the target pane's previous active file and the globally active file, fixing the blur-event gap flagged in previous reviews. Non-editor content placement logic is duplicated between makeActive and switchFile (redundant but harmless). Per-file isPanePlaceholder lifecycle management for empty-pane placeholder tabs looks correct.
src/handlers/editorFileTab.js Drag-to-pane transfer implemented with dragSessionId snapshot to prevent stale safety-net timeouts from corrupting a subsequent drag's state. contentEditable file-path drop now uses proper Range/Selection API. FLIP animation migrated from WAAPI to Motion. Logic is sound; moveDragToParent and commitPaneTransfer interact cleanly with editorManager.
src/lib/commands.js All new pane commands wired correctly; next-file and prev-file updated to use getPaneFiles for pane-scoped tab cycling. close-current-tab and edit-with null-guarded.
src/lib/keyBindings.js New pane keybindings added. Close-pane uses Ctrl-Alt-W (not Ctrl-Shift-W as in earlier drafts), avoiding the browser close-window conflict flagged in a previous review thread.
src/lib/openFile.js paneId option propagated through all file-type branches (text, video, image, audio). Already-open file is moved to the target pane when paneId is specified, with a correct fallback to makeActive when pane is missing.
src/styles/codemirror.scss New pane layout styles: split handles, flex layout for pane root, per-pane tab bars with top/bottom position variants. Pane resize cursor feedback added via body class. Looks complete.
src/cm/editorUtils.ts Adds getDocText utility for efficient large-document text extraction; replaces all direct doc.toString() calls throughout the codebase.

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()
Loading
%%{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()
Loading

Reviews (19): Last reviewed commit: "fix: address multi-pane review concerns ..." | Re-trigger Greptile

Comment thread src/lib/editorFile.js Outdated
Comment thread src/lib/editorManager.js
Comment thread src/lib/keyBindings.js
@UnschooledGamer UnschooledGamer added the area:editor Feedback, improvements related to the editor (code editing, editor iteration, formatting, etc) label Jun 29, 2026
@bajrangCoder

This comment was marked as outdated.

@bajrangCoder

This comment was marked as outdated.

@bajrangCoder

This comment was marked as duplicate.

@bajrangCoder

This comment was marked as outdated.

Comment thread src/lib/editorManager.js
@bajrangCoder

This comment was marked as outdated.

@bajrangCoder

This comment was marked as outdated.

@bajrangCoder

This comment was marked as outdated.

@bajrangCoder

This comment was marked as outdated.

@bajrangCoder

This comment was marked as outdated.

Comment thread src/handlers/editorFileTab.js Outdated
@bajrangCoder

This comment was marked as outdated.

@RohitKushvaha01 RohitKushvaha01 added the CI: RUN ON-DEMAND PREVIEW RELEASES Triggers an on-demand preview build for this pull request via CI workflow. label Jul 1, 2026
@github-actions github-actions Bot removed the CI: RUN ON-DEMAND PREVIEW RELEASES Triggers an on-demand preview build for this pull request via CI workflow. label Jul 1, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment was marked as outdated.

@deadlyjack

Copy link
Copy Markdown
Member

@greptile

@deadlyjack deadlyjack force-pushed the feat/multi-pane-view branch from 187dad6 to 1c478aa Compare July 3, 2026 12:30
Comment thread src/lib/editorManager.js
@deadlyjack

Copy link
Copy Markdown
Member

@greptile_apps

@deadlyjack deadlyjack merged commit 5d6e175 into main Jul 4, 2026
13 checks passed
@github-project-automation github-project-automation Bot moved this from In progress to Done in The Code Board - Acode Jul 4, 2026
@deadlyjack deadlyjack deleted the feat/multi-pane-view branch July 4, 2026 18:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:editor Feedback, improvements related to the editor (code editing, editor iteration, formatting, etc) enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants