feat: dynamic tabbed workspace with multi-file and multi-terminal support

Replaces the fixed 3-tab workspace (Editor/Diff/Terminal) with a VS Code-style
dynamic tab system. Users can now open multiple files, terminals, and diffs in
closeable tabs with type icons, modified indicators, and file deduplication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 14:33:47 +01:00
co-authored by Claude Opus 4.6
parent cd949e4d9c
commit a14ee82883
12 changed files with 623 additions and 376 deletions
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 36 KiB

+1 -8
View File
@@ -59,7 +59,7 @@ class TestWorkspacePanel:
panel = WorkspacePanel(workdir=tmp_path)
assert panel._workdir == tmp_path
assert panel.visible is False
assert panel.active_tab == "editor"
assert panel.get_active_tab_type() is None
assert panel.id == "panel-workspace"
def test_default_workdir(self):
@@ -109,13 +109,6 @@ class TestWorkspacePanel:
msg = WorkspacePanel.DiffRejected("test.py")
assert msg.file_path == "test.py"
def test_command_submitted_message(self):
"""Test CommandSubmitted message."""
from clide.widgets.panels.workspace import WorkspacePanel
msg = WorkspacePanel.CommandSubmitted("ls -la")
assert msg.command == "ls -la"
def test_close_requested_message(self):
"""Test CloseRequested message."""
from clide.widgets.panels.workspace import WorkspacePanel
+1 -9
View File
@@ -383,8 +383,7 @@ class TestTerminalPane:
pane = TerminalPane(cwd=tmp_path)
assert pane.cwd == tmp_path
assert pane._history == []
assert pane._history_index == 0
assert pane._terminal is None
def test_default_cwd(self):
"""Test default cwd is current directory."""
@@ -401,13 +400,6 @@ class TestTerminalPane:
pane._cwd = tmp_path
assert pane.cwd == tmp_path
def test_command_submitted_message(self):
"""Test CommandSubmitted message."""
from clide.widgets.components.terminal_pane import TerminalPane
msg = TerminalPane.CommandSubmitted("ls -la")
assert msg.command == "ls -la"
class TestProblemsView:
"""Tests for ProblemsView component."""