microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
162.74k stars 28.72k forks source link

Allow custom setting/control of workbench tab titles #43806

Closed DABH closed 3 months ago

DABH commented 6 years ago

Hi there,

In my project, I have files with quite long file names (beyond my control). This limits me to having 3-4 tabs show in my workbench at once. I would like to be able to rename these tabs, or control their label format myself, in order to have more condense tab titles and thus more easily navigate my tabs. This was roughly suggested by #21662 but was not really addressed by #12965 -- any of the options for workbench.editor.labelFormat still give me tab titles that are too long. Can workbench.editor.labelFormat be modified, for example, to optionally take a formatter lambda function we can provide? As just one example of a reasonable formatter one might write, it could be that you fix tab titles to 20 chars, and for long filenames you truncate and prepend with "...". Additionally, one might want to assign nickname/shorthand tab titles for commonly used files. Please pardon me if there is already a way to do this (would love to know how!), but if not, I'd sincerely appreciate considering this as a feature request.

Thanks!

danielo515 commented 5 years ago

It is a shame that is not possible to configure tab titles. It is also a shame that the configuration for tab titles are almost imposible to find if you don't know that they are called labels, incredibly hard to deduce.

stefcameron commented 5 years ago

Custom editor tab title formatting could be useful to solve this problem:

image

