Skip to content

feat: split editor pane#632

Merged
tomlin7 merged 22 commits into
mainfrom
feat/split-editor
Jul 18, 2026
Merged

feat: split editor pane#632
tomlin7 merged 22 commits into
mainfrom
feat/split-editor

Conversation

@tomlin7

@tomlin7 tomlin7 commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Implements the split editor feature (Ctrl+\ to toggle). EditorsManager now uses a PanedWindow with EditorPane instances instead of placing editors directly. Each pane shows one editor at a time, and clicking a tab routes the editor to the currently active pane.

- Add EditorPane class that holds one editor at a time with its own placeholder
- Replace direct editor grid placement in EditorsManager with a PanedWindow containing EditorPanes
- Update Tab.select/deselect to route editor placement through the active pane
- Add Split Editor entry to editors bar menu for discoverability
- Toggle split via Ctrl+\ (keybinding already existed)
@vercel

vercel Bot commented Jul 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
biscuit Ready Ready Preview, Comment Jul 17, 2026 7:07pm

tomlin7 added 12 commits July 16, 2026 01:58
…dWindow reparenting

pane.master is set at widget creation and never changes, but after a split
the pane gets reparented into a nested PanedWindow. This caused a crash
('is not in list') on subsequent splits and close_pane calls.

Added _find_parent_pw / _find_parent_pw_recursive to walk the PanedWindow
tree and find the actual parent that contains the given EditorPane.
config.py still referenced self.editorsmanager.editorsbar.show_breadcrumbs()
which no longer exists. Breadcrumbs are now per-pane; iterate all panes.
pip is not available in uv-managed environments, causing a crash on startup.
Also added FileNotFoundError to the exception handler.
…ttons param

- Remove self.editorsbar and self.breadcrumbs from GUIManager (now per-pane)
- Rename create_buttons(editorsbar) -> create_buttons(parent) in BaseEditor
- Add split_editor_vertical command
- change_tab_forward/back now route through editorsmanager instead of editorsbar
- open_editors uses editorsmanager.switch_tabs and close_editor_by_path directly
Each EditorPane now owns its own tab bar (with tabs + right-aligned action
buttons) and breadcrumbs. Tab bar auto-hides when empty. Pane auto-closes
when the last tab is closed (if more than one pane exists).

EditorsBar is stripped of tab management — it retains only action-container
compatibility for legacy callers. Tab's master is now EditorPane instead
of EditorsBar.

Adds 'Split Editor Vertical' and 'Close Split' menu entries.
_find_parent_pw only recursed into PanedWindow children of root_pw,
missing the case where the target EditorPane is a direct child of
root_pw (initial unsplit state). This caused _split_pane to silently
return without doing anything.
nametowidget identity checks (child is pane) can fail in edge cases
due to Tkinter proxy object behavior. Switch to iterating all nested
PanedWindows and comparing pane path strings directly with panes(),
which is deterministic and sidesteps the identity issue.
First check if pane_path is a direct child of root_pw via string comparison,
then fall back to recursion with both identity (is) and string (==) checks.
This handles both the initial unsplit state and deeply nested splits.
On this system (tkinterDnD), PanedWindow.panes() returns widget objects
instead of path strings. All string-based comparisons (in, .index, ==)
silently failed. Switch to identity (is) and isinstance checks throughout.
Key changes:
- Replace reparenting with destroy-and-recreate for nested splits
- Editors survive pane destruction (mastered by EditorsManager)
- Every EditorPane is created fresh with its final parent
- No widget path changes, no grid corruption, no stale sashes
- Flat split unchanged (no reparenting needed)

Adds blog/split-editor-journey.md documenting the journey.
- Each pane's plus/split buttons now operate on that pane (not active_pane)
- Split preserves original editor's exists and showpath attributes
  so untitled editors don't get breadcrumbs on their split sibling
- Add new_like() to BaseEditor/Editor for cloning editors during split
- Non-Editor editors (e.g. BrowserEditor) use reparenting instead of destroy-and-recreate, preserving WebView2 native handles
- Sibling creation falls back to new_like() when no file path exists
- Both flat and nested paths support new_like()
@tomlin7
tomlin7 merged commit 3a0c889 into main Jul 18, 2026
8 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant