<ESC> comes through as <ESC><ESC> #1716

Closed
opened 2026-01-30 22:34:29 +00:00 by claunia · 9 comments
Owner

Originally created by @hamish-smith on GitHub (Jun 17, 2019).

Environment

Windows 1903 18917.1000
terminal master 315abf6fa6

Steps to reproduce

Run CascadiaPackage
Select new Ubuntu package.
run some command (e.g. ls /usr/bin)
now attempt to paste the last command to the previous shell command using <ESC> . (e.g. type cd <ESC> . .

Expected behavior

the last command to the previous shell command should be pasted (e.g. cd /usr/bin)

Actual behavior

cd . Escape appears to be ignored / not passed to WSL.

In WSL <ESC> . works as expected.
I note that <ALT> + and <ALT> . work. For whatever historic reason, my muscle memory is <ESC> . pastes the final argument to last command I ran.

There are other uses of that should be consider (e.g <ESC> t to swap the last two words on the line). As bash considers a control character, it should probably be sent along to the WSL command line the same as CTRL and ALT are.

Originally created by @hamish-smith on GitHub (Jun 17, 2019). # Environment Windows 1903 18917.1000 terminal master 315abf6fa6e096f0ad8ba7db68fa8a3fd9a591b1 # Steps to reproduce Run CascadiaPackage Select new Ubuntu package. run some command (e.g. `ls /usr/bin`) now attempt to paste the last command to the previous shell command using `<ESC> .` (e.g. type `cd <ESC> .` . # Expected behavior the last command to the previous shell command should be pasted (e.g. `cd /usr/bin`) # Actual behavior `cd .` Escape appears to be ignored / not passed to WSL. In WSL `<ESC> .` works as expected. I note that `<ALT> +` and `<ALT> .` work. For whatever historic reason, my muscle memory is `<ESC> .` pastes the final argument to last command I ran. There are other uses of <ESC> that should be consider (e.g `<ESC> t` to swap the last two words on the line). As bash considers <ESC> a control character, it should probably be sent along to the WSL command line the same as CTRL and ALT are.
Author
Owner

@zadjii-msft commented on GitHub (Jun 18, 2019):

holy crap I never knew that keybinding existed. I guess I didn't really know about the alt+. one either, though, fundamentally they're the same keybinding, as esc+. is sending the same sequence as alt+..

This does work in conhost+conpty, so this is definitely a terminal-specific bug. Thanks for the report!

@zadjii-msft commented on GitHub (Jun 18, 2019): holy crap I never knew that keybinding existed. I guess I didn't really know about the <kbd>alt</kbd>+<kbd>.</kbd> one either, though, fundamentally they're the same keybinding, as <kbd>esc</kbd>+<kbd>.</kbd> is sending the same sequence as <kbd>alt</kbd>+<kbd>.</kbd>. This _does_ work in conhost+conpty, so this is definitely a terminal-specific bug. Thanks for the report!
Author
Owner

@DHowett-MSFT commented on GitHub (Jun 18, 2019):

Looks like WT passes ESC through as ESC ESC. That's not great.

@DHowett-MSFT commented on GitHub (Jun 18, 2019): Looks like WT passes ESC through as `ESC ESC`. That's not great.
Author
Owner

@Trundle commented on GitHub (Jun 21, 2019):

The double escape happens because Terminal::SendKeyEvent ignores almost always TerminalInput::HandleKey's return value: 08464648f2/src/cascadia/TerminalCore/Terminal.cpp (L253-L258)

ch is set to UNICODE_NULL for the escape case, hence SendKeyEvent returns false, even though the key was already handled by TerminalInput::HandleKey. That means that TermControl::_CharacterHandler will be called with the key translated as character, which will be \x1b, hence it appears as ESC ESC.

Now ignoring HandleKey's return value (in many cases) would mean that almost all keys would appear twice. And indeed that happens in theory, but not in effect because HandleKey has two cases: one for "printable" keys and one for others: 08464648f2/src/terminal/input/terminalInput.cpp (L446-L461)

So for printable keys, the event's char data is used - but char data is most of the times UNICODE_NULL due to the way Terminal::SendKeyEvent constructs the event: 08464648f2/src/cascadia/TerminalCore/Terminal.cpp (L255)

And ch is initialized with UNICODE_NULL: 08464648f2/src/cascadia/TerminalCore/Terminal.cpp (L226)

And that means that for "printable" keys, HandleKey returns that it handled the key already, but then didn't really send an input sequence (or rather: it sends one with size 0) - which doesn't really matter because SendKeyEvent happily "ignores" the return value.

@Trundle commented on GitHub (Jun 21, 2019): The double escape happens because `Terminal::SendKeyEvent` ignores almost always `TerminalInput::HandleKey`'s return value: https://github.com/microsoft/terminal/blob/08464648f280624023d3572346a75dee7a428de8/src/cascadia/TerminalCore/Terminal.cpp#L253-L258 `ch` is set to `UNICODE_NULL` for the escape case, hence `SendKeyEvent` returns `false`, even though the key was already handled by `TerminalInput::HandleKey`. That means that `TermControl::_CharacterHandler` will be called with the key translated as character, which will be `\x1b`, hence it appears as `ESC ESC`. Now ignoring `HandleKey`'s return value (in many cases) would mean that almost all keys would appear twice. And indeed that happens in theory, but not in effect because `HandleKey` has two cases: one for "printable" keys and one for others: https://github.com/microsoft/terminal/blob/08464648f280624023d3572346a75dee7a428de8/src/terminal/input/terminalInput.cpp#L446-L461 So for printable keys, the event's char data is used - but char data is most of the times `UNICODE_NULL` due to the way `Terminal::SendKeyEvent` constructs the event: https://github.com/microsoft/terminal/blob/08464648f280624023d3572346a75dee7a428de8/src/cascadia/TerminalCore/Terminal.cpp#L255 And `ch` is initialized with `UNICODE_NULL`: https://github.com/microsoft/terminal/blob/08464648f280624023d3572346a75dee7a428de8/src/cascadia/TerminalCore/Terminal.cpp#L226 And that means that for "printable" keys, `HandleKey` returns that it handled the key already, but then didn't really send an input sequence (or rather: it sends one with size 0) - which doesn't really matter because `SendKeyEvent` happily "ignores" the return value.
Author
Owner

@nickperkins commented on GitHub (Jun 22, 2019):

I note that + and . work. For whatever historic reason, my muscle memory is .

This is because bash (and other shells/terminals) prefix an ESC in response to the Alt key. Alt + . ends up as ESC + .

@nickperkins commented on GitHub (Jun 22, 2019): > I note that <ALT> + and <ALT> . work. For whatever historic reason, my muscle memory is <ESC> . This is because bash (and other shells/terminals) prefix an ESC in response to the Alt key. Alt + . ends up as ESC + .
Author
Owner

@aduitsis commented on GitHub (Jun 24, 2019):

Just to add that a very common sequence is also esc-p, which in tcsh and csh executes a command search based on what has been typed so far. In other words, you type a part of a command, esc-p and you get the first possible completion, and so on. Esc-p is also used in zsh and it is also possible to enable it in .inputrc for bash. Speaking of which, esc-b (back one word) and esc-f (forward one word) and esc-d (delete word) also cannot work in bash. I'd say that correct esc behaviour is important.

Microsoft terminal version 0.2.1715.0.

@aduitsis commented on GitHub (Jun 24, 2019): Just to add that a very common sequence is also esc-p, which in tcsh and csh executes a command search based on what has been typed so far. In other words, you type a part of a command, esc-p and you get the first possible completion, and so on. Esc-p is also used in zsh and it is also possible to enable it in .inputrc for bash. Speaking of which, esc-b (back one word) and esc-f (forward one word) and esc-d (delete word) also cannot work in bash. I'd say that correct esc behaviour is important. Microsoft terminal version 0.2.1715.0.
Author
Owner

@DHowett-MSFT commented on GitHub (Jun 24, 2019):

Cool, thanks, we know it is a bug and it is impacting peoples' lives. It will break all sorts of different things that require individual escape characters.

@DHowett-MSFT commented on GitHub (Jun 24, 2019): Cool, thanks, we know it is a bug and it is impacting peoples' lives. It will break _all sorts_ of different things that require individual escape characters.
Author
Owner

@DHowett-MSFT commented on GitHub (Jun 25, 2019):

@Trundle you've looked at this in a good amount of depth. Would you want to take it on as a community contribution? 😄

@DHowett-MSFT commented on GitHub (Jun 25, 2019): @Trundle you've looked at this in a good amount of depth. Would you want to take it on as a community contribution? :smile:
Author
Owner

@Trundle commented on GitHub (Jun 26, 2019):

I can try to, but I also won't be able to do so until the end of next week - I don't mind if someone else fixes it in the meantime.

@Trundle commented on GitHub (Jun 26, 2019): I can try to, but I also won't be able to do so until the end of next week - I don't mind if someone else fixes it in the meantime.
Author
Owner

@ghost commented on GitHub (Aug 3, 2019):

:tada:This issue was addressed in #1974, which has now been successfully released as Windows Terminal Preview v0.3.2142.0.🎉

Handy links:

@ghost commented on GitHub (Aug 3, 2019): :tada:This issue was addressed in #1974, which has now been successfully released as `Windows Terminal Preview v0.3.2142.0`.:tada: Handy links: * [Release Notes](https://github.com/microsoft/terminal/releases/tag/v0.3.2142.0) * [Store Download](https://www.microsoft.com/store/apps/9n0dx20hk701?cid=storebadge&ocid=badge)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#1716