feat(tabs): a tab that shares a file name says which folder it is from - #728
Merged
Conversation
Two tabs on .claude/skills/alpha/SKILL.md and .claude/skills/beta/SKILL.md both read SKILL.md, and the tab strip is the one surface where the path is not already on screen. Each now carries the containing folder, dimmed, and only while the name is actually ambiguous. The containing folder alone is not always an answer: docs/api/README.md and packages/api/README.md would both read api. A suffix that is still shared grows by one more folder, and only for the tabs that share it, so a sibling that was already unambiguous keeps its one-folder suffix. Whether a name is ambiguous is a fact about the set of open tabs, not about any one of them, so the suffixes are derived in TabList rather than written into Tab.title -- which also feeds the window title, the close dialog and untitled numbering. Behind Settings > Appearance > Show Folder for Duplicate Names, on by default and inactive while Show Tabs is off, since the strip it annotates is not on screen then. ref #727
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
Two tabs open on
.claude/skills/alpha/SKILL.mdand.claude/skills/beta/SKILL.mdboth read SKILL.md, and the tab strip is the one surface where the path is not already on screen. Each tab now carries the containing folder after the file name, dimmed, and only while the name is actually ambiguous.Reported by @SamHasler in #727, with VS Code named as the app that gets it right.
Closes #727
Mechanism
Nothing was wrong; there was no disambiguation at all.
tab.titleis the basename, assigned at the five places a tab acquires a path (openFile,claimPath, Save As, rename, session restore), and the tab strip renders it verbatim.Two shapes were on the table:
shorten()invs/base/common/labels.ts) picks the shortest distinguishing segments from anywhere in the path and elides the rest with…, giving…/skills/alpha. It reads as a path fragment.This is the second, with one correction. The containing folder alone is not always an answer:
docs/api/README.mdandpackages/api/README.mdwould both readapi, which is the original defect with a longer label. So a suffix that is still shared grows by one more folder — and only for the tabs that share it, so a sibling that was already unambiguous keeps its one-folder suffix rather than growing in sympathy.Termination is not a loop bound:
TabManager.claimPathmakes a file path exclusive to one tab, so two paths cannot share every folder. Thegrowableguard is there for the file at a filesystem root, which has no folder to give.Whether a name is ambiguous is a fact about the set of open tabs, not about any one of them, so the suffixes are
$derivedinTabListand passed down as a prop. Writing them intotab.titlewould have been the shorter diff and the wrong one: that field also feeds the window title, the per-tab close dialog,nextUntitledTitle's numbering, and the session snapshot.The setting is
editor.showFolderForDuplicateNames, on by default — the suffix is silent until two tabs collide, so an existing install sees no change until the moment the strip stops answering the question it exists to answer.Scope
Per window, not per app. VS Code disambiguates within one tab group and not across groups, and the analogue here is one window's strip. A suffix earned by a tab in another window would be noise: the reader cannot see that tab.
The setting row is gated on Show Tabs,
class:inactiveplusdisabled, and sits directly below it. With the strip hidden the switch does nothing at all, which is the exact failuresettingsSemantics.test.tsdocuments three prior instances of. Following that file's rule, the prerequisite is the row above.Tab width is untouched.
.tabis stillmax-width: 200px, so a suffix takes room from the file name. The existing hover marquee and the full-pathtitletooltip already cover an overflowing label, and widening tabs is a change to the strip's layout that this issue did not ask for. IfREADME.md packages/apiturns out to be too tight in practice, that is a one-line follow-up.Case. Two files whose names differ only in case get no suffix. On Windows they cannot both be open (
claimPathis exclusive on the path), and on a case-sensitive filesystem the names already read differently.Tests
scripts/duplicateTabNames.test.ts, seven behaviour tests against the real module — one folder, growth on a shared suffix, the sibling that does not grow, a Windows path, the file at the root, and the non-files (untitled buffers, the home sentinel).Revert the growth loop to a plain "containing folder, once" and keep the tests: three go red — the two that assert growth, plus the Windows one, whose fixture is a two-level collision. The other four stay green either way, which is right: they pin behaviour that a JetBrains-shaped implementation also has.
The render itself has no test. Mounting
Tab.sveltein jsdom would earn "the prop is interpolated", which is weaker than whatnpm run checkalready gives, andAGENTS.mdsays not to migrate component tests for exactly that reason.Verification
Ran on macOS 15 / arm64 as a release bundle, with five files laid out to hit each branch:
skills/alpha|beta/SKILL.mdfor the one-folder case, anddocs/api+packages/api+guide/README.mdfor growth —guidestays at one folder while the other two go to two. The suffix renders as intended and the settings row greys out with Show Tabs off.Not verified: Windows and Linux. The separator choice (
\when the path is spelled with one) is reasoned from the path string, not observed — on Windows the folder suffix should readdocs\api, and nothing in this branch has run there. The 26 locale strings past English and Simplified Chinese are unreviewed by a speaker.