In a repo where the adopted pattern is the directory is the most meaningful name, and every directory contains an index.js and styles.css file, you end-up with this, regardless of any tab title-related settings I know of so far (including workbench.editor.labelFormat.

In this case, if (I say "if" since this ask only applies, for me, to this particular scenario, which is quite common out there) the file is some generic name like these, I'd want to replace the file name with the directory name, like {directoryName} so I'd get MyComponent with a JS-related icon instead of index.js, or similar instead of styles.css.

evdama commented 5 years ago

@stefcameron that's exactly it. Take a few patterns to structure bigger react applications for example https://hackernoon.com/fractal-a-react-app-structure-for-infinite-scale-4dab943092af https://medium.freecodecamp.org/scaling-your-redux-app-with-ducks-6115955638be

The directory is the meaningful name, not the file, as index.ts is the same in any directory. Also, I have a big 49 inch screen so I divide my vscode in 7 vertical regions next to each other (best thing I've done in years), each has one file, index.ts, but then of course a different one as they're in different directories.

At the moment you can set workbench.editor.labelFormat to e.g. medium so it shows you a portion of the path in the tab when you pull a second or third index.ts in the same vscode region. However, I want to see the path inside the tab even when I only have one index.ts per region in order to keep them apart i.e. which index.ts am I looking at... The only way I know how to do that atm is with "breadcrumbs.enabled": true but then I'd love to have it inside my tab even if I only have one index.ts per editor region.

As a matter of fact, after spending some time reading current and past issues, https://github.com/Microsoft/vscode/issues/47142 is exactly what I want.

...show differences on inactive tabs...

even if there's only one index.ts per editor region and thus only one tab in any of my seven opened regions next to each other. It would allow me to have a bunch of index.ts next to each other, and have eyes and mind move fast through my application and work effectively and joyfully.

stefcameron commented 5 years ago

@evdama 49in screen!? Impressive. 😄 Yes, I could see #47142 working for my issue as well. I'd still have index.js and styles.css everywhere, but I'd also see the folder name underneath -- perhaps that's the important detail, since with current settings, we can display the folder name after, but in my case, that information is quickly and completely lost, hidden behind other tabs (or I can't put more than like 3 or 4 tabs in a single editor, which isn't useful to me).

evdama commented 5 years ago

@pixmaster @stefcameron yeah, one week old 49WL95C-W connected to my macbook via USB-C :) Agreed, foldername underneath filename is what I think is visually very appealing and makes for a great workflow.

danielo515 commented 5 years ago

I also have a 49-inch ultra-widescreen... best thing I did too

Nick-Lucas commented 5 years ago

There is precedent for this (well, for more granular control) in the window.title option. It would be great to get an equivalent for tabs!

  // Controls the window title based on the active editor. Variables are substituted based on the context:`${activeEditorShort}`: the file name (e.g. myFile.txt).
  // - `${activeEditorMedium}`: the path of the file relative to the workspace folder (e.g. myFolder/myFileFolder/myFile.txt).
  // - `${activeEditorLong}`: the full path of the file (e.g. /Users/Development/myFolder/myFileFolder/myFile.txt).
  // - `${activeFolderShort}`: the name of the folder the file is contained in (e.g. myFileFolder).
  // - `${activeFolderMedium}`: the path of the folder the file is contained in, relative to the workspace folder (e.g. myFolder/myFileFolder).
  // - `${activeFolderLong}`: the full path of the folder the file is contained in (e.g. /Users/Development/myFolder/myFileFolder).
  // - `${folderName}`: name of the workspace folder the file is contained in (e.g. myFolder).
  // - `${folderPath}`: file path of the workspace folder the file is contained in (e.g. /Users/Development/myFolder).
  // - `${rootName}`: name of the workspace (e.g. myFolder or myWorkspace).
  // - `${rootPath}`: file path of the workspace (e.g. /Users/Development/myWorkspace).
  // - `${appName}`: e.g. VS Code.
  // - `${dirty}`: a dirty indicator if the active editor is dirty.
  // - `${separator}`: a conditional separator (" - ") that only shows when surrounded by variables with values or static text.
  "window.title": "${activeEditorShort}${separator}${rootName}",

workbench.editor.labelFormat does seem good enough for the vast majority of use cases though. I've got it set to "short" so I always see the current folder name.

dansteren commented 5 years ago

In the hopes that it helps someone else that finds themselves here, there is a setting for allowing tab to auto-shrink if there isn't enough room:

"workbench.editor.tabSizing": "shrink"

That was good enough for me.

Knightly-Spartan commented 5 years ago

Thanks @dansteren , that's exactly what I was looking for.

iansan5653 commented 5 years ago

+1 to @danielo515's note - the setting does not show up if you search for anything with tabs, you have to search for labels.

Also with regards to issue at hand - I'd love to see something like @Nick-Lucas' suggestion but allowing newlines and somehow also supporting tab subtitles (the lower contrast part).

lannyheidbreder-mc commented 4 years ago

I got here via #40386, and I would like to reiterate the request to hide file extensions, since the nice file type icons give the same information.

If possible, it would be nice to only hide the extension if a type-specific icon is already on the tab. If there's an extension that doesn't have its own specific icon, the extension would appear in that tab label, and the icon would disappear instead.

But that may be overkill, and merely the option to hide all extensions would be great.

tomByrer commented 4 years ago

it would be nice to only hide the extension if a type-specific icon is already on the tab

Any progress on this?

mehanix commented 4 years ago

it would be nice to only hide the extension if a type-specific icon is already on the tab

Any progress on this?

I'm trying to address this issue, will be putting up a PR which solves extension cropping in a few days. Then I'll look into porting the titlebar variable feature to tab labels.

mehanix commented 4 years ago

Okay, I implemented this so far in #102725, following the example of window.title:

With this, you can use variables to customize tab names. Please note that i've let tab labels unchanged so far.

I have the following questions:

Thank you!

stefcameron commented 4 years ago

@mehanix

Okay, I implemented this so far in #102725, following the example of window.title:

🎉 Thanks for taking this on!

I have the following questions:

  • I believe there should be a bit of a discussion as many of the possible variables of window.title don't make much sense (active editor, ssh, etc.). What options should we offer users when customizing their tab names?

The main reason why I was originally looking for tab name customization is to solve this problem where a project uses index.js files for every single component. So you end-up with dozens of useless "index.js" tabs open and can't tell them apart. What I was hoping for is a way to say that the tab name should be the directory name IIF the file name is "index.js".

Also note that tab labels don't help with this problem, as I explained here.

I'm not sure how this would work with the token syntax because of the conditional, and because it probably shouldn't hard-code "index.js" as the common name to check for (even though that's a pretty common pattern in the community).

Maybe it could be similar to how ${separator} works, since the value of the token is also configurable in the "Tab Title Separator" option you also captured in your screenshot.

We could have an ${alternateIf} token, which points to a "Tab Title Alternate" option, which gives you a way to set the conditional file name to match, and then a list of options which we could start as only "Directory name" for now, unless other folks can think of additional alternatives to name.

Another way to solve this issue would be to do something similar to what #47142 was proposing (and closed in favor of this issue). What if this feature worked with the tab labels feature and provided tokens like ${labelPlacementTop}, ${labelPlacementBottom}, ${labelPlacementOpposite}.

By default, if you set a label option (e.g. "short"), the label is displayed on the right (in a left-to-right language, I presume, and on the left in a r-to-l language). If you set ${labelPlacementOpposite} in the tab title format, then it goes on the opposite side (left for l-to-r, and right for r-to-l). And then you have ${labelPlacementTop} which puts it on top, and ${labelPlacementBottom} which puts it on the bottom.

Top and bottom options would probably solve my use case because I could set the label to "short" to show the directory name, and the placement to bottom, so that the dir name isn't cut off when I have many same-named tabs open like the screenshot I posted in my earliest comment.

But it would alway be displayed, which is different from my ${alternateIf} suggestion. At least it would be configurable in the workspace for that project alone where I know the index.js and styles.css patterns are being used.

  • Should this feature replace workbench.editor.labelFormat and allow you to customize both the tab name and the tab label?

Maybe that's where I'm going with my suggestions? I still think there's value in the Tab Label option we have today. I just don't like that it makes the tab title even longer because of where it gets displayed.

  • Should we also include some sort of syntax for truncating or is workbench.editor.tabSizing sufficient?

I think the existing option is sufficient.

mehanix commented 4 years ago

Thank you for the detailed response, @stefcameron!

Following your suggestions and what I think would make most sense, I propose the tab name system works in the following way:

I'm not sure whether it should be called a blacklist or something else, i'm open to suggestions. Maybe tabAlternateFilenames ?

In your use case, I would be able to do the following:

And get the desired results.

I believe this system would best accomodate as many use cases and programming languages/frameworks as possible which use the "folder is the most meaningful descriptor" naming pattern.

As for the tab label, i also believe it is best if we kept it and added the possiblity of changing where it is displayed on the tab. However, i will leave this to be treated in another PR and will not be dealing with it now.

Please let me know what you think about this possible solution to this issue.

darsain commented 4 years ago

Wouldn't it be more explicit, efficient, and provide more fine grained control to add just 1 option that specifies renaming map?

"workbench.editor.tabTitleOverrides": {
  "**/index.js": "${folderShort}"
}

vscode already suffers from a huge option fatigue. tabNameBlacklist and tabTitleAlternate would add 2 options to solve 1 problem, and in a pretty un-intuitive way since it's not obvious without further documentation that these two are intended to be used and work together. It'd be yet another case where people have to look up some stack overflow thread to figure out how to do, while something like tabTitleOverrides seems pretty straight forward.

Also, for more advanced cases where tab titles might depend on context, such as what other tabs are open at the moment, an API like this would be awesome:

function customTabTitle(currentTab: TabFilePath, openTabs: TabFilePath[]): TabTitle {}

so that userland has an option to customize this to their liking.

mehanix commented 4 years ago

Wouldn't it be more explicit, efficient, and provide more fine grained control to add just 1 option that specifies renaming map?

"workbench.editor.tabTitleOverrides": {
  "**/index.js": "${folderShort}"
}

@darsain

Yes, that's a great idea! I tried to solve this in a way that would take advantage of the UI elements already in place, however I agree this would be a much simpler fix and also allow for fine grained control. I imagine this would be configured by directly writing into settings.json, and to simply provide an edit in settings.json link for configuration.

I'll look into updating the PR. Thanks!

stefcameron commented 4 years ago

@mehanix @darsain I like where this is going! I think the glob mapping option would provide some nice flexibility for various scenarios, and it would also solve my use case.

mehanix commented 4 years ago

@stefcameron @darsain Okay, i implemented the following: (more details on the PR page #102725)

ezgif com-optimize

done

I believe that with this you can cover a lot of use cases (since the glob syntax is so powerful compared to a simple name match)

I would love to know what you think!

stefcameron commented 4 years ago

@mehanix What you've implemented as a solution looks great to me! I agree, it looks it would be quite a flexible way to solve a lot of related use cases. Love the fact you can also use constant strings in the names, not just the variables. Nice work, thank you! 😀

iansan5653 commented 4 years ago

This looks awesome! Can't wait to use for React:

{
  "**/components/*/*": "${folderShort} (${fileExtension})"
}

Which would yield "ComponentName (html)", "ComponentName (tsx)", etc.

DABH commented 4 years ago

Thank you so much @mehanix for taking this on so long after this issue was opened :)

I think that your proposed solution will solve many classes of problems; however, the specific type of issue I was having at the time (and still to some extent) is that I had a codebase where filenames were like

CompanyNameAVeryLongNameForMySourceFileGeneratorFunctorLambda.cpp

So even if you used some tokens like ${folderShort} or ${fileExtension}, you would still be stuck with this big unwieldy file name if you wanted to uniquely identify the tab.

So an example of what I wanted to do would be more along the lines of what I think (?) @darsain was getting at, e.g. give a lambda like

workbench.tab.tabTitleFormatter = (path) => { return path.filename.remove('CompanyName').substr(0, 10); };

to strip the "constants" in the filename and keep all tab titles no more than 10 characters (ok, this lambda is probably not the exact thing I'd want, but something like this).

Is it possible to have the option/configuration for this functionality take a lambda that returns a string or format string, rather than just having it take a format string directly? That would provide the most flexibility and would hopefully solve all problem types. Let me know your thoughts. Thank you again for taking this on!

Nick-Lucas commented 4 years ago

Perhaps that use case could be solved by supporting RegEx and capture groups alongside/instead of globbing?

So something like this

{
  ".*/components/.*/CompanyName(.*)": "\1"
}
DABH commented 4 years ago

I think it’s still easy to imagine transformations that are difficult to express as regex. Regex does probably capture a lot of the common transformations people want to do but a lambda may be simpler to write/read and will give full flexibility. You could have a combination of regex and lambda where the lambda is passed the file path plus whatever tokens are derived from the regex.

Globbing definitely seems useful; I guess for something to apply to all files you could just do “*” ? And what if a file matches multiple glob patterns, will multiple rules apply or just one? E.g. trim CompanyName, then if it’s a tsx file format as “TrimmedName (tsx)”? This is again behavior that could be done with lambdas that may be able to be done with other solutions too but just want to make sure this kind of thing is possible since it’s the most general solution.

mehanix commented 4 years ago

While i can see how regex could treat more cases, it is also a lot more complex and difficult to set up for users.

Globbing is already used in VS Code in a number of places, however, as far as i know, regex isn't used in any settings thus far. I think it would be a bit more consistent to keep this as-is for now, until we also get feedback on my current PR.

As for lambda functions, is anyone aware of a safe method to implement this? some sort of sanitizing function? To me, lambdas sound dangerously close to code injection, but then again - I'm not incredibly experienced and will be researching this in the next few days.

Nick-Lucas commented 4 years ago

mehanix: Globbing is already used in VS Code in a number of places

Yep, I agree this is an important precedent, I just don't see another way without introducing a lambda of some sort like @DABH is proposing

DABH: but a lambda may be simpler to write/read and will give full flexibility

Is this even possible or wise to do? Settings are stored in JSON after all, so you at least would have to provide the path to a JS file somewhere, but that might raise future security and performance concerns if arbitrary code can be executed from within a setting?

Edit: @mehanix your edit showed up just as I was hitting post on this. Yes my suspicion is that any arbitrary code execution would be rejected by anyone reviewing, but I have nothing but my own developer instincts to base that on.

DABH commented 4 years ago

@mehanix @Nick-Lucas Thanks for thinking this through. I agree that in the settings file one might be constrained to static expressions rather than specifying a (path to a) script.

So I wonder if there is any other way to have a lambda/script for this somewhere? I have not dug into the VS Code internals too much, but presumably there's some code that sets an icon for a tab based on filetype -- that sounds quite similar to some code that would set the tab title based on the filename. Maybe rather than an entry in settings.json, the lambda/script could live as a customizable VS Code plugin, since plugins run code? So for example, change VS Code so that tab titles are set via the "identity lambda" i.e.

workbench.tabs.tabTitleFormatter = (filename) => filename;

but then the plugin would be able to overwrite that property with a lambda you specify? Do you think something like that is possible, or have you seen any examples of any similarly-behaving plugins?

I guess there could be two complementary solutions, one just based on regexes/globs in the settings.json, and the other being some plugin with lambdas. Unless someone has a cleverer solution :)

stefcameron commented 4 years ago

I feel like a plugin is starting to get pretty heavy-handed to address this. Functions in JSON won't work, though, obviously. I don't have any clever ideas; I don't know VSCode internals enough.

I have to say, I like the idea of a RegEx map with matchers, though globs would still be way more useful than not having this feature at all. RegEx feels like a possible middle ground between globs with no matchers, and a lambda that requires module loading and potentially-unsafe/expensive code execution, or an entire plugin.

Nick-Lucas commented 4 years ago

Perhaps the best solution really is to provide the Glob implementation in VS Code because it's simple and easy to configure for perhaps 80% of uses, and then to expose this to VS Code Extensions, so that extensions from the community can handle the corner cases?

Given we're able to extend everything from icons to intellisense in VS Code, it seems plausible that language extensions might want to handle displayed filenames too? Additionally then someone could publish a real power-user extension with regex and lots of complex options, without having to weigh down the default settings with complexity.

DABH commented 4 years ago

Right that's what I'm thinking, if we can just make tab titles extensible then someone sometime can make an extension that allows arbitrary customization. I imagine doing that (making titles extensible) would only be a small change to VS Code? My question is whether it's possible to do that, to make it extensible so that someone could make an extension later. Idk the internals well enough sadly.

But yeah in the meantime the simpler settings/configuration options exposed by the proposed solution will still help a lot of folks I think.

mocanew commented 3 years ago

We would love this feature in our company. @bpasero would you mind giving @mehanix some feedback so that the PR would be merged? I'm sure you have a lot on your plate but we'd really appreciate if you'd have a look.

mocanew commented 3 years ago
  • shouldn't this be implemented in the getName method of the editor rather than being specific to tabs? what if I have tabs disabled but still want to control the title? and note that we show editor names in more places than just tabs, so it would need to be consistent

You're right, we didn't know that.

  • rather than allowing to use glob patterns to scope the setting to certain files, I would make the setting resource capable (see example here) and let the user define it per language type

I'm not sure what "resource capable" means, but making this setting affect a whole language is not specific enough. There are project structures that employ multiple naming conventions even withing the same language. Glob patterns are already used in other settings(files.exclude, search.exclude) and would enable users to make this setting as specific as they need it to be, while keeping it simple enough for non-experienced users(eg. **/*.js for matching the javascript language).

  • how does this work together with the existing workbench.editor.labelFormat setting that seems very similar? maybe that setting should optionally allow to define the value via template syntax?

It would be awesome to have workbench.editor.labelFormat use a template syntax, but we couldn't find a function that handles variables in a settings string. There is an open issue for such a function: #2809. The proposed setting TabTitleOverride overrides workbench.editor.labelFormat for the matching glob patterns. If we'd change how workbench.editor.labelFormat works instead of adding an override, the default behaviour(labels showing only when there are duplicate tab titles) couldn't be achived since the template function is not able to run custom logic.

@bpasero do you have a better idea than our TabTitleOverride? We'd like to iron out the settings before opening another PR.

tequilacat commented 3 years ago

Controlling tab names via extension API would make working with typescript components simpler. Same problem as described by the topic starter. I started learning Extension API just to make an extension showing shorter names like "ReportCardAction+" + type icon instead of report-card-action.component.ts. It seems the extension API does not allow that - or I just haven't looked hard enough?

Is there a way to program this even if there's no way to configure it via globbing/regex settings?

yhslai commented 2 years ago

Bumping this. I'm using VScode to edit scripts inside Houdini, of which filenames are generated and super long. One single tab could take half of my space!

image

tkdennis commented 2 years ago

Did this fall off the radar? Would love to be able to change tab names, color, border, etc!!

DABH commented 2 years ago

Good to see that this issue, which I opened almost 4 years ago to this day, is still getting interest from the community :) I still think this would be a valuable feature, but it looks like someone from the community is going to have to try and implement this themselves, rather than relying on anyone else to do so.

Glootie commented 2 years ago

I need this for VSCode and Azure Data Studio. Sometimes I need to leave adhoc SQL queries open for a few days to verify data for the business, but they get lost in the sauce of other queries that I'm using while context switching all day. I don't want to save every ephemeral tab I open just so I can organize them. Same goes for VSCode when I want to review a large JSON.

Craksy commented 2 years ago

Others already mentioned how this is an issue for languages that use a common filename for module entry points, like index.js, mod.rs, __init__.py etc..

One feature I would absolutely love, would be the ability to replace the file extension with the common part, and the file stem with the module name. So for a Rust project with geometry/mod.rs, data/mod.rs and utility/mod.rs, in my tab bar they would become geometry.mod, data.mod and utility.mod

Or even just the module name in a emphasized font. Being able to define your own naming rules using pattern matching, string formatting and context variables would let people implement it however they prefer.

Such a system could also be used for other features, like automatic filtering and sorting, or configuring certain file types to prefer the transient/temporary tab.

devslayertech commented 2 years ago

How to hide file extension in tab?

Version: 1.69.0-insider (user setup) Commit: 4c72dedb4ad283a569f83a7389468c3ae2c642c3 Date: 2022-06-20T05:17:02.003Z Electron: 18.3.3 Chromium: 100.0.4896.160 Node.js: 16.13.2 V8: 10.0.139.17-electron.0 OS: Windows_NT x64 10.0.22000

iDad5 commented 2 years ago

I'm late to the party, but it seems to be a long running one anyhow.. ;-)

I found this issue when looking for a way to to better work with a lot of index.html lies in a lot of sub-folders. My idea would have been to ask for an option to display the html - title in the tab. For other files I would like to have support for a simple comment in the first line(s) of the file like:

// @vstab-title: something

I do know that not all file types allow for comments but most we use do, so could this somehow be considered and additional feature. (Or: Setting it in the workspace setting on a per file basis - and being able to change it vie right-click on the tab would be a dream too....)

tvld commented 1 year ago

Right now default shows both an icon for the file type as well as the extension. That's a duplicate in a very valuable space. I like to hide the extension from the editor tab label ..)

oncet commented 1 year ago

Tab renaming would be really useful when using pinned tabs!

rbadapanda commented 1 year ago

Bumping the request.

I am wondering why the fix which satisfies 80% of cases discussed in this thread is not merged/shipped into vscode-insiders yet.

I checked the fix. It has some feedback. Can't it be released first and then incrementally polished in future versions ?

bsdelf commented 1 year ago

I guess if customize title is implemented, "show tab index in title" could also be addressed, see #86865, the issue has been closed due to insufficient votes before I see it, but I really like the feature, switching tabs by shortcuts like alt-1, alt-2, alt-3 is quite handy.

Luke-Callaghan23 commented 1 year ago

Bumping the request as well. Like others have said, there doesn't need to be full customization right away. If we could just have some way to handle tab titles in extensions, the extension community can take care of the rest. It really helps when you're working in an environment where there are super long file names, or files with similar names!

al6x commented 1 year ago

I still don't understand, how can I hide file extensions (only file extensions, the icon shall be shown) from editor tabs? Is that possible?

bobcat2085 commented 1 year ago

Alongside some of the other options presented, it would be nice to have the options to show the filename with the workspace top-level path in which it resides to the side, instead of just the parent folder.

MrDanielHarka commented 1 year ago

I really need to hide the file extensions, so only the icon and the file name is left.

tvld commented 1 year ago

Yeb, In my case this is the difference between one or two rows of tabs, when editing on my laptop.