Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore previously closed session's state (Buffer contents) #961

Closed
zadjii-msft opened this issue May 23, 2019 · 56 comments · Fixed by #16598
Closed

Restore previously closed session's state (Buffer contents) #961

zadjii-msft opened this issue May 23, 2019 · 56 comments · Fixed by #16598
Assignees
Labels
Area-User Interface Issues pertaining to the user interface of the Console or Terminal In-PR This issue has a related PR Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Needs-Tag-Fix Doesn't match tag requirements Product-Terminal The new Windows Terminal.

Comments

@zadjii-msft
Copy link
Member

Lets talk about restoring the state of the terminal here.

This could arise in two scenarios I'm thinking of:

  1. Restoring the state of a previously closed terminal session (i.e. the app was closed due to a restart, and you launch it again)
  2. Restoring from a previously closed tab in this session (i.e. you've closed a tab, but not the app.)

1 is certainly harder than 2.

Restoring the buffer contents wouldn't be impossible, but restoring the actual state of the running executable might be impossible. IIRC @malxau has a long email from his work on yori that is relevant to this discussion.

We could certainly restore the buffer contents from file, then display some sort of message saying [Restored from previous session]. That's not that hard.

@zadjii-msft zadjii-msft added Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Area-User Interface Issues pertaining to the user interface of the Console or Terminal Product-Terminal The new Windows Terminal. labels May 23, 2019
@zadjii-msft zadjii-msft added this to the Terminal Backlog milestone May 23, 2019
@ghost ghost added the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label May 23, 2019
@DHowett-MSFT DHowett-MSFT removed the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label May 23, 2019
@binarycrusader
Copy link
Member

I think there are possible security considerations with this. With that in mind, making restoring previous output seems an opt-in rather than opt-out feature seems prudent. On Windows of course if the user's profile is BitLocker-protected, maybe it's less of an issue, but regardless worth considering.

I did enjoy this feature of Terminal.app for the few years I used a mac some time ago.

@malxau
Copy link
Contributor

malxau commented May 24, 2019

Firstly, welcome to github and the terminal project, @BEAClerbois!

Just adding to the record some of the information @zadjii-msft is referring to, I tried to implement save/restore of state as part of Yori, which is a CMD-like shell. This was opt-in due to the security/privacy issue that @binarycrusader mentioned, and is enabled with an environment variable. See http://www.malsmith.net/yori/guide/#env_yoriautorestart .

In that context, save/restore meant saving both terminal state as well as shell state. Terminal state includes things like the size and position of the window, its contents, colors, and fonts.

Shell state includes things like current directory, environment, and in this case, aliases and command history.

But the real challenge is how to reason about multi-process relationships. One example was given previously: suppose the user launches a CMD window, and within that launches Powershell. Even if both
CMD and Powershell were capable of saving their state, the restoration process needs to include a) terminal state; b) a CMD process with its state; c) a Powershell process with its state; d) somehow get the CMD process to wait for the Powershell process to terminate. (d) is very unnatural because on the running system the parent can only reason about the child via a handle or PID, and here neither are known until the child is running. It's possible that I'm not thinking creatively enough, but this sounds a bit like a cyclic dependency, because on the one hand the parent process should be fully restored before the child can accept user input and terminate itself, but on the other hand, the parent process can't really know what to wait for until the child is present.

A clearer example of the same effect would be opening CMD and within that executing "vim foo". The terminal will know about the existence of the vim process, but the meaning of "foo" depends on the current directory that vim was launched from, and that information has to come either from vim or from the parent process, and CMD needs to wait for vim. Recovering things accurately would require coordination from three different programs.

When the multi-process relationship is outside the console, things get messier still. The specific case that affected Yori users which I couldn't see how to handle is the Virtual Filesystem for Git agent, because launching a shell with a correct current directory does not mean the user can interact with the files there unless the agent is running. But the agent can be launched via any mechanism which may be completely unrelated to the console, so there's no knowledge indicating it must be restored. In the context of restoring a recently closed tab this may not be so problematic.

Obviously this is in addition to restoring state which depends on OS configuration which may not be present - having network shares, authentication, a particular IP address, a USB device attached - things that might change between attempting a save and a restore.

@zadjii-msft
Copy link
Member Author

