From 384e2e40dc5b5497d2d6863f2716aac8b4052a7e Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sat, 19 Aug 2023 19:08:25 +0200 Subject: add the tui article --- src/tui.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/tui.md (limited to 'src/tui.md') 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 ``, 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 -- cgit 1.4.1-2-gfad0