Closed DJackman123 closed 4 years ago
This is likely a duplicate of #530 but with more information
TL;DR: There are actually some things that just cannot be represented via VT sequences, (Shift-Ctrl-Enter, Shift-[anything that isn't a letter/number]), and for which we'll need to devise or extend a standard.
@dhowett-msft -- I was thinking about this before and there is a VT200+ command, DECUDK
for user-defined keys. Normally this is limited to fifteen of the terminal's top-row function keys: F6 through F14, Do, Help, and F17 through F20. They are only triggered by using shift: e.g. shift+F6 will emit the user defined sequence, but F6 alone remains F6. What if we extended this scheme to cover Enter, Backspace, Del etc? The devil is in the details but it's somewhat consistent and keeps shift as an independently inert key in VT land. I'm not sure how this might work with respect to shift+ctrl+enter, since we'd be redefining ctrl+enter, not just enter. Unless we choose to read that as shift+enter is an entirely new key, and that ctrl is a modifier for that. Hmmm.
In my opinion, the right way to fix this is to add support for full INPUT_RECORD
s via VT, at least between the Terminal and Conpty. This'll let the terminal act just like conhost in terms of keypresses, but requires a decent amount of work.
The other potential trick here is how do we get full INPUT_RECORD
s in UWP? Doesn't seem to me like all the state we'd want is actually exposed, so we might have to live with "good enough" INPUT_RECORD
synthesis, and only fill in the info we can gather.
@zadjii-msft As long as it doesn't become a nest of windows-specific magic. One of the goals of ConPTY is to allow anyone to write a drop-in replacement terminal that speaks VT. If it has to speak WinAPI then I think we've failed somewhere along the way.
Oh I'm very aware of that. I think this is primarily a case of making sure that Windows-specific programs running attached to a conpty terminal can still behave the way they used to, if the terminal is capable of acting as a Windows-specific terminal.
The alternative is driving with PSReadline to stop using those keychords, because they won't work on *nix. Kinda curious that this is still a problem at all, with all the cross-platform stuff powershell is working on. I woulda thought they changed those keybindings. I guess them changing the defaults won't prevent people from setting them back to what they like, even if they don't work cross-platform.
The problem with pushing it back to PSReadLine to change its default keybindings is that the whole reason these particular bindings were used was to make the text editing experience in PowerShell consistent with other text editors (like Visual Studio). That's the case for keybindings like Ctrl+Backspace, Ctrl+Space, PageUp, and PageDown especially.
Alacritty has an interesting solution to this problem. They support remapping keys (from the OS point of view) to arbitrary character (VT) sequences. See their default config file.
This would still require custom key bindings in PSReadLine or similar applications. For example, in my alacritty.yml
, I might add:
# Replace Ctrl+Space with F12,a
- { key: Space, mods: Control, chars: "\x1b[24~a" }
Then in my PowerShell profile I might add:
Set-PSReadLineKeyHandler -Chord 'F12,a' -Function MenuComplete
It turns out that the xterm guys may have a more generalized approach for dealing with modifiers:
CSI > Ps ; Ps m
Set or reset resource-values used by xterm to decide whether
to construct escape sequences holding information about the
modifiers pressed with a given key.
The first parameter identifies the resource to set/reset. The
second parameter is the value to assign to the resource.
If the second parameter is omitted, the resource is reset to
its initial value.
Ps = 0 -> modifyKeyboard.
Ps = 1 -> modifyCursorKeys.
Ps = 2 -> modifyFunctionKeys.
Ps = 4 -> modifyOtherKeys.
If no parameters are given, all resources are reset to their
initial values.
I know we're trying not to step too far outside DEC VT stuff, but xterm is the de-facto standard. I don't think we should aim to emulate xterm, but we definitely need to take on enough to solve our open problems. Anyway, this seems to imply that xterm has a scheme for passing modifiers for all keys, not just shifted f5-f20 on vanilla DEC hardware.
Thoughts?
Oh, that's a really good idea. We'd need to add support to conpty for parsing them, but that shouldn't be impossible.
Just to add more to the mix, here's Kitty's approach: https://sw.kovidgoyal.net/kitty/protocol-extensions.html#keyboard-handling
The escape sequence encodes the following properties: Type of event: press,repeat,release Modifiers pressed at the time of the event The actual key being pressed
As you can see, they've got a pretty good analog of how we already encode things with INPUT_RECORD. I'm curious if xterm does the same.
I generally prefer the xterm way. xterm is the de facto standard for terminal communication. Generally any valid VT parser should discard those particular CSIs if they don't understand them. And if we can get away with solving the problem without going fully toward the INPUT_RECORD
model, then I think we should.
However, Kitty's approach does seem pretty decent if we do indeed end up having to do something like INPUT_RECORD
. There looks to be a provision to reset out of the special mode... but I would say that not a ton of applications/terminals/users are expecting or ready to do a reset when things go wrong. And if a reset doesn't occur... we could be causing strange things to happen.
I think this won't become clear until we choose a path and start down it by trying it out. At which point, I'd encourage the xterm-style way first until proven otherwise.
If anything, I think we should probably accept both methods as input to our system but only actively try to emit the xterm way out of the pty interface until proven otherwise.
Agree @miniksa -- the Kitty guy's protocol using Application Program Commands (APC) is pretty neat, but it's de-facto making anything that parses them a "KittyApp"(tm) and not a VT app. I guess Xterm are doing the same thing, but they are the Gold Standard. APC is meant for VT apps to signal each other, and should be ignored (never echoed) by terminals (although DEC does use some APCs itself, namely DECEKBD -- extended keyboard report.) That said, it's a open, well-known way to do internal signalling, if needed.
Just want to point out that legacy tools like ZtreeWin are very hard to impossible to use under Windows Terminal without some kind of support for direct raw input.
Here's a thought: could this instead just be a profile setting? "I want to run a legacy thing like ZTW" => "do the raw input dance"
Just throwing my vote in for the xterm way. xterm.js doesn't implement CSI > Ps ; Ps m
yet, but if it helps solve this issue we definitely would.
Another option to consider would be the VT510 PCTerm mode (enabled with DECPCTERM), where the keyboard generates a unique scancode (typically one byte) for both the press and release of every key. With that you should be able to handle any key combination imaginable.
You can see a list of the scan codes here: https://vt100.net/docs/vt510-rm/chapter8.html#S8.13
Another option to consider would be the VT510 PCTerm mode (enabled with DECPCTERM), where the keyboard generates a unique scancode (typically one byte) for both the press and release of every key. With that you should be able to handle any key combination imaginable.
You can see a list of the scan codes here: https://vt100.net/docs/vt510-rm/chapter8.html#S8.13
Man, DEC really were the masters of having twenty different ways to do something. I hadn't seen this before. Very interesting.
Just curious, how come this works okay in conhost? Is it because that is working with raw input, whereas terminal is only processing characters?
@factormystic basically, yes. The full story's much more complicated, but that's definitely the tl;dr version.
For my future sanity, the text on invisible-island changed:
CSI > Pp ; Pv m
CSI > Pp m
Set/reset key modifier options, xterm. Set or reset resource-
values used by xterm to decide whether to construct escape
sequences holding information about the modifiers pressed with
a given key.
The first parameter Pp identifies the resource to set/reset.
The second parameter Pv is the value to assign to the
resource.
If the second parameter is omitted, the resource is reset to
its initial value. Values 3 and 5 are reserved for keypad-
keys and string-keys.
Pp = 0 ⇒ modifyKeyboard.
Pp = 1 ⇒ modifyCursorKeys.
Pp = 2 ⇒ modifyFunctionKeys.
Pp = 4 ⇒ modifyOtherKeys.
If no parameters are given, all resources are reset to their
initial values.
Also:
It seems to work in xterm
, but maybe not gnome-terminal
\x1[<something maybe>;<modifiers>;<char value>~
for <char value>
: space
== 32
, A
=65
, a
=97
, etc
This seriously breaks the usability of terminal for powershell. I realize what I'm saying here doesn't really add to the solution. But even though this is a difficult problem, I feel that by not assigning this a higher priority for fixing, it shows a lack of concern for a basic mandatory feature of this program.
Please bump this higher in your stack of things to fix/solve!!
But it breaks Ctrl+h behavior for many applications.
Do we have any updates about this? I was really thrilled at the beginning about the project, but if basic functionalities such as CTRL + SPACE do not work, I don't see the point of using it.
When there are updates, we'll be sure to post here. We agree that this is a highly important feature, but it's one that unfortunately is going to take a lot of work to get quite right. It's a harder problem than just "add this keychord to the terminal" - it involves implementing an entire other input encoding to the conpty backend, and then also implementing a similar synthesis of input from the Terminal.
I've got this crazy thought that some of the work in #4856 might enable this keybinding for WSL applications, but it still won't work for Win32 console apps, like powershell.exe
and pwsh.exe
.
@zadjii-msft - PSReadLine supports VT input mode if you set $env:PSREADLINE_VTINPUT = 1
. As it isn't the default, it's not widely tested. It could in fact be completely broken, but the person who implemented it was happy with using that mode under tmux
.
@lzybkr Oh I didn't know that existed! That's certainly an interesting idea. Looks like with #4856 merged, we do pipe a NUL all the way through conpty to the client app for Ctrl+Space, but PSReadline doesn't accept it as the key for Ctrl+Space. It looks like it's being treated by PsReadline as Ctrl+@. That's perfectly understandable - they both have the same encoding in VT. Weirdly enough though, binding Ctrl-@ to MenuComplete still doesn't trigger it, event with #4856 merged and PSREADLINE_VTINPUT = 1
set.
Not sure it's already fixed in development, but CTRL-H doesn't work in Vim in my environment. It works in Command prompt, but not work in Windows Terminal when I use Vim.
When I use Far Manager under the Terminal, RightCtrl+N (N is numeric key) keys don't work.
Is it a manifestation of this issue? (if yes, it's very sad, since makes Terminal unusable to host Far Manager)
Unfortunately, yes. Anything that requires modifiers alone or specific modifiers (right versus left) is covered by this issue.
:tada:This issue was addressed in #6309, which has now been successfully released as Windows Terminal Preview v1.1.1671.0
.:tada:
Handy links:
Environment
Steps to reproduce
Open a PowerShell tab in Windows Terminal. Attempt to use these PSReadLine key bindings (use the Get-PSReadLineKeyHandler command to see a list of all key bindings):
Expected behavior
Key executes the specified PSReadLine function.
Actual behavior
Nothing happens (or the current tab changes in the case of Alt+digit)