21

VS Code remembers the file tabs that are open in my Workspace from the last environment, and so if I close VS Code and re-open, I have the same files opened.

Over a day or two of work, I may switch between 2 or 3 different feature branches while my PR's are going through review.

Each feature branch is usually on a totally different area of the code base, which means, I will want to open different groups of files when working on each branch.

I wonder if there is a way to save snapshots of open tabs so that I can re-reopen in future.

A really nice flow would be to have those files open automatically whilst other files close when VS Code detects a branch change.

3
  • 1
    I think you need an extension for this. It can be done with a couple of extensions chained together - I'll add the answer soon. It is a little "bulky" but works quite well. Commented Jul 9, 2020 at 21:04
  • Thanks Mark, looking forward to a solution Commented Jul 9, 2020 at 22:42
  • related: How can I save/restore window layouts in VS Code? Commented Nov 22, 2023 at 21:04

4 Answers 4

14

UPDATE: As of April 2024 (v1.89) release, VS Code now support saving/restoring editors on branch switch, so if that is all you need, give it a go: https://code.visualstudio.com/updates/v1_89#_source-control


NOTE: The layout restoration is only supported on Insiders as vscode.getEditorLayout was introduced recently and should go to Stable on v1.77.0

What do you need to create an extension for it:

There are a few pieces you will need:

  • vscode.window.tabGroups.onDidChangeTabs to listen for tab changes so you are able to store the opened tabs.
  • vscode.commands.executeCommand to run built-in commands (vscode.getEditorLayout and vscode.setEditorLayout) so you can store and restore the tabs position (I did this based on viewColumn that can be found within the tab.group).
  • This one is a bit hacky but I've not found a way to open tabs without opening many text documents. For this you will need to use vscode.workspace.openTextDocument to create the document and vscode.workspace.showTextDocument so it appears as a tab on vscode.

The magic with this is once you are able to restore the editor layout, and you set viewColumn on vscode.workspace.showTextDocument the layout configuration should be restored as expected.

Couldn't generate a link pointing to each item, but overall details can be found here in VS Code API doc or in my extension source code:

If you don't want to create one, I've started working on something like this in 2019 for this same reason, hopefully this might also be useful for those that have this problem:

This is the extension: https://marketplace.visualstudio.com/items?itemName=marlom.keep-context

Here is a screen share of how it works:

enter image description here

It manages to store the layout position (Only on Insiders for now as pre-release, should be good to be released once vscode 1.77.0 comes out), files opened and git branch used.

Sign up to request clarification or add additional context in comments.

Comments

4
  1. Get a "snapshot" of currently opened files.
  2. Save this snapshot somewhere; make it easy to change.
  3. Use the snapshot to open all of its files; close all other files first.
  4. Be able to make multiple snapshots and call each one easily.

(1) is harder than you might think. There are a number of vscode issues about searching only within the currently opened files and the problem remains largely unsolved after a few years for this reason.

Demo: get the relative paths of all opened files (unfortunately the gif creation software did a poor job of capturing all the keystrokes used in all these demos) :

get relative paths of opened files demo

Holy crap, what just happened. One keybinding and they are collected and formatted in a specific way.

A number of things happened. The only way I know of to efficiently get a list of opened files (maybe true even in an extension) is through the "Open Editors" view. So we

(a) focus that Open Editors view,

(b) select the entire list, and fortunately there is a

(c) copyRelativeFilePath command (or copyPath for the full path) that will get them all in a list.

But the list initially looks like:

1.html
simple\\gulpfile.js
test1.txt

which isn't going to do us much good. But it is now on the ClipBoard and there is an extension, Replace Rules that is able to run the Clipboard content through a series of regex's (without modifying the Clipboard content either) and paste the result somewhere. So you will need that extension and a macro extension, here using multi-command to run all the steps. Here is the macro which goes into your settings.json:

  "multiCommand.commands": [

   {
      "command": "multiCommand.getOpenedEditorsForTaskOpenAll",
      "interval": 50,

      "sequence": [
        "workbench.files.action.focusOpenEditorsView",
        "list.selectAll",
        "copyRelativeFilePath",
        // "copyFilePath",
        "workbench.action.focusActiveEditorGroup",
        {
          "command": "replacerules.pasteAndReplace",
          "args": {
              "ruleName": "Prepare file list for task open"
          }
        },
        "editor.action.formatSelection",
        "cancelSelection",
        "deleteLeft"
      ]
    }
  ]

Here is the replacerules rule that is used in the macro:

"replacerules.rules": {

   "Prepare file list for task open": {
    "find": ["(\\\\)", "^(.+)$"],
    "replace": ["\\\\", "\"'$1'\","]
  }
}

It just modifies that bare file list into something we can use in a task. Here is a keybinding to run that macro (keybindings.json):

