Fix Terminals
leonerd.org.uk
leonerd.org.uk
(That's literally the plan described in the article)
The first paragraphs of https://clojure.org/community/etiquette nail it: the software community is about making. If you want something done, make it.
How would a "maker-driven" solution look like in this domain? For example:
- make a terminal emulator that accepts the devised keybinding system
- make at least one popular program (e.g. Emacs) play fine with said terminal
- promote that combination, showing the world how the technology can in fact work. Word of mouth would do the rest.
They are the lead author of libvterm, a popular modular terminal emulator library that is for example used in neovim and emacs-libvterm.
They have also been working on libtermkey, a library that accepts input from the divised keybinding system, now part of libtickit mentioned in the post.
It can. How would you like them to move into the future? It's not as if there's been no recent evolution in terminal emulators.
Notice that evolving into the future and using old ideas are not incompatible. Modern cryptography still uses Euclid's algorithm from more than two millennia ago.
For starters: stop using in-band signaling.
In-band signaling — or rather, in-band markup — is a big part of what makes a "terminal" (i.e. a TTY/PTY device) semantically a "terminal": a hybrid character-grid / event-log that works both as a sink for streamed-in text, and as a "plotter" for making line-printer art. A device that both streams out as, effectively, an input-event log (where this log can be captured for replay, as with script(1) or most logging systems); but which also maintains a notion of being a ring-buffer "containing" a rectangularly-bounded volume of text (and control-events), such that clients just connecting onto it can begin streaming just from the beginning of that buffer, to end up with one complete "image" of the latest PTY state, minus any scrollback, without needing previous history.
All that is kind of predicated on control-characters being embedded in the text and "following" the text around, such that taking a slice of the text (as the PTY's ring-buffer does every time a line is expunged) will preserve the corresponding slice of events.
What would reading back the contents of a PTY device look like in a world with out-of-band TTY signalling? What would flow over a serial port? Would it even be a character-stream device, or are you imagining a TTY/PTY as operating in something more akin to a structured datagram event-stream mode, such that you'd use sendmsg(2) and recv(2) on it rather than write(2) and read(2)?
I mean, it's not an impossible dream; but that really is a "start over with a whole separate ecosystem that no existing software works with until made compatible" kind of change. Effectively it'd be a separate thing from TTYs, that just happens to have similar functionality. But it wouldn't support any existing software, or any existing hardware, except by virtualization (i.e. running a PTY emulator process inside your modern OoB-signalling terminal emulator.) Kind of like what Windows has been going through to replace its own command-line.
---
Personally, I'd prefer to keep in-band signalling (in the "in-band markup" sense above, not the "you have to recognize conventional escape-code sequences heuristically to even know they're not regular text" sense.)
But I'd rather just make the in-band signalling structured — i.e. to make TTYs into a data-stream containing a variable-length self-synchronizing bit-encoding with clear prefix separation for control- and data- packets.
Y'know, like UTF-8 is for text.
...or, well, speaking of Unicode: we could just use Unicode for this, reserving another block† of control characters to go with the 30-odd ones that sit at the beginning of the BMP. Then "is this is a control codepoint, and if so, what does it mean" could just be answered by consulting a Unicode table. (In such a setup, CSI command parameterization would be accomplished with zero-width joiners, variant selectors, and other things. Just picture control-characters as invisible emoji — specifically like the flag emoji that are formed by spelling out country-codes in a sort of "flags meta-alphabet"; or like that family emoji [https://emojipedia.org/family/] with the combinatoric variants.)
† Why not use the Private Use Area? Because this would be an explicitly inter-compatible signalling standard, not a proprietary usage. It's not text, but it is a standard signal within a text document. Just like emoji — or like the existing control codepoints in Unicode.
I have some frustrations with terminals, which I have always interpreted as being caused by their adherence to some old standards. After reading this comment, I think I can see how it's more the terminal paradigm itself that is responsible for some of these things.
Now, in the future I will be able to look at these frustrations in a new light, and hopefully understand a little better why it makes sense to continue using the terminal paradigm despite them.
This is something I've struggled to understand for a long time, and your comment, obvious though it may seem to some, is one of the first helpful answers I've seen.
Keep in mind that I do not deeply understand the stack of standards and implementations that comprise a terminal. That said, my assumption is that this complaint is an unfortunate, unavoidable byproduct of that stack.
While introducing newcomers to terminal usage, there are simple actions from the gui world that do not work at all, or even seem to break the terminal display. It's extremely confusing for them, they get over it eventually, and come to accept that the terminal just can't do certain things. This is what I mean by being unable to move into the future.
As a point of comparison, consider how much of a mess it is to deal with spaces in file names, in bash. To a newcomer, this seems like a crazy hassle, some antiquated nonsense. It's hard for them to understand how experienced Linux users can stand to deal with it. It's annoying, but it's a direct consequence of the choice to use the space character as the delimiter between tokens in bash. This choice is actually super convenient most of the time, because that is the best use of the space character/key in a terse shell language.
What is the analogous rationale behind the shortcomings of the terminal paradigm? What would we need to give up, in order to make the terminal interface a little bit more modern?
For example, you could get a terminal that allows selecting text with keyboard but what happens when a user inevitably wants to or accidentally selects text from the non-input part of the terminal? Should the input part of the terminal and the display part of the terminal be treated differently? In Firefox as I type this I get a nice big input box where I can do multi-line paragraphs but if I start clicking and dragging to select the text in the input box it'll never let me select text from your comment, likewise in reverse, but on a terminal this would be undesirable behaviour for the common pattern of selecting text to copy output for documenting or troubleshooting. Some terminals have plugins or scripts to allow such selection of text but not for input purposes, if you decide to only allow text selection on the input field as a means of improving text input do you just get two such methods of being able to select text? The sane approach might be to allow selecting all text but you'll end up with paper cuts where a user doesn't care about what is going on before the $ but might end up in situations where text is selected far before the $ because of a reverse search gone wrong, etc.
As an aside, terminals/bash do have some form of text-editor like functionality, readline is the usual library involved (man bash, /^readline) and has reasonable support for moving cursor around words, move cursor to character search, deleting/yanking/pasting words, etc. It's not the best text editing interface but for dealing with a single command line it's usually sufficient. There's even a vi-like editing mode (set -o vi) built into bash if you feel like you need a modal editor for a single line but it seems even less intuitive and harder to grok.
https://readline.kablamo.org/emacs.html
<ctrl-v> essentially means "insert the next key I press verbatim". So, like in Vim, <esc> would switch modes, unless you press <ctrl-v> first. Helpful if you're trying to insert a control character into a file, or echo a literal <ctrl-c> etc.
Changing the existing standards just won't work as it would break a ton of programs, although if I'm being honest - while I like the idea of such a terminal rework - I don't know if it can be done nowadays without it opening the flood gates by developers who just can't restrain themselves from adding so many features it might as well be a new browser engine.
And either way I don't think it's worth the effort as those input limitations only affect a few specific situations. I use hundreds of custom keybindings in Vim and so far the only obstacle I encountered was the `Tab` & `Ctrl-i` overlap. If I need to hold down more than one modifier I did something wrong anyway.
However I like those modernised protocols and it would be neat to have widespread support for it.
kitty is a great terminal, but it's one example of fast not being also lightweight.
time xterm false real 0.052 user 0.035 sys 0.000 maxmem 9 MB faults 1
Doesnt look like an order of magnitude to me.
mlterm -e false 0.08s user 0.02s system 84% cpu 13Mb mem 0.125 total
kitty -1 false 0.22s user 0.05s system 93% cpu 78Mb mem 0.290 total
(and yes, there's a kitty instance running already..)
~ >=> time st ls
real 0m0.048s
user 0m0.041s
sys 0m0.008s
~ >=> time kitty ls
real 0m0.239s
user 0m0.173s
sys 0m0.059s
If kitty isn't nicely cached it takes over 500ms on my machine.
Using your suggested flag it still takes twice as long."time kitty -1 true" takes about 180ms on my machine. That's more than fast enough for me, but certainly slower than many other terminals.
To me it feels silly to put a lot of effort into supporting things better in terminal emulators because they are not as flexible as actual user interfaces and I think the main reasons we still have them are historical.
Aside: I’d also like to see a command line shell which runs outside the terminal emulator rather than inside it.
The problem with using a terminal is that control of it is distributed between a few things the user can control and the escape sequences (or just output) produced by the shell and any processes that run in it. These may end up conflicting with each other leaving your terminal in a bad state or you may just get broken output (ever tried piping pv something | ... | less?). One way to regain some control is with something like tmux but this can become unwieldy (and heaven forfend it sees a multibyte Unicode character—terminal emulators don’t really have a way to communicate with applications about how wide a character is going to be when drawn)
I think a few things get conflated because there are few text-centric or command-line user interfaces. I put it to you that it is possible to have good composable text-centric user interfaces that don’t rely on pretending to be a VT100 or an ancient single-byte-stream-with-control-sequences protocol.
I have many text notes which record various commands. I have them because it is so easy -- once you figured out how to do something, get the history and copy relevant stuff. At work, we share the commands on Slack, put them into Wiki, paste them in the docs, and so on. If the commands grow too complex, they turn into scripts -- after all, scripts are just file rename away.
I don't think I could do this efficiently I had to use GUIs. Theoretically, I could write an manuals with dozens of steps[0], but this is much more significant effort, and they'll likely go stale anyway.
[0] https://docs.microsoft.com/en-us/iis/application-frameworks/...
For example, the entire MS Office Suite is programmable - you can write VB Script (or lately, JS?) and achieve most if not all of the functionality supported in the GUI.
Rather more well known on this front, Emacs and many other Lisp systems have always supported the same kind of programmability as a shell from within the GUI environment - both in the form of a simple REPL and more advanced GUI-command interaction (e.g. executing the current selection as elisp code, executing a command with the current selection as input etc).
The problem with such a shell would be that all the simple utilities and tools one likes to use in a shell will not work without a tty (or pty or fake-pty-conhost.exe). So the shell by itself would be pretty useless.
This theoretical shell and its family of utilities would all have to emulate terminal emulators by using something of a common library of wrappers around tty functionality. At that point you've re-invented cygwin for your OS of choice. And you're going to be running the same kinds of stuff you'd run in a real terminal emulator.
I'm not being snarky. I gave this kind of thing a lot of thought many years ago when I was thinking of native GUI unix-style shells on Windows.
Unless you have a different use case in mind for this shell ?
I also think it’s not so useful anymore to just set up a pipeline and let it run off and do it’s work. Interactive shell usage is often mostly about editing or extending a small suffix of the previous command, so I think a shell should be optimised to do that well.
Could be do-able in Unixy OSes, with a lot of work to detach the OS from the concept of a tty.
Interesting !
Plan 9 did something like that with its rio windows (that replace the terminal emulators) and its rc shell.
https://9p.io/wiki/plan9/using_rio/index.html
http://man.cat-v.org/plan_9/1/rio
> The problem with such a shell would be that all the simple utilities and tools one likes to use in a shell will not work without a tty (or pty or fake-pty-conhost.exe). So the shell by itself would be pretty useless.
Right -- no vi, no emacs, no readline, no curses -- nothing that uses cursor addressing. You have to start all over. Plan 9 can be seen as an experiment to find out how much you can simplify if you can abandon backwards compatibility.
So how would that work over something like ssh or even a serial terminal. And you'd have a shell containing a lot of very platform specific code. That really breaks everything. I'd prefer to see well thought out evolutions to the ANSI escape sequence standards that solve real problems. The proposal on the original post does that for keys. Other things like bracketed paste and support for more than a few colours have seen some adoption. Some good ideas get less attention like having a stack for titlebar changes. Some things that weren't a great idea security-wise have been dropped (key redefinitions, retrieving the title).
One of the problems is that the concept behind termcap and terminfo doesn't really scale or allow for innovations. As a user of rxvt-unicode I often suffer the frustration of it being unrecognised on bare OS installs. But I respect the fact that it doesn't just claim to be xterm while emulating it imperfectly like many.
Take eshell for an example: it connects processes together in emacs and can natively support navigating to places on remote hosts, opening files there, or running (remote) shell commands.
I sympathise with you on the pain of terminfo+ssh where the remote host doesn’t have the appropriate files. But I don’t think that further piling on “standards” to terminal escape sequences is a long-term solution to terminal woes.
Perhaps it finally is time to come up with an entirely new terminal technology re-engineered from [almost] scratch based on today achievements and needs.
For a period of time near 2000 people felt like terminals were going to be abandoned in favor of GUIs so changing them didn't feel reasonable. But now it's clear that was wrong.
What do you mean, exactly, by that? Do you think that programs designed to work in current terminals (e.g., vim) should stop working with the new terminal technology? That seems a bit tough for progressive adoption. Otherwise, how do you think that these programs should be changed? Or wrapped in some intermediary "terminal emulator" so that they can run unchanged in the newer terminals?
Also, the new terminal technology doesn't necessarily have to be fundamentally incompatible with the legacy technology. It probably can be made reasonably easy to compile classic apps for any terminal technology. Many of them are compatible (although not necessarily 100% compatible) with both Linux and DOS/Windows already.
I don't have a proper overview of how these things work, but I'm a bit worried that there may be multiple layers (reprogrammable keyboard, kernel, X server, terminal, editor) trying to solve similar problems in similar ways and they might end up interfering with each other.