Thanks @malxau for the great explanation. As we can see, restoring shell state is a neigh-impossible thing to do totally correct (and why I wanted this to have it's own thread separate from #766).

However buffer content is not impossible to restore. Lets make it opt-in, in addition to opting-in to general window state restore being tracked in #766.

@malxau
Copy link
Contributor

malxau commented May 24, 2019

After sleeping on it, I started remembering even nastier cases about process relationships. Consider pipes: "type foo | more" means saving the state of the "type" command and the "more" command and somehow recreating the pipe. This looks like another cyclic dependency: pipes are normally created by the parent, which carefully hands one end to the child and closes it; but here we need some kind of resumable identifier that describes a pipe between two processes and can recreate that. The "type" command, in turn, needs to know where it was within its source stream to resume from; in this example with a source file that's at least possible.

When the source stream is dynamic, finding that point becomes somewhat meaningless. Suppose the command was "tasklist | more" - where should tasklist resume from? Its source stream has completely changed.

Agree with "neigh-impossible", and this feels like something where if we tried to solve it, it would end up being Windows-specific and a large part of the terminal effort is better interoperability with other platforms. It seems to me like if there was a push to solve this on other platforms we can contribute to the conversation, but going it alone doesn't seem like the right thing to do. Users would be left with an experience that only works for some programs, some of the time.

@jamieghassibi
Copy link

jamieghassibi commented Apr 4, 2020

@malxau While all the complications make saving state difficult, I don't feel simply saving the tabs, tab names, panes, and their respective directories should be relatively simple.

Having different session setups could also be possible as an argument to wt, for example I could type win+r wt session foo to open the foo session. Saving could be accomplished via wt session -s foo.

Thinking about the above suggestion, it may be easier to add a section to the options JSON that let's users describe a session layout.

@malxau
Copy link
Contributor

malxau commented Apr 4, 2020

@jamieghassibi How would the terminal obtain the directory that is active within the shell processes?

I can see how this would work if the session is defined in config, but to capture the current state into the config still sounds like it's depending on capturing state from the terminal and from all of the command line processes executing within it.

@Chris-Dickerson
Copy link

I would like to see allowing a definition of tabs to be opened on startup (much like other Windows terminal applications).

As far as restoring state, I accept what happens in the terminal to be volatile. If I want the output, I capture it with the commands executed.

@nmoinvaz
Copy link

It would be great if the Terminal could remember:

  • List of tabs previously open and their current working directory
  • List of commands previously ran in each tab (maybe last 10-20)

The actual contents of the buffer are not as important. When I restart my computer or accidentally close the Terminal app, I just want to get back to where I was as quickly as possible.

@zadjii-msft
Copy link
Member Author

@nmoinvaz So those two might be generically impossible for the Terminal to solve.

@lukaseder
Copy link

lukaseder commented Jul 1, 2020

To me, this is just like how browsers allow for reopening tabs. In fact, a terminal kinda is a browser. And while restoring the session might not be easy, restoring the path (and things like the tab title: https://docs.microsoft.com/en-us/windows/terminal/tutorials/tab-title) definitely is (things are never as easy as we users think) seems to be. For my use-cases, that would already be enough

@gerhard4
Copy link

I'm surprised that nobody has mentioned that yet, but iTerm2 for macOS does pretty much what one would expect from such a feature. It's one of the very few things that I miss from the Mac on Windows. The GitHub project: https://github.com/gnachman/iTerm2

@111andre111
Copy link

Now I am not really an OS specialist, but I think iTerm2 is not really a good example as it goes back to macOS which basically only has to hold sessions that go back either to zsh or bash. I think Terminal has to fill much more gaps because under a Windows there is an extremely broad spectrum of terminal sessions possible starting from MinGW sessions, Cygwin sessions, bash sessions, Powershell sessions, CMD sessions (which even don't really have a state and you would need to work around lots of things if it's even possible to save the CMD buffer separately). So I think that request is a whole other beast than what iTerm2 has to fulfill.

For Windows you need to compare to a completely other set of shells like e.g. Babun which has been discontinued, cmder or MobaXterm. Lots of these shells base on the initial work that has been done with ConEmu. If you look to all these shell's issue collections you will find out that there have been happening lots of struggles around lots of issues. And the chorus is that some of these shells specialized only on a possible subset of possible shells like e.g. Cygwin sessions or SSH sessions....

Please correct me if I am wrong.

@gerhard4
Copy link

I know that I don't know enough -- by a long shot -- to correct you or to tell you that you're wrong :)

However, sometimes perfect can be the enemy of good (or better). Tools that have to work with a multitude of environments sometimes support features only for a subset of supported environments. If Terraform, for example, only supported features that are supported by all cloud environments it supports, it would not be very useful. Sometimes it makes sense to support features only for a subset of supported environments. In this case, if it can be done, say, for Bash and PowerShell, that would be a huge win for many if not most (or even an overwhelming majority of) users.

(FWIW, iTerm2 supports tcsh, zsh, bash, and fish.)

@christophe-calmejane
Copy link

Agreed!
Only support for bash/powershell is enough for me (for now).
It really is a pain when windows decides to reboot by itself (crash, update, ...) and I loose the 10 shells I have opened because I work on many projects at the same time.
On the other hand, when my mac reboots, I always get back right where I was.

Please consider partial support.

@mmseng
Copy link

mmseng commented Oct 22, 2023

Just expressing my use case: As an IT Pro, I frequently have 8-10 PowerShell 5.1 or 7+ tabs open in terminal. I don't "pre-plan" what's going to happen in these tabs, and I don't waste time customizing each tab with titles or colors. I just open them as I need them to work on different tasks/projects in parallel. So "losing" the content of these tabs when I come back to my PC when either the PC has restarted for Windows updates, or Terminal has mysteriously restarted (I assume for a forced update of some sort?) is very disruptive.

All of this would be solved (for me personally) if only the buffer contents would be restored, as I could easily look and see what I was doing last in each tab and what the most recent command output was. To a lesser degree, restoring the tab's "local" command history would suffice as well, as I could then just use the up arrow to see what the last command was in any given tab.

Currently when these Terminal restarts happen, the number, position, and client of each tab are successfully restored, but that is not enough to get me back on track. Ostensibly I could manually customize the title of every tab just in case this happens, which might help a little, but even then it wouldn't tell me exactly what I was doing in that tab or what state I had left that tab's task in. Plus, during a work day I will have opened and closed dozens (maybe hundreds) of tabs, so customizing tabs just in case would be a huge waste of time. Restoration of the buffer/command history is really what's needed.

@gerhard4
Copy link

Re mmseng's comment:

Restoration of the buffer/command history is really what's needed.

For me, it's more the buffer than the command history. The buffer contains the output and the commands. If the output of a command changed over time, rerunning the commands might not help getting the information back about what happened.

Lateral thought: an on-disk rotating buffer with a maximum lifetime (24h? configurable?) on disk for every tab that contains everything visible on screen would be helpful, too, and would give me most of what the feature of this issue could give me.

@mmseng
Copy link

mmseng commented Oct 23, 2023

it's more the buffer than the command history

Wholeheartedly agreed. The buffer is far more important; I would even go so far as to call it precious.

At the risk of repeating drama from above, from an outside perspective, either item seems relatively simple (compared to something like preservation of state), as both buffer and command history are mostly just plain text and the rendering thereof. The command history implementation already even lends itself to this purpose, since you can technically manually edit it.

I know it's always way more complicated than it seems; I only mentioned the above because, as much as I'd like to see this implemented for the good of all, I would personally be willing to implement a custom solution that, at the very least, dumped buffer history to a file along with some sort of identifier as to the tab it belonged to (e.g. name the file after the tab title and date), if it allowed me to recover my work in these instances. Of course, I would have no idea how to develop such a hack myself, and the logic for when to dump that data does not immediately come to mind.

@plutonium-239
Copy link

Is this being worked on?
I see that PR #8771 was opened in 2021 but then it got closed without a reason? (last comment was just a discussion on changes)

@zadjii-msft
Copy link
Member Author

Yep, I believe @lhecker's been working on this for a bit now.

#8771 was more specifically a PR to implement #766. This issue is more specifically "restore buffer contents", while #766 was more generally "restore various elements of the Terminal's state".

#8771 ended up resurrected as #10513 which then was used by #10972 to store the window position, size (but notably, not the buffer content)

@microsoft-github-policy-service microsoft-github-policy-service bot added the In-PR This issue has a related PR label Jan 24, 2024
github-merge-queue bot pushed a commit that referenced this issue Mar 29, 2024
This changeset allows Windows Terminal to dump its buffer contents as
UTF-16LE VT text onto disk and restore it later. This functionality is
enabled whenever `persistedWindowLayout` is being used.

Closes #961
Closes #16741

## Validation Steps Performed
* Open multiple windows with multiple tabs and restart the app
  Everything's restored ✅
* Reopen a tab with output from `RenderingTests.exe`
  Everything's restored ✅
* Closing tabs and windows with Ctrl+W deletes their buffer dumps ✅
* Closing tabs doesn't create buffer dumps ✅
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Tag-Fix Doesn't match tag requirements label Mar 29, 2024
@soroshsabz
Copy link

@zadjii-msft Did you know how to use this feature?

@zadjii-msft
Copy link
Member Author

This only just merged hours ago, so it's not available yet outside of just building the code from main directly. Tonight's canary build should have this, though, our canary pipeline has been having some publishing issues this week.

It should be enabled if you have "firstWindowPreference": "persistedWindowLayout" enabled in your settings.

@ylluminate
Copy link

Is this supposed to be available in 1.20.11381.0? When I have the "firstWindowPreference": "persistedWindowLayout" set, I still lose buffer / tab history upon restart, even though it does restart the sessions... My expectation from the parent request is that all of my history for various shells from PowerShell and cmd.exe to Ubuntu 24.04, etc. is all retained in perpetuity between Windows Terminal restarts...

@zadjii-msft
Copy link
Member Author

Nope. This was added in 1.21.

@mmseng
Copy link

mmseng commented Jun 13, 2024

I've been using it in the 1.21 Windows Terminal Preview. It does work as expected (for a certain definition of expected), however the vast majority of the times when I need it is when Windows updates reboot the machine, or when the machine otherwise reboots while Terminal is open, and from what I've seen I don't believe it's been working in these cases (I haven't been tracking it closely enough to make a more confident statement). As I recall, the failure due to Windows update reboots is an open issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-User Interface Issues pertaining to the user interface of the Console or Terminal In-PR This issue has a related PR Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Needs-Tag-Fix Doesn't match tag requirements Product-Terminal The new Windows Terminal.
Projects
Specification Tracker
  
Spec Needed ❓
Development

Successfully merging a pull request may close this issue.