-
-
Notifications
You must be signed in to change notification settings - Fork 3
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
Parse terminal escape codes into a useful representation #15
base: main
Are you sure you want to change the base?
Conversation
This is essential for parsing terminal key codes.
This will probably be more useful than peek in most situations.
This is not complete, but it already does the basics. - Define Key type - Define KeyReader effect for reading Keys - Implement basic KeyReader for terminal escape codes. Not complete - Implement for JLineTerminal - Update Prompt example to use KeyReader
Users will have to interact with Eof, Timeout, and Key. They shouldn't need to import things from `terminus.effect`, so move these types into `terminus`.
/** Enumeration describing the key presses we recognize from the terminal */ | ||
enum Key { | ||
|
||
/** A standard character, like 'A' or 'z.' */ |
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.
What about adding something like:
case class KeyStroke(keys: Seq[Key])
So instead of ControlShiftI
, you'd have KeyStroke(Seq(Control, Shift, Character('i')))
?
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 think that's a good idea, though I'd rather not use a Seq
(unordered and space inefficient) compared to a more compact representation like that in Crossterm: https://docs.rs/crossterm/0.28.1/crossterm/event/struct.KeyEvent.html
- Refactor keys into separate elements for key modifiers and key codes - Implement `KeyReader` on Native which causes many changes to the implementation: - Add non-blocking read - Switch `fgetc` to `read` so they don't use the same buffer - Switching modes take effect immediately and doesn't flush input (flushing input means we lose key codes) - Don't translate CR to NL - Implement `Prompt` as a generic (cross-backend) example For efficiency we may need to rethink how we handle input to store a character buffer. I think the longest key code is 4 characters, so we could read 4 characters at a time and keep a buffer of elements. Dealing with unicode (i.e. characters longer than one byte) is also an open question.
private val reader = terminal.reader() | ||
private val writer = terminal.writer() | ||
|
||
def peek(duration: Duration): Timeout | Eof | Char = |
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.
Does peek look at the buffer without clearing it?
package terminus | ||
|
||
opaque type KeyModifier = Byte | ||
object KeyModifier { |
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 like the use of bitflags for keystroke modifiers. What are Super
, Hyper
, and Meta
? Do they vary based on keyboard/operating system?
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.
Yes. Super is, I think, usually mapped to the Windows key, or the squiggle on Mac keyboards. The other two aren't used so much, I think. I think they were originally found on Lisp machines. Just more of the ancient baggage the terminal carries.
Parse the mess of escape codes the terminal uses to encode key presses into a useful representation.
Closes #9