[HN Gopher] Things I've learned building a modern TUI Framework
___________________________________________________________________
Things I've learned building a modern TUI Framework
Author : willm
Score : 174 points
Date : 2024-08-11 12:22 UTC (10 hours ago)
(HTM) web link (www.textualize.io)
(TXT) w3m dump (www.textualize.io)
| emrah wrote:
| In case you missed this: Casey vs Windows terminal
| https://news.ycombinator.com/item?id=27725559
| emrah wrote:
| > The first trick is "overwrite, don't clear"
|
| This is how games were written back in the day before DirectX was
| a thing. You'd write directly to the frame buffer and instead of
| clearing and redrawing, you'd redraw what changed and what was
| around and under it (because there was no time to refresh the
| entire view in time in addition to everything else you need to
| do)
| Neywiny wrote:
| I learned this from ComputerCraft programming. It's become
| applicable many times since then, occasionally professionally.
| But, the ability to tell the terminal when it's starting/done a
| frame is a lot more powerful IMO.
| moring wrote:
| There were at least two other techniques back then.
|
| The first is to write to another buffer (possibly in normal
| RAM, not video RAM), then when the frame is done copy the whole
| buffer at once, so every pixel gets changed only once.
|
| The second is to write to another buffer that must be in video
| RAM too, then change the registers of the graphics hardware to
| use that buffer to generate pixels for the monitor to show.
|
| They had different tradeoffs. Copying the whole buffer when
| done was expensive, changing an address register was cheap. But
| the details of the register were possibly hardware-dependent,
| and there was no real graphics driver framework in place. Also,
| to just "flip buffers" (as changing the address register was
| called), rendering to the off-screen buffer meant sending
| pixels to video RAM, which was (IIRC) slower to access than
| normal RAM (basically a NUMA architecture), so depending on how
| often a pixel gets overdrawn, rendering in normal RAM could be
| faster overall even with the final copy taken into account.
| CBarkleyU wrote:
| > But the details of the register were possibly hardware-
| dependent, and there was no real graphics driver framework in
| place
|
| Did this change with 3dfx's Glide (or subsequently Direct3D
| once Windows got a foothold into the gaming industry)?
| traverseda wrote:
| My big complaint with textual is that it wants to be react. I can
| see why it would want to be react, that's a very popular
| framework that a lot of people are already familiar with, but I
| don't think it's actually a good way of doing user interfaces.
| But the basic reactive design is a well trod road, and basing
| your system design on something that's known to work is a great
| way to derisk the project. Sure, we'll draw some heavy
| inspiration from react.
|
| Alright, so we're using some bastardization of CSS as well? That
| might be going a little bit too far. The react model already
| breaks the idea of CSS in a lot of ways, preferring standardized
| components. Sure, developers still use CSS to customize
| components, but I view that more as a side effect of how react
| evolved rather than as a justifiable architectural choice. But as
| long as you don't _have_ to use CSS I suppose it 's fine.
|
| Last I tried it, you do have to use CSS. There are no good
| standard components, so you will be making your own, and instead
| of having components be one nice self encapsulated Python class
| the standard docs use things like list components and then style
| them with an external style sheet.
|
| For those reasons textual just isn't for me yet. In python there
| should be one, and preferably only one, obvious way to do
| something. By mirroring react so closely they're also mirroring
| what I see as the JavaScript communities biggest vice.
| itronitron wrote:
| Can you elaborate on how textual wants to be like the react
| framework? I don't see React (or react) mentioned anywhere in
| the article.
| traverseda wrote:
| They have a virtual DoM
| https://textual.textualize.io/api/dom_node/
|
| This includes a lot of what you'd expect from HTML, classes,
| CSS, etc.
|
| They have reactive attributes
| https://textual.textualize.io/guide/reactivity/
|
| It has HTML (or at least a DoM), css, and you design widgets
| the same way.
| willm wrote:
| > They have a virtual DoM
| https://textual.textualize.io/api/dom_node/
|
| It's not a _virtual_ DOM. It 's not technically even a DOM,
| because there is no Document. The name has stuck, which is
| why we went with that. Technically, its a tree. One of the
| most common data structures used to represent a UI, and
| predates React by decades.
|
| > This includes a lot of what you'd expect from HTML,
| classes, CSS, etc.
|
| It has CSS in common with HTML. classes are pretty much
| required for CSS. That's not "a lot". But why shouldn't a
| UI framework borrow concepts that work for, you know, User
| Interfaces?
|
| > They have reactive attributes
| https://textual.textualize.io/guide/reactivity/
|
| Reactives attributes are very useful concept to manage UI
| complexity. And again, not exclusive to React.
| kragen wrote:
| this sounds like you're elaborating on _why_ textual
| wants to be react rather than rebutting the assertion
| _that_ textual wants to be react. but nobody was saying
| that wanting to be react was unreasonable
|
| hmm, well, i guess traverseda was sort of saying that
| react was bad. i doubt that's a widely shared opinion tho
| willm wrote:
| I only meant to rebut the factual claims made in the
| previous comment. Textual is inspired by web development
| (and I've always described it as such), but "want to be
| react" is way overblown. It has things in common with
| React, but equally many other web and UI frameworks. Heck
| you could say that Textual wants to be JQuery, and that
| would be just as apt...
| kragen wrote:
| maybe it depends on what the implicit reference class is.
| if you're comparing it to react, angular, ncurses,
| s-lang, jquery, vue.js, and php, then sure, things like
| html and css are hardly react-specific. if you're
| comparing it to ncurses, s-lang, win32, mfc, the vic in
| the commodore 64, winforms, whiptail, dear imgui, the
| tms9918 used in the msx, emacs lisp markers and text
| properties, gtk, the nintendo ppu, opengl and glut, xlib,
| xt, tcl/tk, ansi.sys, naplps, ripscrip, turbovision,
| direct access menu.exe, and react, it's basically exactly
| the same thing as react
|
| jesus, i sure have built shitty user interfaces on a lot
| of platforms
| yunohn wrote:
| How is it more like jQuery than React?
| itronitron wrote:
| Thanks, it seems like people tend to say react, or reactive
| attributes, when they are describing model-view-controller
| (MVC) patterns.
| willm wrote:
| > Last I tried it, you do have to use CSS.
|
| You don't _have to_ use CSS (actually you never did). Every
| style can be set in code, and the docs have CSS + Python
| equivalent for every style.
|
| > There are no good standard components
|
| I guess its been a while since you checked
| https://textual.textualize.io/widget_gallery/
| traverseda wrote:
| Yeah, it does seem like things have changed a lot since I
| last used it, which I think was probably a few years ago.
| Time flies.
| actionfromafar wrote:
| I want a way to embed a terminal (it doesn't have to support a
| myriad terminal emulations, only one) inside a graphical
| program. MacOS first, but other platforms would be nice.
|
| So, imagine a normal GUI window, but one of the components in
| it is a terminal window. Is there something like that?
|
| Or should I just use mono font text view?
| yoavm wrote:
| I don't see how it is trying to be React; It definitely tries
| to use concepts from HTML and CSS (and perhaps even some JS?),
| but I actually found that it allowed me to move very quickly as
| I didn't need to learn a whole new UI system from scratch. I
| didn't need to create any component of my own, and CSS is
| something I already know. If anything, like I wrote in another
| comment, the slight layout differences and deviation from CSS
| is what sometimes got me a little confused.
| nine_k wrote:
| If you think that react (and FRP in general) is not a good way
| to build UIs, what is, in your opinion?
| sesm wrote:
| I don't agree that React is FRP. FRP is a generic solution
| that builds data-UI synchronization around data, and assumes
| that incremental UI updates will be written in UI code. React
| puts data-UI synchronization code inside UI components and
| provides an Immediate Mode-like API to avoid writing
| incremental updates in UI code.
| spencerchubb wrote:
| Interesting that they're hiring. I'm curious how they plan to
| make money from a TUI framework
| itronitron wrote:
| the jobs link gives a 404 error
| __float wrote:
| This post 2 years old, it seems they have filled their open
| roles :)
| ynniv wrote:
| He mentioned eventually running on the web, so my guess is to
| facilitate migrating old TUIs. There's plenty of consulting
| money in maintaining old enterprise software.
| tyre wrote:
| Yeah same question. It looks like they're building some pretty
| cool software, but engineers are expensive and other frameworks
| exist.
| rivo wrote:
| It's funny how every TUI developer eventually stumbles over
| Unicode and then handling international characters and emojis
| correctly turns into its own project close to the same scope of
| (or even bigger than) the original TUI project. It happened to me
| on rivo/tview and through the resulting rivo/uniseg package, I
| learned that all other TUI library maintainers deal with the same
| issues. Finally, everyone invents their own unique solutions to
| the problem because character width is not standardized and
| terminals are messy, as noted in the article. OP simply supports
| Unicode 9 only (Unicode is at version 15.1 at the moment). Sooner
| or later, users will complain, however, that certain emojis or
| international characters are not rendered correctly. So I'm not
| sure that this is a great solution.
| roland35 wrote:
| Are there any libraries in place which can normalize all emojis
| down to a single symbol?
| kevindamm wrote:
| It's a design decision. On one end, if I'm reading your
| question correctly, you could use 0xFFFD (the replacement
| character) for anything not recognized as language-specific
| characters in the BMP and SMPs (this can be done within
| practically all existing Unicode libraries by filtering on
| character class) which will inadvertantly filter some non-
| emoji symbols and doesn't really convey any information (it
| can even look unprofessional, it reminds me a lot of the
| early web during the pre-unicode growing pains of poorly
| implemented i18n/l11n).
|
| There are libraries like Unidecode[0py] [0go] [0js] which
| convert from unicode to ASCII text that might be easiest to
| include in a TUI. All the ones I looked at will convert emoji
| to `[?]` but many other characters are converted to that,
| too, including unknowns.
|
| On the other end you can keep a running list of what you mean
| by emoji[1] and pattern match on those characters, then
| substitute for a representative emoji. But it will still pose
| some difficulty around what to choose for the representative
| symbol and how to make it fit nicely within a TUI. An example
| of a library for pattern-matching on emoji is emoji-test-
| regex-pattern[2] but you can see it is based on a txt file
| that needs to be updated to correspond with additions to
| Unicode.
|
| [0py]: https://github.com/avian2/unidecode
|
| [0go]: (actually there are a few of these)
| https://pkg.go.dev/github.com/gosimple/unidecode
|
| [0js]: https://github.com/xen0n/jsunidecode
|
| [1]: these aren't really contiguous ranges, and opinions
| vary, see
| https://en.m.wikipedia.org/wiki/Emoji#Unicode_blocks
|
| [2]: https://github.com/mathiasbynens/emoji-test-regex-
| pattern
| estebank wrote:
| There's a "trick" that works somewhat well for some
| compound emoji like "family": replace ZWJs with whitespace.
| Emoji width is not standardized because it depends on
| platform, fonts available, shell and terminal emulator,
| _but_ almost no terminal supports compound emoji correctly.
| Because of how they were designed, most terminals will
| print the emoji as its component parts. If you need to do
| something like underline a piece of text (like rustc has
| to) we decompose them ourselves, and then it is a more
| tractable problem to know what the width of a char is (0, 1
| or 2, and var width for tabs, which we just transform to a
| hardcoded 4--incorrect but usable). This can still be
| incorrect, on specific terminals, but works well enough on
| most.
| rockorager wrote:
| The state of the art here is to detect mode 2027, and enable it
| when supported. This lets you know the terminal will handle
| graphemes properly.
|
| I maintain two TUI libraries which use this technique and emoji
| support has been (nearly) great. (One of which uses your uniseg
| library!)
|
| https://mitchellh.com/writing/grapheme-clusters-in-terminals
| sweeter wrote:
| really great read, thanks. Im a little disappointed that no
| terminal emulator both implements the Kitty image protocol,
| and mode 2027. I wish there would be a terminal project that
| would just pick the best standards we have at the moment. Im
| not a fan of sixel for a lot of reasons. Im looking forward
| to trying Ghostty, though.
| rockorager wrote:
| Ghostty has both mode 2027 and kitty image protocol
| eNV25 wrote:
| wezterm has both according to the above article
| lynx23 wrote:
| Anyone old and naiv enough to share this observation: Almost
| everything I looked at _after_ TurboVision was inspired, but
| actually not really finished. Once you take the toolkit for a
| ride, you realize its kind of cute but unfinished. Maybe another
| way of looking at this is to call many of the TUI frameworks I
| say "opinionated", whatever that exactly means.
|
| I am likely just dense and uncreative, but the truth is, when I
| switched from DOS to Linux in the 90s, I was never again as
| productive as I happened to be with B800. Granted, it likely took
| me a long time to understand the need for double buffering and
| the difference between a local/direct text mode vs a terminal,
| let alone escape sequences. But still. Whenever I tried to do
| something directly in ncurses, I pretty much gave up due to a
| distinct feeling of being unhappy. Completely different to what I
| was able to do with the simple ideal of B800.
| thechao wrote:
| I learned GUI programming using win16, then win32 -- this
| would've been during the transition to WinXP. I must have a
| city-wide blind spot, but every post message pump GUI framework
| has left me completely befuddled. One thing I never understood
| was how these OO frameworks helped to really solve the
| multithreaded UI issues. In Win32, I just threw the main
| renderer into a thread, then had support renderers build models
| "on the side", and then updated the difference. The code never
| really got out of hand.
| dualogy wrote:
| I get what Turbo Vision is (was), but what's that B800 thing?
| Surely you aren't talking about a Celeron processor? Seems
| tricky to google, also no Wiki page on that. You got me
| curious, plz spill it! =)
| anothername12 wrote:
| Ok I think he's referring to 0xB800, the VGA text buffer
| segment in real mode.
| vetinari wrote:
| In real mode addressing and graphic card in text mode, your
| video memory started at absolute address 0xb800:0x0000. It
| was an two-dimensional array, where you could poke and
| whatever you changed here, was reflected immediately on the
| display. Each element of the array was two bytes: character
| itself and color attributes.
| lelanthran wrote:
| 0xb800 is the address of the framebuffer for text. Simply
| write characters to that address, using offset `((row *
| width) + col)` and they'll appear on screen.
|
| In graphics mode it was, IIRC, 0xa000. I once wrote a pacman-
| type easter egg inside the point-of-sale system[1], because
| doing direct graphics straight to an address is so easy and
| simple.
|
| [1] Was removed after pilot and before actual release.
| ynniv wrote:
| If you're going to run kitty it can do a lot more than that:
| https://m.youtube.com/watch?v=ft1Q-DwGWIs
|
| https://notcurses.com/
| nine_k wrote:
| I prefer WezTerm over Kitty, because of the Kitty's author
| attitude towards feature requests and even pull requests. And
| yes, you can do graphics on both, using the same protocols. If
| you really need graphics, a terminal is hardly a right
| solution. It's occasionally useful for tiny stuff like icons
| though.
| cocodill wrote:
| Humanity needs more TUI tools
| miki123211 wrote:
| As a screen reader user, reading this post makes me want to
| scream.
|
| If you care about accessibility even one bit, for the love of
| god, please, don't use any of the features this post mentions.
|
| Things like animation or unicode diagrams break screen readers in
| horrible ways.
| willm wrote:
| I would love to improve support accessibility for TUIs. Textual
| internally keeps a browser like DOM structure, which means it
| could in theory offer browser-like support for screen readers
| while keeping all the features offered to sighted user. But it
| would require a protocol to allow the app to send structured
| information so that the screen reader has more to work with
| than a matrix of characters. AFAIK this doesn't exist.
|
| The most promising way forward for accessibility is the web
| support for Textual. It would be possible for the app to work
| with the browser to make highly accessible TUIs.
| blooalien wrote:
| > Textual internally keeps a browser like DOM structure,
| which means it could in theory offer browser-like support for
| screen readers while keeping all the features offered to
| sighted user. But it would require a protocol to allow the
| app to send structured information so that the screen reader
| has more to work with than a matrix of characters.
|
| Isn't it possible to expose this content via a publicly
| accessible API that screen readers could simply hook into?
| BTW, thank you _so very much_ for Rich and Textual. Wonderful
| tools. Love 'em.
| willm wrote:
| De nada!
|
| > Isn't it possible to expose this content via a publicly
| accessible API that screen readers could simply hook into?
|
| Definitely possible from a technical standpoint, but I
| don't know of anyone who has done that. Maybe one day,
| Textual could provide that solution.
| ericwood wrote:
| It's more in the Rust ecosystem but AccessKit looks
| really promising from this standpoint. I'm not sure if it
| could work in the context of a TUI but it might be a
| great starting point!
| https://github.com/AccessKit/accesskit
| miki123211 wrote:
| > Definitely possible from a technical standpoint
|
| Yes and no, it would be possible, but only if the
| terminal emulator, the operating system's accessibility
| API, the screen reader and the library supported it. The
| library needs to output the right information via escape
| codes, the terminal emulator needs to expose it via the
| OS API, the OS API needs to have support for it, and the
| screen reader needs to know what to do with the
| information. I believe you could wrangle the existing
| a11y APIs and make it work, but you'd still need to
| implement support for it in emulators, libraries and
| screen readers. Not to mention that you'd actually have
| to design the standard and write a spec for it.
|
| This would be slightly easier to do for terminal screen
| readers, which run directly inside a terminal emulator
| (kind of like Tmux) and pass most commands and keys
| unmodified, generating speech in the meantime.
| miki123211 wrote:
| > AFAIK this doesn't exist
|
| I have complained about this not existing many times and at
| length, and have actually been thinking about how such a
| think could work.
|
| It's a great idea, but we'd need support both from screen
| readers, TUI libraries and some terminal emulators, and I
| don't know if we could get that to happen.
| kbouck wrote:
| This TUI discussion triggered a bit of 80s/90s programming
| nostalgia -- anyone remember TTT (TechnoJock's Turbo Toolkit)?
| Pre-gui era UI framework.
| RunSet wrote:
| > I use monodraw for these diagrams. Monodraw is MacOS only
| unfortunately, but there are no doubt good alternatives for other
| platforms.
|
| https://github.com/Nokse22/ascii-draw
| mikkelam wrote:
| Why do software engineers care so much about TUI? I really don't
| get it. I love a good command line program. But TUI just doesn't
| appeal to me.
| willm wrote:
| Each to their own. But running apps over SSH is a big plus. And
| some folk, like myself, enjoy the snappy keyboards focused
| experience that perhaps GUI apps could offer, but typically
| don't.
| pjmlp wrote:
| I guess, mainly because of nostalgia, back from the days TUIs
| were the only way to interact with computers.
|
| Turbo Vision, curses and dialog were cool back in the 1990's.
|
| Having started with computers in 1986, I really don't get the
| TUI fetisch, not even remote access is an issue, given X
| Windows, VNC, RDP, Citrix,... exist for decades.
| nine_k wrote:
| Having run X programs over network connections quite a bit,
| I'd say that they make sense for graphics stuff, and textual
| interfaces over SSH are significantly more responsive.
|
| But once a fixed-width text grid stops being the right tool
| for the job, it's likely better to have a web UI.
| pjmlp wrote:
| I used xterm for such purposes.
|
| Yes, I do agree the browser is the new X Windows / RDP
| client, on the modern timesharing systems.
| fastasucan wrote:
| Its great for running things in a terminal where you want more
| of a user interface than a CLI. Sometimes a TUI is faster and
| gives better oversight than a CLI.
| habitue wrote:
| It's the other ubiquitously installed cross-platform GUI
| toolkit other than the web.
|
| Additionally, it has a hacker aesthetic. The styling is
| aggressively not separated from the content, and the styling
| knobs are pretty limited, so tui apps kind of converge on a
| single style. That style reminds us of hacker movies and cool
| sci-fi shit :)
|
| It's not loved by corporate designers. Companies don't make
| sales based on their TUIs (to either businesses or consumers).
| So without those commercial pressures, tuis are designed by
| developers for developers.
|
| Because of this, the meme of tuis self-reinforces. Developers
| see and use TUIs, notice that they are usually tools built with
| developers in mind, and then want to go on to make their own
| TUIs.
| electroly wrote:
| There isn't much obvious benefit in using TUIs, but _writing_
| TUIs has a big upside: it 's easier in most ways. It's
| trivially cross-platform, you don't have to make pixel-perfect
| GUIs (because it's impossible), you don't need icons or
| graphics (because you can't show graphics), etc.
| bogdan-lab wrote:
| This TUI looks pretty, but I cannot imagine situation, when I
| would actually use it and be ready to pay for it. Probably I am
| not living in a right environment for it. But in my experience,
| either people are happy with something truly minimalistic or they
| try to please a user with GUI right away.
|
| For example, YouTube link in the article showed a possibility to
| display table with highlighting cells. Why would I need that as
| TUI? Probably if I want to navigate through table with
| highlighting active cell I would also need a bunch of other stuff
| and eventually I would need a proper GUI.
| seeknotfind wrote:
| One reason to prefer textual UIs is that you can use them from
| any computer anywhere fast (no slow video VNC). Also, if you
| are already using a terminal, then improving that experience is
| nice. There is a big enough market there for this company.
|
| However, I'm not sure what a "proper" GUI is. Terminals have a
| widely used open standard. These protocols are more standard
| and interoperable than any GUI framework, and they are
| supported on every system. Once you add video in there, close a
| few more gaps, I think competing with the browser, or bringing
| the full computer experience to the terminal is reasonable.
|
| Obviously if terminals add something like video, it's "copying"
| rendering pipelines from "proper" GUIs, but making the terminal
| experience better, which could also be viewed as bringing UNIX
| zen to GUIs, if it makes it big, you'll love it too! <3
| mrweasel wrote:
| It does seems niche at this point. One scenario I can see is
| where you want something more user friendly than pure CLI and
| where providing a web UI might be too risky for some reason. A
| TUI could allow users to SSH in to server somewhere and just
| have TUI app as their shell. It's a bit contrived I grant you
| that.
|
| Personally I found Textual a little weird to use, but better
| than ncurses. Though it didn't really yield what I wanted. I
| like the old mainframe style TUI application, those already
| struck me as being wildly efficient.
| halfcat wrote:
| The use case is something like medical billing entry where
| people are trained to know all of the billing codes and they
| still use an AS400 green screen console.
|
| The employees work by keyboard shortcuts and are extremely
| efficient, and every time someone tries to replace the AS400
| with a modern web app, their productivity drops 100x.
|
| It's the same scenario as a vim/emacs wizard vs a slick looking
| GUI that doesn't have keyboard shortcuts.
| tyre wrote:
| The solution to manual medical billing is to have computers
| do the billing. The system can be configured via GUI with
| rules about billing codes, payers, DX codes, etc. and then
| the rest of the system Just Does It.
|
| (I work at a company automating medical billing.)
| hggh wrote:
| (2022)
| yoavm wrote:
| I've used Textual to build a quick Swedish-English dictionary
| that runs in terminal but also works using touch, when using the
| laptop as a tablet and on my Android phone. It was a pretty
| smooth experience and was very fast to get something working. The
| TCSS layout system thing is a little strange, but only because I
| automatically expected it to be CSS and obviously that doesn't
| really work in the terminal.
|
| https://yoavmoshe.com/blog/learning-swedish-with-sway-and-an...
| troupo wrote:
| On emojis I highly recommend "Emoji under the hood"
| https://tonsky.me/blog/emoji/
___________________________________________________________________
(page generated 2024-08-11 23:00 UTC)