Files
vs-code-vertical-tabs/package.json
T
maxandClaude Opus 5 2e9a43f78b Fix the pin toggle, stale selection, and project detection in Unity repos
Three problems visible on a real project:

- The inline pin button showed twice on every unpinned row: the `when`
  clauses matched /pinned/ and /unpinned/, and "unpinned" contains "pinned".
  Context values now use unambiguous `pin:on` / `pin:off` tokens, and both
  commands call one togglePin — the pair exists only so the button's icon can
  reflect the current state.
- The list selected the tab you just left. followActiveTab read `isActive`
  from the entry snapshot, and after a refresh the tree has not necessarily
  asked for children yet, so it matched against the previous build. It now
  rebuilds the list and compares against the live active tab.
- Every file in a Unity repo resolved to an arbitrary project. Unity generates
  one .csproj per assembly into the repo root, and the walk took whichever
  readDirectory happened to return first. Matches are now sorted, a project
  file named after its directory wins, and .asmdef — which lives in the
  assembly's own directory and is what actually defines a Unity assembly — is
  a default marker, so it is found before reaching the root.

Palette widened from 8 to 12 hues, since a hash-assigned colour collides more
often than it looks like it should.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 18:24:36 +02:00

393 lines
10 KiB
JSON

{
"name": "vertical-tabs",
"displayName": "Vertical Tabs",
"description": "Open editors as a flat vertical list, colour-coded by project, with pinning. For people who turn the tab bar off.",
"version": "0.1.0",
"publisher": "local",
"license": "MIT",
"engines": {
"vscode": "^1.85.0"
},
"categories": [
"Other"
],
"keywords": [
"tabs",
"vertical tabs",
"open editors",
"csharp",
"visual studio"
],
"activationEvents": [
"onStartupFinished"
],
"main": "./out/extension.js",
"contributes": {
"views": {
"explorer": [
{
"id": "verticalTabs.tabs",
"name": "Tabs",
"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)"
},
{
"command": "verticalTabs.closeOthers",
"title": "Close Others",
"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",
"category": "Tabs"
},
{
"command": "verticalTabs.setOrderOpen",
"title": "Sort by Open Order",
"category": "Tabs"
},
{
"command": "verticalTabs.setOrderProject",
"title": "Sort by Project",
"category": "Tabs"
},
{
"command": "verticalTabs.setOrderName",
"title": "Sort by File Name",
"category": "Tabs"
}
],
"menus": {
"view/title": [
{
"command": "verticalTabs.setOrderOpen",
"when": "view == verticalTabs.tabs",
"group": "1_order@1"
},
{
"command": "verticalTabs.setOrderProject",
"when": "view == verticalTabs.tabs",
"group": "1_order@2"
},
{
"command": "verticalTabs.setOrderName",
"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": {
"title": "Vertical Tabs",
"properties": {
"verticalTabs.order": {
"type": "string",
"enum": [
"open",
"project",
"name"
],
"enumDescriptions": [
"Keep the order the editors are open in, matching the tab bar.",
"Group by project, so the colours run in blocks.",
"Sort by file name."
],
"default": "open",
"description": "How the tab list is ordered. Pinned tabs always come first."
},
"verticalTabs.pinnedFirst": {
"type": "boolean",
"default": true,
"description": "List pinned tabs above the rest."
},
"verticalTabs.showProject": {
"type": "boolean",
"default": true,
"description": "Show the containing project name beside the file."
},
"verticalTabs.showDirectory": {
"type": "boolean",
"default": true,
"description": "Show the containing directory beside the file, for files with the same name."
},
"verticalTabs.colorByProject": {
"type": "boolean",
"default": true,
"description": "Colour each tab's icon by its containing project."
},
"verticalTabs.allGroups": {
"type": "boolean",
"default": true,
"description": "List the tabs of every editor group. When off, only the active group is listed."
},
"verticalTabs.projectFiles": {
"type": "array",
"items": {
"type": "string"
},
"default": [
".asmdef",
".csproj",
".fsproj",
".vbproj",
"package.json",
"Cargo.toml",
"go.mod",
"pyproject.toml",
"pom.xml",
"build.gradle"
],
"description": "File names or extensions that mark a project root. The nearest match above a file names its project."
}
}
},
"colors": [
{
"id": "verticalTabs.project1",
"description": "Project colour 1.",
"defaults": {
"dark": "#4ec9b0",
"light": "#227d68",
"highContrast": "#4ec9b0"
}
},
{
"id": "verticalTabs.project2",
"description": "Project colour 2.",
"defaults": {
"dark": "#dcdcaa",
"light": "#7a6e17",
"highContrast": "#dcdcaa"
}
},
{
"id": "verticalTabs.project3",
"description": "Project colour 3.",
"defaults": {
"dark": "#9cdcfe",
"light": "#0b5f92",
"highContrast": "#9cdcfe"
}
},
{
"id": "verticalTabs.project4",
"description": "Project colour 4.",
"defaults": {
"dark": "#c586c0",
"light": "#8b338a",
"highContrast": "#c586c0"
}
},
{
"id": "verticalTabs.project5",
"description": "Project colour 5.",
"defaults": {
"dark": "#ce9178",
"light": "#a3441f",
"highContrast": "#ce9178"
}
},
{
"id": "verticalTabs.project6",
"description": "Project colour 6.",
"defaults": {
"dark": "#b5cea8",
"light": "#3c7a2e",
"highContrast": "#b5cea8"
}
},
{
"id": "verticalTabs.project7",
"description": "Project colour 7.",
"defaults": {
"dark": "#569cd6",
"light": "#1d4f91",
"highContrast": "#569cd6"
}
},
{
"id": "verticalTabs.project8",
"description": "Project colour 8.",
"defaults": {
"dark": "#d7ba7d",
"light": "#8a6512",
"highContrast": "#d7ba7d"
}
},
{
"id": "verticalTabs.project9",
"description": "Project colour 9.",
"defaults": {
"dark": "#f28b82",
"light": "#b3261e",
"highContrast": "#f28b82"
}
},
{
"id": "verticalTabs.project10",
"description": "Project colour 10.",
"defaults": {
"dark": "#a5d6a7",
"light": "#2e7d32",
"highContrast": "#a5d6a7"
}
},
{
"id": "verticalTabs.project11",
"description": "Project colour 11.",
"defaults": {
"dark": "#b39ddb",
"light": "#5e35b1",
"highContrast": "#b39ddb"
}
},
{
"id": "verticalTabs.project12",
"description": "Project colour 12.",
"defaults": {
"dark": "#80cbc4",
"light": "#00695c",
"highContrast": "#80cbc4"
}
},
{
"id": "verticalTabs.noProject",
"description": "Colour for files that belong to no project.",
"defaults": {
"dark": "descriptionForeground",
"light": "descriptionForeground",
"highContrast": "descriptionForeground"
}
}
]
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"pretest": "npm run compile",
"test": "node ./out/test/runTest.js"
},
"devDependencies": {
"@types/mocha": "^10.0.6",
"@types/node": "^20.11.0",
"@types/vscode": "^1.85.0",
"@vscode/test-electron": "^2.4.1",
"mocha": "^10.4.0",
"typescript": "^5.4.0"
}
}