-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
[Unix] Console.ReadKey rewrite #72193
Conversation
…ed to reference all sys-calls used for reading files
… bytes which represent single UTF8 character by design
… between Enter (\r) and Ctrl+Enter (\n) like we do on Windows
remove UXTerm as its the same as Term
…uilding Console solution only)
src/libraries/System.Console/src/System/ConsolePal.TerminalFormatStrings.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Console/src/System/ConsolePal.TerminalFormatStrings.cs
Outdated
Show resolved
Hide resolved
']' => (ConsoleKey.F8, ConsoleModifiers.Control | ConsoleModifiers.Shift), | ||
'^' => (ConsoleKey.F9, ConsoleModifiers.Control | ConsoleModifiers.Shift), | ||
'_' => (ConsoleKey.F10, ConsoleModifiers.Control | ConsoleModifiers.Shift), | ||
'`' => (ConsoleKey.F11, ConsoleModifiers.Control | ConsoleModifiers.Shift), |
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.
'`' => (ConsoleKey.F11, ConsoleModifiers.Control | ConsoleModifiers.Shift), | |
''' => (ConsoleKey.F11, ConsoleModifiers.Control | ConsoleModifiers.Shift), |
This one looks to me as '
on https://vt100.net/docs/vt510-rm/chapter6.html.
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.
Same here, but PuTTy uses '`' for it and it's the only Terminal that supports SCO emulation that I could find and test
https://serverfault.com/questions/429901/how-to-change-the-terminal-to-sco-compliant-in-ubuntu
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.
LGTM
// Is it a three character sequence? (examples: '^[[H' (Home), '^[OP' (F1)) | ||
if (input[1] == 'O' || char.IsAsciiLetter(input[2]) || input.Length == MinimalSequenceLength) |
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.
// Is it a three character sequence? (examples: '^[[H' (Home), '^[OP' (F1)) | |
if (input[1] == 'O' || char.IsAsciiLetter(input[2]) || input.Length == MinimalSequenceLength) | |
// Is it a three character sequence? (examples: '^[[H' (Home), '^[OP' (F1)) | |
if (char.IsAsciiLetter(input[2]) || input.Length == MinimalSequenceLength) |
// based on https://en.wikipedia.org/wiki/ANSI_escape_code#Fe_Escape_sequences | ||
static ConsoleKey MapEscapeSequenceNumber(byte number) |
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 looked at the wikpedia link and I still don't see the relation with the 1 to 34 numbers used here.
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.
Co-authored-by: David Cantú <dacantu@microsoft.com>
@jozkee big thanks for the review! I know it was not an easy one ;) |
@adamsitnik your changes to the TermInfo.cs tests undid the changes done in #73104. We now have a blocking-clean-CI issue on it in #73212. Could you please have a look? |
@MichalStrehovsky sure thing! |
I believe that the most important aspect of this change is testing and ensuring that the new implementation is better than the old one.
To make
Console.ReadKey
testable, I’ve moved the parsing logic to a new method (and type) and made all the environment-specific variables like Terminfo parameters of it. Pseudocode:This required breaking
TermInfo.cs
into multiple files but allowed for testing (and debugging!) the parser on any OS. I’ve not made these types public, I am just referencing them as links in the test project. It’s not perfect, but I think it’s the best solution without introducing a new public API.The next step I took was writing a small command line app that records all the necessary information (Terminfo, VERASE, Encoding, $TERM) and asks the user to press a LOT of key combinations, records the data returned by
read()
sys-call and outputs it to source code file that can be included in System.Console test project.I’ve recorded the testing data for:
And implemented a new parser that uses Terminfo to map every escape sequence, but when there is no mapping (a very common example is well known keys with modifiers), fallback to mappings defined by various Terminals and/or standards.
When I run the new tests against the old implementation I can observe 987 failures. I've kept the old code and I can introduce a flag to switch to the old implementation.
fixes #802
fixes #25735
fixes #44621
fixes #45597
fixes #60101 (VT sequences are not going to miss
[
anymore)fixes #63387
fixes #63644
Limitations:
Cltrl+D2
vsCtrl+Space
as they both produce null ascii character. CurrentlyCtrl+Space
is mapped toCtrl+D2
but I am not sure whether I made a good decision here.read()
sys-call. Shift+Dx keys can't be mapped to key and modifier, just to resulting character. Example: Shift+D1 (‘!’ on most keyboards) is mapped to char=!
with no key and no modifier.OemX
andDivide
(Numeric Keypad on Windows), as they are both mapped to/
character. They are both mapped toConsoleKey.Divide
OemPlus
andAdd
(Numeric Keypad on Windows), as they are both mapped to+
character. They are both mapped toConsoleKey.Add
.OemMinus
andSubtract
(Numeric Keypad on Windows), as they are both mapped to-
character. They are both mapped toConsoleKey.Subtract
ConsoleKey
does not define such value, so it’s mapped toConsoleKey.NoName
.