-
Notifications
You must be signed in to change notification settings - Fork 8.4k
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
Strange behavior with ENABLE_VIRTUAL_TERMINAL_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT #4949
Comments
Thanks for doing all the legwork here! This is, unfortunately, to a fairly great extent "by design." The input and output modes are global state, and while we're thinking about what it would take to change that we're definitely concerned about backwards compatibility. When an application exits and leaves the console in a state different from the one it has when it launched (which can happen for a number of reasons: it wasn't authored correctly, it crashes, it returns control of the console so the shell before it's ready (#4921)), we have little choice but to get into a weird state. You see this with most terminals on the market, unfortunately. If vim is running in mouse mode, and is abruptly terminated, suddenly moving your mouse over your terminal generates an absolute heap of garbage input. It's impossible to solve in that case, but given that we own the console subsystem in its entirety we can put together a better story. I'm going to close this one as a /dupe of #4954, which we'll use to track the overall scenario. |
Hi! We've identified this issue as a duplicate of another one that already exists on this Issue Tracker. This specific instance is being closed in favor of tracking the concern over on the referenced thread. Thanks for your report! |
Thanks for the response @DHowett-MSFT! I just wanted to clarify a few things: For the mode issue, my understanding (after reading the linked issues) is that the reason my particular sample here works properly in PowerShell is that PowerShell actually makes an effort to set a sensible console mode before/after running a program, while CMD does not. Is that correct? If so, then I suppose the best I can do right now is try really hard to set the console mode back to its original state, even in the case of a crash, to make things work under CMD? Regarding the backspace issue I also brought up here, as far as I can tell, this isn't explained by the linked issues. To be clear, this issue happens even if you run the sample program from a 'clean' console. |
Exactly this. The backspace issue is an intricacy of how backspace is encoded in |
(because |
What does |
Ah, sorry. The input mode that CMD and legacy versions of PowerShell (without PSReadline) use. It's the mode there the console host handles producing a single line of input for the client application and only returns it when the user mashes Enter. |
It's the opposite of "raw" input 😉 |
OK, so to be clear, is the implication here that |
It would be ideal if you do so, yeah -- if all you want is actual VT input, unmanipulated by the console host, you're going to want to disable line and processed input. Most VT input consumers are doing their own line editing and want to get hold of the arrow keys and other keys germane to line editing, or they want to get mouse input in a cross-platform way, and having the processed or line input modes enabled will make it difficult to do that. |
But the thing is, that's not what I want. 🙂 For this project I'm working on, I'm trying to expose a consistent terminal interaction API that works the same way on Windows and Unix systems, and this issue touches on a pretty fundamental aspect of that. I'm attempting to get the same behavior on Windows that you get in the Unix world: VT keyboard input at all times, with cooked mode by default, and raw mode optionally available via Is there nothing that can be done to make the Windows console host handle this situation properly? |
Sorry, I misunderstood your use case. I'll try to break down a couple of the scenarios and the flags that'll light them up. Would you let me know if I've captured the ones you're looking for?
|
Okay, now I get it. Item 2 sub 3, the one I think is vt-cooked mode, has the wrong behavior for backspace; this seems to be true back a couple major releases of windows. That's not excellent. I'll check this out versus the version that introduced Sorry, I had to talk myself through your problem. 😄 |
Maybe it's easier to explain with this C program: #include <unistd.h>
int main()
{
char buf[4096];
write(STDOUT_FILENO, "reading: ", 9);
ssize_t len = read(STDIN_FILENO, buf, sizeof(buf));
write(STDOUT_FILENO, buf, len);
return 0;
} Run on a Linux system (or WSL) with You will notice that you are able to do fairly basic line editing while the program reads from stdin, i.e. the TTY is in cooked mode. The exact level of line editing available will probably depend on your terminal and But, you will also notice that if you type some special keys, they are picked up as VT sequences by the program. For example, This is the behavior I'm trying to achieve. To be clear, though, I don't particularly care what amount of editing features is available in cooked mode. It's okay that those are different between terminals and platforms. The important thing here is achieving the cooked + VT behavior, but not breaking Backspace / Ctrl+Backspace behavior on Windows in the process. |
@DHowett-MSFT This issue is quite annoying as it is making I have tried to investigate this and the end story is that the key is mapped by this table here for some reasons that I don't know:
I could make a PR and remove this line, but I'm not sure about the consequences. Thoughts? |
I tested by modifying these two places in terminal/src/terminal/input/terminalInput.cpp Lines 78 to 81 in 1e22bfa
static constexpr std::array<TermKeyMap, 19> s_keypadNumericMapping{
TermKeyMap{ VK_TAB, L"\x09" },
- TermKeyMap{ VK_BACK, L"\x7f" },
TermKeyMap{ VK_PAUSE, L"\x1a" }, terminal/src/terminal/input/terminalInput.cpp Lines 218 to 221 in 1e22bfa
static constexpr std::array<TermKeyMap, 14> s_simpleModifiedKeyMapping{
- TermKeyMap{ VK_BACK, CTRL_PRESSED, L"\x8" },
- TermKeyMap{ VK_BACK, ALT_PRESSED, L"\x1b\x7f" },
- TermKeyMap{ VK_BACK, CTRL_PRESSED | ALT_PRESSED, L"\x1b\x8" },
+ TermKeyMap{ VK_BACK, CTRL_PRESSED, L"\x7f"},
+ TermKeyMap{ VK_BACK, ALT_PRESSED, L"\x1b\x8" },
+ TermKeyMap{ VK_BACK, CTRL_PRESSED | ALT_PRESSED, L"\x1b\x7f" }, And the terminal seems to behave correctly with or without There are a few other places in the file where VK_BACK is mapped to |
@xoofx I think this might be relevant context: #5957 (comment) |
wow, ok, thanks for the link, what a mess 😅 So basically, the official terminal mapping is:
While in powershell/cmd on Windows to, it is interpreted as:
And the issue here is that, when
But it's incompatible with vt/unix terminals and Could Windows Terminal interpret [Edit]I have edited multiple times this message to get my head around the problem, and I will end it as I started, what a mess 😞 ) |
So thinking more about it, in the presence of
|
Tested this fix proposal for diff --git a/src/host/readDataCooked.cpp b/src/host/readDataCooked.cpp
index 169b0973..c33e6f2f 100644
--- a/src/host/readDataCooked.cpp
+++ b/src/host/readDataCooked.cpp
@@ -503,6 +503,8 @@ bool COOKED_READ_DATA::ProcessInput(const wchar_t wchOrig,
return true;
}
+ bool isInVirtualTerminalInputMode = _pInputBuffer->IsInVirtualTerminalInputMode();
+
if (wch == EXTKEY_ERASE_PREV_WORD)
{
wch = UNICODE_BACKSPACE;
@@ -558,7 +560,7 @@ bool COOKED_READ_DATA::ProcessInput(const wchar_t wchOrig,
_currentPosition -= 1;
// Repeat until it hits the word boundary
- if (wchOrig == EXTKEY_ERASE_PREV_WORD &&
+ if (!isInVirtualTerminalInputMode && wchOrig == EXTKEY_ERASE_PREV_WORD &&
_bufPtr != _backupLimit &&
fStartFromDelim ^ !IsWordDelim(_bufPtr[-1]))
{
@@ -636,7 +638,7 @@ bool COOKED_READ_DATA::ProcessInput(const wchar_t wchOrig,
NumSpaces = 0;
// Repeat until it hits the word boundary
- if (wchOrig == EXTKEY_ERASE_PREV_WORD &&
+ if (!isInVirtualTerminalInputMode && wchOrig == EXTKEY_ERASE_PREV_WORD &&
_bufPtr != _backupLimit &&
fStartFromDelim ^ !IsWordDelim(_bufPtr[-1]))
{ |
Hi folks, any thoughts on @xoofx's comments above? |
short notes I'll fix up tomorrow morning: the fullest solution is to do translation at read time not insert time, but that's Hard to impossible. These modes together will probably always be a little fucky, but they could be less fucky. Proposed fix seems close, but is just all backspace. We need to flip the meaning of |
"tomorrow morning" lmao sorry for the delay
|
Environment
Steps to reproduce
C# program:
(Uses the
Vanara.PInvoke.Kernel32
NuGet package for convenience.)You will need to test this program in both CMD and PowerShell Core.
Try doing these:
aaa bbb ccc
and press backspace a couple times.aaa bbb ccc
and press control + backspace several times.Also, try using special keys (such as arrow keys) after the program closes.
Actual behavior
For the first part:
This behavior happens in both CMD and PowerShell Core.
For the second part:
After closing the program, you'll notice that e.g. using the arrow keys echoes VT sequences (such as
^[[D^[[A^[[C
for left, up, right) rather than doing what they're supposed to. This behavior persists even if theReadLine
+WriteLine
is removed from the program.This behavior only happens in CMD. PowerShell Core seems fine.
Expected behavior
I have no idea to what extent, if any, this behavior is actually buggy/unintended. But here is what I would expect as a user:
Perhaps worth noting that running CMD and PowerShell Core under Windows Terminal has no impact on the behavior seen here.
Also, I wasn't sure whether to file this as two separate issues. I can do that if necessary.
The text was updated successfully, but these errors were encountered: