diff options
author | dzwdz | 2023-08-19 19:08:25 +0200 |
---|---|---|
committer | dzwdz | 2023-08-19 19:08:25 +0200 |
commit | 384e2e40dc5b5497d2d6863f2716aac8b4052a7e (patch) | |
tree | 6b7ee38a007f912eafd338554fca5a251a69125e /src/tui.md | |
parent | a31e70cc51ad197d01ccb09d5da85b9b74798c0d (diff) |
add the tui article
Diffstat (limited to 'src/tui.md')
-rw-r--r-- | src/tui.md | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/src/tui.md b/src/tui.md new file mode 100644 index 0000000..5b23336 --- /dev/null +++ b/src/tui.md @@ -0,0 +1,110 @@ +--- +title: On TUIs +date: 2023-08-19 +--- + +I'm using a relatively modern terminal emulator. +It has snappy native scrolling, with e.g. great touchpad support. +I can search the scrollback with a single hotkey. +The way I navigate and use it is consistent across all cli utilities. +That is, except TUIs. + +## scrollback +Most TUI programs---IRC clients, (web/gopher/gemini) browsers, mail clients---use +custom scroll widgets, as opposed to just printing all the data and +letting the terminal handle scrolling. + +If you're using them over ssh, scrolling turns from something your terminal +can do instantly, to something that requires a roundtrip for each unit scrolled. +This makes them painful to use on high latency connections, which would otherwise +have enough bandwidth to just transfer all scrolled text. +It also breaks touch support, as you lose pixel-wise scrolling, and the lag +makes it harder to predict the length of a scroll. + +Every program has its own bespoke set of hotkeys, so you lose out on consistency. +Some programs have vi bindings, some don't. +Some don't even support arrow keys. +Search support will differ, too, with a slightly different implementation in +each program that supports it. + +You already pretty much need scrollback and search for regular shell usage, though. +Even if you're using a "dumb" terminal, you're probably using something like +tmux to provide that. +Why, then, should programs reimplement what's already provided for you by the terminal? + +One common reason is top/sidebars. +The terminal protocol we use is too primitive to express multiple windows, so +scrolling a program with a sidebar ends up looking wrong. +It's a tradeoff, sure, but IMO +the benefits of using the terminal's scrollback outweight the benefits of sidebars. +In most cases, you don't really need them: + +* Some IRC clients have sidebars with the list of open channels, users, or a topbar with the topic. + They're not really used too often, and they can always be checked with a single command. +* Mail clients have sidebars with the inboxes. + It's useful to see the amount of unread messages in each, but that could be printed on startup. + After that, there's no need to keep the inboxes on screen when you're not actively switching between them. + +I'm not saying top/sidebars are useless. +They're great in *true* GUIs, where using a sidebar doesn't mean you're no longer allowed to use native widgets. +Sadly, terminals are much dumber than that. +If you want to use them well, blindly copying GUI conventions isn't the way to go. + +## improving the situation +The tradeoff would mostly be gone if terminals were extended to allow GUI-like subwindows. +I believe that was one of [notty]'s goals. +[rio] *sort of* supports that, too. + +## line editing +Speaking of [rio], it had some good ideas. +One of them was the "output point". +It separated the program output from your current input. +Instead of directly sending your input to the program, it let rio function as a line editor. + +It had autocompletion, utf8 support, and gracefully handled program output during editing. +If the program sent some text, your input was moved out of the way. +If the program erased some text (`\b`), your input was moved back to the available space. + +Going back to the status quo---this is actually pretty hard to achieve, if you're +not also reimplementing a scroll widget. +If you want to input and output text at the same time (think netcat, or an IRC client), +your two options are: + +* Use Readline as a base. It doesn't support asynchronous output so you'll have + to [implement that on your own][rlwrap]. +* Use [linenoise]. Hopefully you didn't need utf8 support, as [until recently][yhirose] +none of the utf8 forks supported the asynchronous API. + +Similarly, just as with custom scroll widgets, line editing over a high latency +connection *hurts*, because you need to do a full roundtrip for each character typed. + +Also, some utf8 characters have ambiguous width. Only the terminal knows how they +will be rendered, so, if you want your line editor to be fully correct, you'd +have to poll the position after each such character printed. + +Doesn't this suggest that line editing would be better handled on the terminal's end, as in rio? + +### appendix: autocompletion +How would autocompletion work if line editing was implemented in the terminal? +rio was limited to autocompleting paths, but here's my idea for a more general +approach: + +When a program with support for autocomplete starts, it'd send an escape code +to notify the terminal that it can use autocomplete. Similarly, it'd disable +autocomplete support when launching another program, or quitting. + +On `<Tab>`, the terminal would send the current, incomplete, line wrapped in +another set of escape codes. The program would recognize that, and respond +with a list of possible completions, potentially also informing the terminal +that it can request more. + +## tldr +1. Scrolling through TUI sucks. +2. I wish terminals handled line editing. + + +[notty]: https://github.com/withoutboats/notty +[rio]: https://man.cat-v.org/plan_9/1/rio +[rlwrap]: https://github.com/hanslub42/rlwrap/blob/master/src/readline.c +[linenoise]: https://github.com/antirez/linenoise +[yhirose]: https://github.com/yhirose/linenoise/pull/1 |