-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
When the terminal has exited, ctrl+D to close pane, Enter to restart terminal #14060
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just the one thing. This is awesome, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this! I've got a couple thoughts before I dig into the code (whereupon I'm preemptively blocking to have the discussion/avoid it merging while we noodle!)
- I'm a little worried about making connections restartable. In our original connection state flow model, connections never regressed and only marched forward to one of the terminal states (finished, failed). There's a few knock-on effects as a result of this change: output threads need to be restartable, and listeners to the state change notification need to be audited to make sure they, too, can handle regressive state flow.
- I wonder, does TerminalControl or TerminalApp have enough information to reconstruct the connection anew?
- Should we emit a
RIS
(hard reset) to the terminal before restarting? Apps like vim and MC leaving the terminal in an inconsistent state when they die is a big cause of user confusion, and this feature might offer similar behavior across application sessions/conpty sessions.- (I know you worked on cursor inheritance to make this work; however, cursor inheritance has its own set of ... let's call them adorable quirks like History window partially invisible when switching from bash to cmd.exe #3678; what are your thoughts here?)
I totally get the concern about the connection going back to the beginning from closed/failed. I wasn't sure I could get it to work without changing a lot of stuff, but I think I found a minimal way to do it. Also, I make sure I've closed the output thread and the pipes before I restart. Maybe there's more to it than that. I've only been looking at this code for a week now, so I'm definitely no expert!
As for cursor inheritance, the big thing I had to figure out was to always preserve the changing size (rows, cols), even when closed/failed, and then use them when restarting. Before I figured that out, it was always using the initial size which wasn't always guaranteed to be what the pane was currently using, and weird things happened in the output. Also, I considered clearing/resetting the buffer at restart instead of inheriting the current cursor. That might be safer, although I saw that people were asking to reuse the buffer when restarting, so that's what I was trying to do. |
… Enter to restart terminal
…Enter to restart terminal
One minor comment: Ctrl+D may be a clearer message and match keybinding info in tab tooltips, at least makes sense to add it in brackets ^D (i.e. Ctrl+D) |
Initial thought just playing with this: hot DAMN re-using the same terminal feels crisp. I kinda imagined the restart being a whole "discard the existing I agree that we might want to avoid "restartable connections", and instead make fresh connections. That can totally be an us problem IMO, as a pre-ship codehealth fix (I don't really want to ask you to do that). |
…Enter to restart terminal
Yeah, when I got it working, I thought it was pretty slick. I have terminals running PowerShell where it would be nice to say "exit" and then be able to hit Enter to get a fresh terminal with the same command line parameters that started it. Much better than exiting the tab and hunting down the one I want to start a clean one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code is really straightforward. Yea, lets do this. I'll file the follow up to this, I wouldn't want to bother a non-team member with that kind of code shuffling
return true; | ||
} | ||
|
||
if (ch == Enter) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self: file a blocking codehealth task, to turn this into an event for the control to request from the app a new connection.
void _resetConnectionState() | ||
{ | ||
{ | ||
std::lock_guard<std::mutex> stateLock{ _stateMutex }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: removing this delta should be part of the codehealth follow-up
I went ahead and just changed it to Ctrl+D in the text. |
Done! |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Moved from PR body @sotteson1 thanks so much for this, and for your patience! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm cool with this, but I did have a minor rewording suggestion and a question.
Thanks again!
And thank you Mike for taking on the follow up work 😄
Hello @zadjii-msft! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
🎉 Handy links: |
A different take on #14548. > We didn't love that a connection could transition back in the state diagram, from Closed -> Start. That felt wrong. To remedy this, we're going to allow the ControlCore to... ASK the app to restart its connection. This is a much more sensible approach, than leaving the ConnectionInfo in the core and having the core do the restart itself. That's mental. Cleanup from #14060 Closes #14327 Obsoletes #14548
Adds an action for immediately restarting the connection. I suspect most folks that wanted #3726 will be happy just with the <kbd>enter</kbd> solution from #14060, but this will work without having to `exit` the client. Just, relaunch whatever the commandline is. Easy peasy. Closes #3726. Obsoletes #14549
When a terminal process exits (successful or not) and the profile isn't
set to automatically close the pane, a new message is displayed:
You can now close this terminal with ^D or Enter to restart.
Ctrl+D then is able to close the pane and Enter restarts it.
I originally tried to do this at the ConptyConnection layer by changing
the connection state from Failed to Closed, but then that didn't work
for the case where the process exited successfully but the profile isn't
set to exit automatically. So, I added an event to
ControlCore/TermControl that Pane watches. ControlCore watches to see if
the input is Ctrl+D (0x4) and if the connection is closed or failed, and
then raises the event so that Pane can close itself. As it turned out, I
think this is the better place to have the logic to watch for the Ctrl+D
key. Doing it at the ConptyConnection layer meant I had to parse out the
key from the escaped text passed to ConptyConnection::WriteInput.
Validation Steps Performed
Tried adding lots of panes and then killing the processes outside of
Terminal. Each showed the new message and I could close them with Ctrl+D
or restart them with Enter. Also set a profile to never close
automatically to make sure Ctrl+D would work when a process exits
successfully.
Closes #12849
Closes #11570
Closes #4379