| There still some pretty glaring issues, even after 40 years of refinement. Some I think could be iteratively fixed but not all of them (for example I believe #1 requires a significant breaking change to terminals). 1. You can't have an interactive program in a pipeline. For example, you can't do `gpg --decrypt foo.txt.gpg | nano | gpg --encrypt` because keyboard input on the console is handled through stdin. You can work around this by using a graphical editor in the pipeline, but this should be possible entirely over the command line. 2. You can't have hotkeys that are just modifier keys because the modifier keys only change the byte sent when pressing another key. So could couldn't have a hotkey "Shift" but you can have a hotkey "Shift-n". 3. How do you tell the difference between an escape sequence and the escape key? Escape sequences start with exactly the same byte used by the escape key 4. While we have escape sequences to move the cursor and detect the cursor location, in order to find dimensions of the terminal we have to resort to an ioctl. 5. Termcap. Because we can't assume some standard set of terminal features, and since my FreeBSD servers don't have a termcap file for alacritty, when I ssh into my FreeBSD servers my backspace key doesn't work (along with a lot of other things). 6. This ones a bit optional, but it would be nice to have a standard protocol for telling the terminal to render an image. 7. Abruptly killing a program that has put the terminal into raw mode leaves your terminal in raw mode. What would I do to fix this: 1. Move keyboard input to a different file handle than pipes. This would require software to be patched, or at least a compatibility layer written to merge the pipes for legacy software. 2. Remap all the keyboard bytes. Every key press and every key up sends data to the keyboard input stream. Let the program maintain a keyup/keydown state map for handling modifier keys. This would require software to be patched or at least a compatibility layer written to remap the bytes. 3. As part of the new encoding for #2, we should make a better encoding for input. The current system seems a lot more "grown" than designed. I'd love to see something similar to UTF-8 where we get to encode a variable-length integer with the benefits of indicating byte length in the first byte and being able to detect if we're in a continuation byte. We could even use UTF-8 verbatim for most of the keyboard input but we'd need a special section for escape sequences like moving the cursor. I don't know enough about unicode to know if theres a section we could use for that, but worst case scenario we could use the 5 and 6-byte length utf-8 sequences that never made it to the final utf-8 spec despite being possible in the encoding. 4. As part of #3, add escape sequences to detect terminal dimensions. 5. Establish a new minimum set of features that are assumed to work, incorporating all these refinements over the past 40 years. 6. This could be part of the new encoding for #3 7. Automatically revert terminal to its original non-raw-mode state at the end of a program. Finally, I'd recommend this blog post to appreciate how much of a mess terminal programming is: https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode... |
Later model physical DEC terminals had a mode called PCTERM (with escape sequences to enter/exit it) in which the terminal would send PC keyboard scan codes for key presses. However, very few terminal emulators implement that.
The Telnet server and client in Windows NT implements a somewhat similar feature, the VTNT terminal type, in which keyboard scan codes and mouse movements are transmitted in a binary format which is based on the Windows console API. (Nowadays Telnet is mostly deprecated in favour of SSH; there is no reason why SSH clients and servers could not implement VTNT, but I haven't seen any do it.)
The technology already exists to solve this problem, and has for years. It is just that nobody appears to care about it enough for that technology to become widely adopted.