Draw the tab list as a webview, VS-style
A tree view row cannot be styled: no border, no spacing, and a long file name gets middle-ellipsized in a narrow strip — which on a real project left "ClientDogSurger...nionBehaviour.cs" and hid the project text entirely. Drawing the rows means controlling all of it. - A coloured left border per project instead of a tinted icon, so the file icon slot is free and the name gets the width. The border uses var(--vscode-verticalTabs-projectN): VS Code injects every contributed theme colour into a webview, so overrides in colorCustomizations still apply and nothing is hardcoded. - The name is split into stem and extension, and only the stem ellipsizes, so ".cs" survives on a long name in a narrow view. - Configurable row spacing and border width, a rule under the pinned block, a dirty dot that the close button replaces on hover, italics for preview and for tabs that cannot be focused. - Selection, arrow/Home/End/Enter/Delete keys, middle-click to close, and an HTML context menu, since contributes.menus does not reach webview rows. - Clicking a webview row posts nothing rather than asking for an open that would silently do nothing. Actions moved to actions.ts so the wiring, the view and the tests share one implementation; extension.ts is now just registration. The per-row commands are gone — rows act through webview messages — and the palette keeps close / closeOthers / togglePin acting on the active editor. Verified in a browser harness at side-bar width: all twelve project colours resolve, rows stay a consistent 24px, and click, pin, close, middle-click, keyboard and both context-menu variants post the right intents. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+24
-115
@@ -28,69 +28,41 @@
|
||||
{
|
||||
"id": "verticalTabs.tabs",
|
||||
"name": "Tabs",
|
||||
"type": "webview",
|
||||
"contextualTitle": "Tabs",
|
||||
"visibility": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
"viewsWelcome": [
|
||||
{
|
||||
"view": "verticalTabs.tabs",
|
||||
"contents": "No editors are open."
|
||||
}
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"command": "verticalTabs.open",
|
||||
"title": "Open Tab",
|
||||
"category": "Tabs"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.close",
|
||||
"title": "Close",
|
||||
"category": "Tabs",
|
||||
"icon": "$(close)"
|
||||
"title": "Close Active Tab",
|
||||
"category": "Tabs"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.closeOthers",
|
||||
"title": "Close Others",
|
||||
"title": "Close Other Tabs",
|
||||
"category": "Tabs"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.pin",
|
||||
"title": "Pin",
|
||||
"category": "Tabs",
|
||||
"icon": "$(pin)"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.unpin",
|
||||
"title": "Unpin",
|
||||
"category": "Tabs",
|
||||
"icon": "$(pinned)"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.copyPath",
|
||||
"title": "Copy Path",
|
||||
"category": "Tabs"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.revealInExplorer",
|
||||
"title": "Reveal in Explorer View",
|
||||
"command": "verticalTabs.togglePin",
|
||||
"title": "Pin or Unpin Active Tab",
|
||||
"category": "Tabs"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.setOrderOpen",
|
||||
"title": "Sort by Open Order",
|
||||
"title": "Sort Tabs by Open Order",
|
||||
"category": "Tabs"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.setOrderProject",
|
||||
"title": "Sort by Project",
|
||||
"title": "Sort Tabs by Project",
|
||||
"category": "Tabs"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.setOrderName",
|
||||
"title": "Sort by File Name",
|
||||
"title": "Sort Tabs by File Name",
|
||||
"category": "Tabs"
|
||||
}
|
||||
],
|
||||
@@ -111,83 +83,6 @@
|
||||
"when": "view == verticalTabs.tabs",
|
||||
"group": "1_order@3"
|
||||
}
|
||||
],
|
||||
"view/item/context": [
|
||||
{
|
||||
"command": "verticalTabs.pin",
|
||||
"when": "view == verticalTabs.tabs && viewItem =~ /pin:off/",
|
||||
"group": "inline@1"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.unpin",
|
||||
"when": "view == verticalTabs.tabs && viewItem =~ /pin:on/",
|
||||
"group": "inline@1"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.close",
|
||||
"when": "view == verticalTabs.tabs",
|
||||
"group": "inline@2"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.pin",
|
||||
"when": "view == verticalTabs.tabs && viewItem =~ /pin:off/",
|
||||
"group": "1_state@1"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.unpin",
|
||||
"when": "view == verticalTabs.tabs && viewItem =~ /pin:on/",
|
||||
"group": "1_state@1"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.close",
|
||||
"when": "view == verticalTabs.tabs",
|
||||
"group": "2_close@1"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.closeOthers",
|
||||
"when": "view == verticalTabs.tabs",
|
||||
"group": "2_close@2"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.copyPath",
|
||||
"when": "view == verticalTabs.tabs && viewItem =~ /file/",
|
||||
"group": "3_path@1"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.revealInExplorer",
|
||||
"when": "view == verticalTabs.tabs && viewItem =~ /file/",
|
||||
"group": "3_path@2"
|
||||
}
|
||||
],
|
||||
"commandPalette": [
|
||||
{
|
||||
"command": "verticalTabs.open",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.close",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.closeOthers",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.pin",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.unpin",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.copyPath",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "verticalTabs.revealInExplorer",
|
||||
"when": "false"
|
||||
}
|
||||
]
|
||||
},
|
||||
"configuration": {
|
||||
@@ -226,7 +121,7 @@
|
||||
"verticalTabs.colorByProject": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Colour each tab's icon by its containing project."
|
||||
"description": "Colour each row's left border by its containing project."
|
||||
},
|
||||
"verticalTabs.allGroups": {
|
||||
"type": "boolean",
|
||||
@@ -251,6 +146,20 @@
|
||||
"build.gradle"
|
||||
],
|
||||
"description": "File names or extensions that mark a project root. The nearest match above a file names its project."
|
||||
},
|
||||
"verticalTabs.rowSpacing": {
|
||||
"type": "number",
|
||||
"default": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 10,
|
||||
"description": "Pixels of vertical space between rows."
|
||||
},
|
||||
"verticalTabs.borderWidth": {
|
||||
"type": "number",
|
||||
"default": 3,
|
||||
"minimum": 0,
|
||||
"maximum": 8,
|
||||
"description": "Width in pixels of the project colour border on the left of each row."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user