{
  "key": "ctrl+shift+i",
  "command": "extension.multiCommand.execute",
  "args": {
    "command": "multiCommand.getOpenedEditorsForTaskOpenAll"
  },
}

You should be able to test this already to see if it'll dump the formatted file list to wherever your cursor is in the current text editor.


One way to open up all these files at once is to put them into a task (in tasks.json):

{
  "label": "Open snapshot 1",
  "command": "code",
  "args": [

  ],
  "type": "shell",
  "problemMatcher": [],
  "dependsOrder": "sequence",
  "dependsOn": [ "close all editors" ]
},

{
  "label": "close all editors",
  "command": "${command:workbench.action.closeAllEditors}",
  "type": "shell",
  "problemMatcher": []
},

You see the task Open snapshot 1 is dependent on the close all editors task so that happens first. In the Open snapshot 1 the command is code to open all the arg files. Put your cursor in the args array and that is where the properly formatted list of files to open will be written by the macro. Demo:

demo of inserting opened files into a task

If you want to update that file list you can just select them and rerun the macro. And you can now set up as many Open snapshot <n> tasks as you want (with whatever labels you want to give them).

Now, to trigger the task we will use a keybinding as well:

  {
    "key": "alt+s 1",
    "command": "workbench.action.tasks.runTask",
    "args": "Open snapshot 1"
  },
  {
    "key": "alt+s 2",
    "command": "workbench.action.tasks.runTask",
    "args": "Open snapshot 2"
  },

etc. As noted earlier, running this task will first run the dependent task which closes all currently opened files. If you just wanted to open a batch of files you frequently use without closing the others, just remove the "dependsOn": [ "close all editors" ] option.

Here is a final demo of the task closing the open files and opening the snapshot files (I just changed the file list above a little to make it look different).

demo of tasks opening and closing files


Two things to remember:

(1) the Editor > Open Editors: Visible setting must be enable with a number high enough to show all your opened files. The Open Editors can be hidden so you don't have to look at it all the time if you don't want, but it will be opened automatically by the macro - that can't be avoided. You can see it opening in the demos. It can be hidden by its context menu.

(2) The terminal is used, so you see it opening.


It seems like a lot of set-up but the operation is actually pretty simple - just a couple of keybindings to remember.

4 Comments

Wow, mark that is extensive, love it, I will look into your process and see how it goes for me.
I tried it and it works! Nice use of multiple features. It involves too many steps but I really needed it. One caveat: if you have editors open in multiple panes (e.g. split view), it doesn't preserve that and opens everything in one pane.
@nimcap There is a brand-new tabs api which will make this much better. But it is still a little lacking in features, but getting closer.
All that I really needed was the tasks.json part (to occationally open a static set of files), but this answer helped me figure that out.
2

Try an extension called File Group.
My searching reveled that a lot of people are looking for this option but vsCode does not seem to have any good way to do it. This extension lets you list out the files with full path and associate them to a key shortcut.

Three files below will load by hitting ctrl-alt-1 if you add this to youProject.code-workspace:

"1": {
    "files": [
        "C:\\temp\\file1.txt",
        "C:\\svn\\foo.txt",
        "C:\inetpub\wwwroot\iisstart.htm"
        ]
    }

(It is a pain to set up if you are new to vsCode, hopefully it gets developed further.)

Comments

1

Though the question is not specifically about associating open editor tabs to git branches, it was stated as the primary motivation, so I'll like to tackle the question focusing on specifically that angle.

See Git: Preserve open files list when switching branches #35307. A draft of this feature is now in VS Code Insiders and will be release to stable in v1.89. You can enable the feature using the scm.workingSets.enabled setting.


Design annoyances

There are actual cases when you might not want this to happen.

For one thing, git will not automatically stage unstaged changes before you switch to another branch. It will just keep the unstaged changes as-is in the working tree, or issue a warning and abort the operation.

On top of that, VS Code's edit buffers are a level "higher" than the working tree. Changes in the editor do not get persisted to the filesystem until you actually invoke the "save" action.

Given that, I think it would be more generally disruptive and unexpected if VS Code were to automatically close all open editors upon a branch-switch / commit-checkout. And it would be an even bigger pain if one of the editors had unsaved changes- then the user would have to be prompted for whether or not to save those changes, and there could be multiple files with unsaved changes.

Vanilla workarounds / solutions

If you want to have what you're looking for in Vanilla VS Code (pre 1.89), you can also try git worktrees (see also https://stackoverflow.com/a/75417907/11107541), which is just multiple working trees for the same repo (shared .git folder). The nice thing about this is that (as far as I know,) it's immune to the problems I stated above.

Extensions

I have no affiliation with the following extensions and am just suggesting a couple I found from searching the extension marketplace. This list is not exhaustive and you should do your own search as well (Ex. by putting @popular git branch tabs in the Extensions View searchbar).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.