[HN Gopher] Things I've learned building a modern TUI framework
___________________________________________________________________
Things I've learned building a modern TUI framework
Author : willm
Score : 326 points
Date : 2022-08-03 13:24 UTC (9 hours ago)
(HTM) web link (www.textualize.io)
(TXT) w3m dump (www.textualize.io)
| rochak wrote:
| I love TUI and CLI based tools that keep me in my terminal as I
| have started to dread web applications more and more with every
| passing day. For obvious reasons, these tools have a better and
| more consistent UX since they need to rely on keyboard a lot more
| and are catered to more tech minded people. Not to mention the
| fact that they help avoid getting distracted by the endless ocean
| that is the internet.
| MaxBarraclough wrote:
| A neat FOSS project. Have to admit I was surprised to see you're
| hiring and already have 2 developers on staff besides the
| founder. Where does the money come from? Paid support?
|
| It would be good if the _What we do_ page answered this.
| asicsp wrote:
| From https://www.willmcgugan.com/blog/tech/post/textualize-is-
| hir...
|
| > _At the end of last year I took a year off to work on my
| Open-source projects and develop an idea that I believe will
| allow the terminal to eat some of the browser's lunch. Turns
| out this idea was compelling enough to attract some sweet sweet
| VC cash and I am now hiring a third Python developer to join
| the company._
| teddyh wrote:
| The question then becomes: What do _the VCs_ think that the
| money will come from?
| __tyler__ wrote:
| Textualize mention they want to make it so that you can
| deploy the same code base as a TUI and a web app. My guess
| this will be additional paid functionality that makes a
| seamless hosting experience.
| stjohnswarts wrote:
| VCs are naturally risk takers, there is a lot of VC money
| out there seeking novel projects. Maybe if textual can land
| some companies like Dell/IBM/AMD/Oracle/AWS who want
| snappier textual frontends for sysadmins rather than
| slow/clunky web interfaces for sysadmins/app admins to do
| stuff like board management controllers and textual
| dashboards for app/status monitoring stuff. Lower
| bandwidth/more dependable than web interfaces over
| slow/spotty interconnections with something like mosh.
| Seems like an option. Projects like this that add color,
| etc add a 3rd dimension to a 2 dimensional text landscape
| and I think that counts for a lot.
| teddyh wrote:
| > _Maybe if textual can land some companies like Dell
| /IBM/AMD/Oracle/AWS_
|
| And? What does "land" mean here, exactly? The project is
| FOSS, so they won't sell the software the traditional
| way. So how will they _make money_?
| vulcan01 wrote:
| Large companies tend to prefer support for any major
| dependencies, so, companies built around an open-source
| project typically sell support. Customers might also hire
| them for consulting, custom implementations using the
| project, etc.
|
| However, it's not a high-value business so it is somewhat
| surprising VCs are funding this.
| teddyh wrote:
| Maybe the VCs are quietly planning to force the company
| to make the source proprietary once they get enough
| adoption by such large companies?
| zasdffaa wrote:
| Make me happy and point me at some of these because I
| have something and can find no-one to even look at it,
| and I believe it has actual cash value.
| Lendal wrote:
| Apparently some VCs are not expecting anything back except
| karma for making needed enhancements to civilization.
| kmike84 wrote:
| The advice to use lru_cache is good.
|
| But there is an issue if lru_cache is used on methods, like in
| the example given in the article:
|
| 1. When lru_cache is used on a method, `self` is used as a part
| of cache key. That's good, because there is a single cache for
| all instances, and using self as a part of the key allows not to
| share data between instances (it'd be incorrect in most cases).
|
| 2. But: because `self` is a part of a key, a reference to `self`
| is stored in the cache.
|
| 3. If there is a reference to Python object, it can't be
| deallocated. So, an instance can't be deallocated until the cache
| is deallocated (or the entry is expired) - if a lru_cache'd
| method is called at least once.
|
| 4. Cache itself is never deallocated (well, at least until the
| class is destroyed, probably at Python shutdown). So, instances
| are kept in memory, unless the cache is over the size limit, and
| all entries for this instance are purged.
|
| I think there is a similar problem in the source code as well,
| e.g.
| https://github.com/Textualize/textual/blob/4d94df81e44b27fff... -
| a DirectoryTree instance won't be deallocated if its
| render_tree_label method is called, at least until new cache
| records push out all the references to this particular instance.
|
| It may be important or not, depending on a situation, but it's
| good to be aware of this caveat. lru_cache is not a good fit for
| methods unfortunately.
| ttymck wrote:
| Does @staticmethod run into this same issue?
| kmike84 wrote:
| No.
| Philip-J-Fry wrote:
| This is great, it feels like it's one of the better frameworks
| that is actually trying to improve the way we write terminal UIs.
|
| Seems like Textualize is coming at it from the right angle,
| abstract as much as you can away such that a widget is something
| self contained and your UIs are _actually_ composable a la web
| frameworks like React or Vue.
|
| Declarative UIs are the future. Now... When will someone make a
| Go port...
| lotw_dot_site wrote:
| One of my proudest moments during the development of "Linux on
| the Web" had to be the creation of a Terminal application (try it
| at https://lotw.site/shell) that can render its output with near-
| native efficiency. My initial attempt was based on placing
| character images, one-by-one, onto a canvas element, but it was
| horribly sluggish. Then I started playing around with a "Virtual
| Dom" (React-like) approach, wherein I convert the underlying data
| structure into an html string, and then set the innerHTML
| property of a div element, for every time the screen has to be
| redrawn. (Source code:
| https://github.com/linuxontheweb/LOTW/blob/main/root/code/ap...,
| the relevant code is the "render" function starting on line 569,
| and the innerHTML is set on line 940).
|
| I don't know how many years its been that I started working on
| the Terminal application, but it was only within the past week or
| so that I "bit the bullet" and figured out how to do finger
| pad/mouse wheel scrolling of the output buffer (See the
| 'main.onwheel' function in the source code for that little
| tidbit!). Since I required fine-grained control over the
| rendering process, I could not rely on the "naive" way of doing
| scrolling on the web (which is to simply let the browser take
| care of the entire process).
| munificent wrote:
| _> My initial attempt was based on placing character images,
| one-by-one, onto a canvas element, but it was horribly
| sluggish._
|
| I've done web-based terminal-style renders in a number of
| different ways for my roguelike [1]. I've done both DOM and
| canvas renderers. I found that the fastest approach to be:
|
| 1. Render each glyph to a canvas.
|
| 2. Only re-render glyphs that actually changed.
|
| Doing that was _much_ faster than using the DOM. I imagine I
| could go even faster using WebGL but at this point, I
| considered the performance good enough.
|
| For anyone interested, my terminal library is written in Dart
| and is open source:
|
| https://github.com/munificent/malison
|
| [1]: http://munificent.github.io/hauberk/
| jonathan_s wrote:
| Same experience here. Canvas rendering is much faster for
| terminal apps if done well. I think also VS code uses a
| canvas for its terminal because its superior performance.
| markdog12 wrote:
| It's been 357 years, and Dart still can't go full screen
| without a hack like this: https://github.com/munificent/haube
| rk/blob/master/web/main.d...
|
| https://github.com/dart-lang/sdk/issues/11506 (Jun 25, 2013)
| munificent wrote:
| That code is seven years old: https://github.com/munificent
| /hauberk/commit/2ba2f260baa7004...
|
| I should fix it to use:
| https://api.dart.dev/stable/2.17.6/dart-
| html/Element/request...
|
| I just never noticed because it wasn't causing any
| problems.
| lotw_dot_site wrote:
| If I would have continued my original approach, I probably
| would have been able to get something like that working
| pretty well, but since it is pretty hard to beat Virtual DOM
| types of approaches, I had no need to try anything else when
| rendering full screens of text could keep up with key repeat
| rate.
|
| But of course, the idea of developing a terminal using a
| standard DOM-centric approach is usually not going to turn
| out very well... though Google is an exception here with the
| hterm js library that underlies the terminal output for
| Chromebooks: https://chromium.googlesource.com/apps/libapps/+
| /master/hter.... Most Chromebook users will never have the
| opportunity to put this to use, though people like me who put
| their Chromebooks in developer mode the first chance they get
| use it _all the time_.
| navanchauhan wrote:
| Didn't look through GitHub to see if someone else has already
| mentioned the issue but it just shows a blank black screen when
| opened in Safari
|
| > Unhandled Promise Rejection: ReferenceError: Can't find
| variable: webkitResolveLocalFileSystemURL
| lotw_dot_site wrote:
| Yeah, I don't personally mess with anything but Chrome, and I
| consider supporting browsers that are not Chromium-based to
| be a fork of the entire project.
|
| Per the Disclaimer in the Github README
| (https://github.com/linuxontheweb/LOTW/):
|
| ---------------
|
| LOTW is developed in the crouton environment, which involves
| ChromeOS in developer mode. All development and testing is
| currently done on a Chromebook, using an up-to-date Chrome
| browser.
|
| The system should basically work in any modern browser and
| host OS, but there are likely many tiny glitches that degrade
| the user experience in other browsers and/or operating
| systems.
|
| ---------------
|
| The crucial fact of LOTW is that it is based around the
| concept of a full-featured, sandboxed file system in your
| browser. Only Chromium-based browsers natively support that
| kind of thing via 'webkitRequestFileSystem'.
|
| That being said, there is a shim/polyfill that is supposed to
| load and take care of that
| (https://github.com/linuxontheweb/LOTW/blob/main/www/js/fs-
| sh..., created by Eric Bidelman when he was at Google). Last
| I knew, Firefox seemed to work with it.
| ketralnis wrote:
| > I don't personally mess with anything but Chrome, and I
| consider supporting browsers that are not Chromium-based to
| be a fork of the entire project
|
| I see the ie6 world is coming back
| lotw_dot_site wrote:
| Funny, that, seeing how M$ themselves are perhaps the
| biggest contributors to the current browser codebase
| monoculture issue.
|
| Anytime a software project develops enough complexity,
| there is no shame in targeting a specific platform. Given
| enough eyes on a thing, though, those kinds of
| "supported" issues always take care of themselves.
|
| But I'm just a lone developer trying to do something
| never before done. I'm still trying to prove a concept...
| dahfizz wrote:
| Gotta love how cross platform the web is...
| Illniyar wrote:
| Everyone seems to be very excited about this framework, and while
| it looks very impressive, I don't inderstand the impetus for it.
|
| Why do I need the terminal to become an interactive visual app?
| Why not use the tools that are designed for visual interactive
| applications- like GUIs ?
| brabel wrote:
| I am on the same boat: just can't see why someone would want to
| turn the terminal into what is basically a GUI with just poorer
| graphis?!
|
| Am I completely missing something? Should I start thinking of
| replacing my desktop environment with a terminal emulator that
| does everything, including displaying images, videos, windows
| etc to gain some advantage I am unaware of?
| cwalv wrote:
| It's a least common denominator thing: there a places where
| you can easily run a terminal app but not a browser/electron,
| which are probably the next level up in the
| portability/fidelity tradeoff.
| BiteCode_dev wrote:
| - you don't need compiled dependencies
|
| - you may work mostly in the terminal and want to fire a
| quick tool: dev is a lot of that so it's great for this use
| case
|
| - it's cross platform
|
| - it works with no X so it works with ssh
|
| - it doesn't eat a lot of resources
|
| - it's fast to launch
|
| - you usually already have a cli entry point, so this is a
| natural next step. The quick script becomes really nice
|
| - it's very constrained, so devs have to focus on the most
| important things which makes the UI usually better than usual
|
| - it's a common denominator so you can generate web ui and
| native ui form that
|
| - TUI have naturally good keyboard workflow for free
|
| - it's just really cool
| mikkelam wrote:
| I honestly think this is just developers being developers. Why?
| Because it's cool. It's not more than that
| gjulianm wrote:
| Maybe you don't have access to a graphics server, or just want
| to add a small interface to a certain part of a bigger
| application/script that works in the terminal. For example, apt
| will show you TUIs sometimes when it asks more complex
| configuration questions.
| trebbble wrote:
| It's really handy if your "window manager" is actually _in_
| your terminal (say, you use tmux). Otherwise you 've got two
| layers of "window manager" to deal with--your terminal
| multiplexer, and your actual window manager.
|
| Why might one use something like tmux instead of relying on
| Rectangle or a tilling window manager or what have you?
|
| 1) The terminal is far easier to gain access to cross-platform
| than any GUI window manager, so if you can keep most of your
| workflow in the terminal, you can work just about anywhere. You
| get it out-of-the-box basically everywhere but Windows
| (assuming we mean a Unixy terminal, here, not cmd or
| powershell) but it's very easy to gain access to a unixy
| terminal there, too, these days.
|
| 2) Maybe you are constrained to the terminal for some reason,
| as in the case of a remote server that doesn't have X
| installed.
| mixmastamyk wrote:
| Works from a headless server.
|
| Cool, but I'm surprised at VC money to be honest.
| rakoo wrote:
| Because making GUIs is either native but with "complicated"
| frameworks that aren't simply cross-platform, or web-ish and
| fat with Electron.
|
| Every OS has a terminal, so every OS can render those apps.
| Maybe we'll finally get a Electron-less slack one day.
| oblio wrote:
| Now instead of supporting 3 browsers (Chrome, Firefox, Safari)
| you now have to support 5 different terminals.
|
| Though it's probably easier to fully support a different
| terminal.
|
| Interesting trade offs.
| MaxBarraclough wrote:
| Every multi-platform UI toolkit must put in the work to support
| multiple platforms, by definition.
| jacobtomlinson wrote:
| I'm so excited about textual!
|
| I started working on a TUI application over Christmas that used
| it but put it on the back burner until the css branch gets
| merged.
| fadjfadjiiitlz wrote:
| * Fortunately the Unicode database contains a mapping of which
| characters are single width and which are double. Rich (and
| Textual) will look up this database for every character it
| prints. Its not a cheap operation, but with a bit of engineering
| effort and caching (see lru_cache) it is fast enough. *
|
| A bitmap sounds suitably compact and fast. There are likely to be
| large intervals of double-only or single-only items so it may be
| even smaller.
|
| Regarding your hiring it would be nice to actually get a reply,
| and say why if you don't want a person.
| public_defender wrote:
| Has anything been built with textual yet? People here seem to be
| discussing it mostly at the conceptual level.
| andrewshadura wrote:
| I'm considering porting git-crecord to it, but the lack of
| documentation isn't particularly motivating :)
| willm wrote:
| We have a gallery of apps in
| https://www.textualize.io/textual/gallery
|
| I'm surprised how much has been done with it. The version in
| master has been stuck in limbo while we've been working on the
| CSS branch.
| nickdothutton wrote:
| It's this kind of project that makes me want to run a
| shellhost/service/"club". So much interesting stuff happening in
| the terminal these days for high-productivity individuals who are
| sick of the way the web has gone.
| mark_l_watson wrote:
| Really good that he got funding for his open source project. I
| tried Textualize earlier this year and it was really nice: easy
| to use and the UIs look great.
|
| Apologies in advance for drifting off topic: as (primarily) a
| Common Lisp developer, it makes me sad to see great Python
| projects that will never be replicated in my world. Perhaps there
| are 10,000 times as many Python developers as CL, so it is
| understandable.
| openfuture wrote:
| There's a nice TUI lib for cl that I am using for tala (my take
| on this "TUIs will eat the web" thing... datalisp.is).
| mark_l_watson wrote:
| thank you!!
|
| EDIT: do you mean cl-tui?
| tambourine_man wrote:
| Every time I see that scrolling demo my jaw drops. It never gets
| old.
|
| I've been using terminals for too long and the expectation of
| what should be possible is engrained deep.
|
| I want tmux to scroll and have hover states like that.
| [deleted]
| sebastianconcpt wrote:
| OMG you using CSS for stying the TUI??! I love this!
|
| Please tell me you can have window widgets
|
| Like a modern Turbo Vision [1] where you can drag/drop them even
| one on top of the other?
|
| [1] http://tvision.sourceforge.net/#wtv
| willm wrote:
| Yup, it's a subset of CSS of course. But you will be right at
| home if you know CSS.
|
| We support multiple layers, but we are explicitly not
| advocating windows that can be dragged around. It wouldn't be
| hard to build, but I feel TUIs should avoid the requirement to
| shuffle windows around like a desktop app.
| mixmastamyk wrote:
| Working notebook tabs should be fine in the short term. Don't
| think those were mainstream in the TV days, which was more
| the MDI era.
|
| Also, please make them look like actual tabs, which TUI and
| Web designers avoid like the plague for some reason. :-P
| chrismorgan wrote:
| I'm a little disappointed to see no mention of the problems of
| colour. Perhaps Textual is just too firmly in the camp of
| overriding _everything_ , so that these problems don't appear
| (and it just feels extremely heavily out of place instead). As a
| user of a light, high-contrast terminal, I will state that _most_
| TUIs that I use are badly executed, featuring awful ugliness,
| complete inaccessibility, or both, due to incorrect assumptions
| about colour.
|
| Terminals just have the wrong primitives for colour. It's
| irredeemably broken, needing complete replacement with an
| altogether different approach to colours, and I don't even know
| quite what that approach would be, quite apart from the
| improbability of convincing people to implement it.
|
| There are default foreground and background colours, and they
| could be black and white, white and black, or just about
| anything, really. (People speak of 16- and 256-colour terminals,
| but they're actually 18- and 258-colour.)
|
| You want to make your text stronger? Have fun. You'll look at
| your terminal that does #ccc-on-#000 or similar, and try bold.
| One some terminals, this will also change the colour to #fff, but
| on others it won't. You kind of want to, because bold-but-the-
| same-colour isn't drawing the attention you want, so you figure
| you'll set the colour to bright white. Well, now your text is
| _completely invisible_ for may light terminal users. So you
| begrudgingly roll that back and decide to try yellow. Eh, it's a
| bit dull, but not _too_ bad. You'll still get complaints from
| light terminal users, though, because although it does have the
| advantage of distinctiveness, it's _much_ lower contrast. Don't
| even think of bright yellow, because that's back to being almost
| invisible in most light terminals.
|
| Light terminal themes have to decide whether colours 8-15 mean
| "bright" (increase lightness and perhaps saturation) or "higher
| contrast" (where you _decrease_ lightness). Having played the
| game, I can report that both choices will break some things, but
| that "bright" is _probably_ the more reasonable of the two. But
| know that you can't rely on any particular direction in the
| relationship between colours 0-7 and 8-15.
|
| You think you'll get around all of this by setting background
| colours? Please don't, this just guarantees that your app will
| feel _completely_ out of place, and probably be unpleasant to
| use.
|
| You're fed up with light terminal considerations? Well then,
| perhaps you'd like some blue in your dark terminal. Pity that
| there are still widely-used terminals out there where blue so
| dark that it's almost invisible and _extremely_ hard to read. And
| even bright blue is commonly mildly painful to read. So blue's
| out for any length of text.
|
| My advice ends up: by default, you should not set _any_
| background colours, and for foregrounds you can use the default
| colour and colours 1 (red), 2 (green), 5 (purple) and 6 (teal),
| and I will graciously permit you to use colours 3 (yellow) and 4
| (blue) for no more than one word at a time (e.g. "warning:" in
| yellow). Seriously. Until the user opts into anything else, treat
| the entire thing as a five-and-a-bit-colour terminal, because
| you'll cause misery if you go any further. _Never_ use colours 0,
| 7, 8 or 15 by default without determining what they and the
| default colours are, because they may be high contrast or _zero_
| contrast. You can also use bold, which _may_ give brighter
| colours, whatever that means, but shouldn't use colours 7-15
| directly.
|
| In many terminals it is possible to determine what the default
| background and foreground colours and other colours are, and if
| you have a _really_ good reason why you want to use a bunch more
| colours you can try reading them and at least doing something
| simple like switching between a light and dark theme, but I
| recommend against that, because setting backgrounds is still just
| generally... _non-native_ is probably a decent way of putting it.
| Stay colour-neutral by default, fit in rather than standing out.
|
| This is hardly the only place terminals are using a fundamentally
| bad model. The article does talk about the problems of column
| widths, seen especially in emoji. We seriously need to burn the
| current scheme of terminals down and build something _sound_ in
| its place. Of course, this is extraordinarily unlikely to happen,
| and only stands any chance whatsoever if compatibility can be
| maintained in some way.
| eesmith wrote:
| Textual builds on Rich. Rich says this, at
| https://rich.readthedocs.io/en/latest/console.html#color-sys...
| :
|
| > There are several "standards" for writing color to the
| terminal which are not all universally supported. Rich will
| auto-detect the appropriate color system, or you can set it
| manually by supplying a value for color_system to the Console
| constructor.
|
| with options None, "auto", "standard", "256", "truecolor", and
| "windows".
| willm wrote:
| These issues are precisely why Textual uses Truecolor by
| default. It is supported on the vast majority of terminals.
| Colors are reduced to 256 (actually 240 because we avoid the
| ANSI colors) on terminals without truecolor support.
|
| 16.7 million colors gives you a lot more control over emphasis,
| and de-emphasis. You can fade foreground / background, you can
| draw subtle borders, and you can boost saturation. Many of the
| techniques that web-developers have enjoyed for years.
|
| It's true we don't make use of the user's theme, but you've
| laid bare the problems with ANSI themes. Respecting the user's
| color theme isn't going to guarantee readability (probably the
| opposite).
| simonw wrote:
| This is all great, but I particularly liked the tip here on using
| Python Fraction objects for screen positioning calculations where
| floating point errors could result in a whole extra character
| causing display bugs.
| drewzero1 wrote:
| I think I missed the point of that exercise, so I appreciate
| your brief summary. Thanks!
| ketralnis wrote:
| I miss vbdos. This used to be so easy.
| skavi wrote:
| Why don't more languages offer a zero allocation way to view a
| HashMap K V as a HashSet K.
| lilyball wrote:
| A key weakness of TUIs is the complete lack of accessibility.
| Everything is characters arranged for the eye to see, there's
| nothing at all for screen readers to use to extract semantic
| meaning.
| trebbble wrote:
| I'm having trouble imagining how to solve this in the terminal
| itself--there a way to pass information to a screen-reader via
| some kind of side channel?
| cbm-vic-20 wrote:
| Most of these modern TUIs don't work on real "glass" terminals.
| Sure, nobody uses them anymore. I asked one of the Charm
| developer relations people if their stuff worked on old-school
| terminals like the VT-420, but they'd never even heard of that,
| didn't know what it was. Of course, the VT-420 came out before
| they were born, but still...
| azinman2 wrote:
| Do you use a VT-420?
| dragontamer wrote:
| > The first trick is "overwrite, don't clear". If you clear the
| "screen" and then add new content, you risk seeing a blank or
| partially blank frame for a brief moment. It's far better to
| overwrite the content in the terminal entirely so that there is
| no intermediate blank frame.
|
| > The second trick [...]
|
| > The third trick [...]
|
| This is pretty hilarious to consider when coming from Win32API.
|
| Its traditional to clears the window before showing anything on
| Win32. Clearing the window happens so fast that you shouldn't see
| a flicker, even as the mouse moves over your window (each pixel
| your mouse cursor moves, Win32API will clear the window to its
| background, redraw the window (erasing the old mouse pointer),
| and draw the mouse pointer in the new location.
|
| This "TUI needs to be overwritten, not cleared" idea seems quaint
| and slow. Win32API was drawRect(background color) for decades on
| ancient 386 machines and fast enough to deliver a good
| experience. Why is a 80 x 24 terminal window so much slower?
|
| > In Textual the layout process creates a "render map". Basically
| a mapping of the Widget on to it's location on the screen. In an
| earlier version, Textual would do a wasteful refresh of the
| entire screen if even a single widget changed position. I wanted
| to avoid that by comparing the before and after render map.
|
| Win32API creates and maintains the "invalidRect", the rectangle
| that needs to be re-rendered from scratch (ie: draw-calls called
| upon the hierarchy of "windows" from the background to
| foreground, in order , to make the overall window look
| unchanged).
|
| Not only from mouse-cursor movements, but also as other windows
| "move" ontop of your window, or Clippy's speech bubble disappears
| (if you remember that little UI from the 90s version of Microsoft
| Word).
|
| And again, this needed to be done every time the mouse moved one
| pixel, to erase the old mouse cursor (aka: redraw the entire
| window from scratch "over" the old mouse cursor, making it look
| like you've erased it) and redraw the mouse cursor on top of the
| fresh coat of paint. It was an incredibly common operation even
| in 20MHz 80386 land from the early `90s.
|
| There's just no way a modern terminal is that slow, unless
| there's a billion layers of vsync / refreshes going on. There's
| definitely something wrong going on IMO here.
|
| > Unicode art is good
|
| This is true. Heck, ASCII art / symbols are often good enough to
| do many, many things.
|
| There's something wrong with the terminal model at the
| fundamental level if you're a couple of magnitudes slower than
| the 1980s. I can't say I'm an expert on TUI (or guis for that
| matter), but... this whole blog post is kind of a horror story
| IMO.
| willm wrote:
| Win32API was designed to render a GUI from day 1. The terminal
| protocol pre-dates Windows and wasn't designed with modern
| hardware in mind. It's not that it is slow per se.
| dragontamer wrote:
| A 1920 byte (80x24x1-byte each) character window shouldn't be
| having performance problems on modern systems (ie: seeing
| blank-characters or whatever) when a 1080 x 1920 x 4-byte ==
| 8MB desktop completes any execution faster than the eye can
| see on 30 year old hardware (blank, redraw, scale, etc. etc.)
|
| Something, somewhere, is flushing the screen and waiting for
| V-Sync, or something like that. You can write a 2D Canvas or
| even 3D world (involving the reupload of entire geometries
| each frame) that executes faster in Javascript compared to
| this 80x24x1 byte TUI window.
| willm wrote:
| It's not a "performance" issue, it's a protocol issue. One
| which is largely solved with the synchronisation protocol.
| Workarounds are needed for older emulators.
| badsectoracula wrote:
| > Its traditional to clears the window before showing anything
| on Win32. Clearing the window happens so fast that you
| shouldn't see a flicker
|
| That is not due to speed but due to Windows API being smart
| with clipping regions/rectangles to only allow pixel updates in
| damaged regions (e.g. uncovered parts of a window as you move
| it). Note that nowadays this only happens inside windows as
| toplevel windows are composed via DWM in an offscreen buffer.
| Windows also tries to doublebuffer window drawing updates to
| avoid flickering. However in Win7 (with DWM -aka Aero mode-
| disabled) and earlier you'd be able to see flickering by, e.g.
| resizing windows with complex UIs.
|
| Also the "tradition" here isn't to clear the window but to
| invalidate the regions that were damaged so that the next
| update (which does clear the window) only affects the damaged
| regions instead of the entire window. This was most common
| during the 90s and early 2000s though, at some point computers
| and memory were fast and big enough to do double buffering
| during paint events (which in some cases you still need to do
| when working with GDI) to avoid visible flickering - and
| nowadays most common flickering issues are solved by Windows
| themselves doing it via composition.
|
| > even as the mouse moves over your window (each pixel your
| mouse cursor moves, Win32API will clear the window to its
| background, redraw the window (erasing the old mouse pointer),
| and draw the mouse pointer in the new location.
|
| This is what Windows did until Windows 3.1 (and you could see
| the cursor flickering when, e.g. a control drew itself while
| the cursor was over it) but with Windows 95 the system composed
| the mouse cursor to avoid that flickering. However nowadays
| (and for a long time now actually) the mouse cursor is drawn by
| the GPU as a separate hardware plane on top of the screen
| contents. All Windows do in that case is to send the cursor
| image to the GPU and set the registers that specify the plane
| (cursor) position whenever the mouse moves - no drawing takes
| place.
| dragontamer wrote:
| > All Windows do in that case is to send the cursor image to
| the GPU and set the registers that specify the plane (cursor)
| position whenever the mouse moves - no drawing takes place.
|
| On the contrary. The modern GPU has so many buffers that its
| constantly recalculating every pixel with custom code pixel
| shaders (transparency and everything) every frame, maybe 60
| FPS or faster.
|
| Yeah, the CPU doesn't do any of that bit-blit stuff anymore.
| But the GPU does that constantly every frame, over-and-over
| again to compose modern windows. VRAM is 500GBps for a reason
| on modern GPUs.
|
| In either case, "blanking" the screen and redrawing it is a
| fundamentally fast operation 30 years ago, let alone today.
| Today's computers are so much faster that there are layers of
| custom-programmable parts running on 2 different processors
| (CPU passing data to GPU over PCIe) every frame.
|
| 4GB+ VRAM buffers on the GPU allows the GPU to save off some
| work of course, but there's an incredible amount of
| calculations that occur on every pixel of every frame 60
| times a second today.
|
| --------
|
| In any case, a pure-text, maybe ASCII (or Unicode) window
| shouldn't be having these issues.
| wolpoli wrote:
| I feel like these TUI projects are popping up as a rejection to
| the modern mobile first GUI. They are keyboard driven, have no
| pictures, have clear borders between sections of the app, and are
| truly focus on the content.
| badsectoracula wrote:
| The linked video looks like it follows mobile/web styling
| though, it feels like if you could run a modern mobile-first
| web site through elinks. Sure there aren't pictures (which is
| really the least of modern GUI issues) but everything looks
| "flat" with big sizes (e.g. scrollbars) and aside from
| background color there isn't any other distinction between
| elements. Compare this with, e.g., the Debian textmode
| installer (which i guess is based on the Newt TUI library) or
| the console version of Yast in openSUSE (which is based on
| libyui, itself using ncurses for the console backend). In those
| the elements are very clear (though Newt's buttons are a bit
| too big IMO), scrollbars are thin (perhaps too think for
| libyui) and everything has a clear border.
|
| Also no scrolling areas inside scrolling areas, which is always
| annoying.
|
| [0]
| https://news.softpedia.com/images/reviews/large/debianinstal...
|
| [1] https://documentation.suse.com/sles/15-GA/html/SLES-
| all/imag...
| nisegami wrote:
| Textual seems to be the right fit for a project I just started,
| but I have some concerns about its maturity and longevity. I feel
| better about both after reading the post (and seeing the call for
| applicants at the end despite the economy). Maybe I should just
| jump in.
| idomi wrote:
| There are so much stuff you could do with it right?
| forrestthewoods wrote:
| I'm sad that Python is so slow it needs an LRU cache for trivial
| math operations like computing the overlap between a pair of 2D
| rects.
| jorgenbuilder wrote:
| I have to say that my immediate reaction is "why the *#%# would
| one want to render a gui in a terminal"
| mixmastamyk wrote:
| Uses 1/100 the resources of a modern GUI, maybe 1/1000 of an
| electron app. Works over ssh.
| mixmastamyk wrote:
| I like this, seems to be the answer to the promise of Urwid.
| Unfortunately the main developer of which left for a long time
| once it hit 1.0. It was enough to build a widget toolkit, but
| didn't get proper widgets implemented for long enough that I lost
| track.
|
| I wanted to build an CUA terminal editor with one of these for
| decades but micro is recently good enough. So am cheering on in
| spirit.
| baobob wrote:
| Does Textualize have a good example application? I was impressed
| by the demos (moreso that the company is somehow funded!), but I
| couldn't find any actual real world application using it yet.
|
| Also reliance on the mouse in the demos made me feel a bit
| queasy. Anything involving overriding the default mouse semantics
| in a terminal window can go straight to hell
| willm wrote:
| We have a [gallery](https://www.textualize.io/textual/gallery)
| of Textual apps, although largely using the older version on
| Textual/
| shrubble wrote:
| For full-on terminal nuttiness, see the demo video (and it is
| like a demoscene video) at https://notcurses.com . Someday I will
| figure out how to use that library...
| robocat wrote:
| Semi-pornographic soundtrack to the demo makes it feel rather
| non-professional to me ("penitrate my face" is not what I want
| to hear at work).
| shrubble wrote:
| Apologies, I watched the video but didn't catch that.
| kevin_thibedeau wrote:
| > Fortunately the Unicode database contains a mapping of which
| characters are single width and which are double.
|
| This doesn't work for all emoji. Some are categorized as
| ambiguous width and their rendered width is system dependent.
| dahfizz wrote:
| This is really cool! I was impressed by the demo. I would be sad
| to see this replace a more "traditional" cli/tui, but for highly
| complex command line applications like qemu this is really
| awesome!
| BiteCode_dev wrote:
| I really like this trend of "making the terminal great again".
| Between rich/textual in python and lipgloss/bubble tea for
| golang, this turns cmd from "the default ugly stuff that is easy
| to produce" into "something fun and pretty".
|
| Also note that those projects have the (not anymore) secret goal
| to also produce a web app from the same code base automatically.
|
| I imagine native will follow, or wasm, or something.
| Nevertheless, having the terminal as the smallest denominator for
| UI makes a lot of sense for small utilities. You won't build the
| next Figma with it but a lot of scripts could benefit from that.
| mastry wrote:
| Agreed. I cut my programming teeth on the Dr. Dobbs/Al Stevens
| "D-flat" series which was a text-based windowing system in C.
| Some of the most fun I've ever had programming. The hardest
| part was waiting for the next issue to be published!
| password4321 wrote:
| I've tried to find the most recent version of that library,
| even emailing the author, but he's long since moved on and I
| could only find bits and pieces.
|
| Maybe https://archive.org/details/dflat is best now?
| mr_tristan wrote:
| The general workflow I'm finding useful is to generate a ton of
| simple logs, ingest all those logs into a SQLite database (that
| acts like a "data lake"), and then use the customized REPL to
| generate some charts (typically .png files), CSV, or ascii
| reports.
|
| I could see using a REPL to generate a TUI, e.g., "run a query
| and generate your own `top`". This seems like it could be a lot
| easier than trying to generate a PDF, interactive Excel, or
| complex HTML report (which usually means a bunch of
| javaScript).
|
| There's something about text interfaces that just fundamentally
| "flows" from most programming environments.
| zokier wrote:
| I feel the opposite, these kinds of projects imho are just
| moving terminals away from their key benefits, being simple,
| predictable, brutally functional with no gratuitous animations
| or flourishes, allowing no-hassle adaptation to any colortheme
| and font.
|
| Indeed, if all the features of modern graphical/web
| applications are dragged into terminals, then what is the point
| of using terminal anymore instead of native graphics/web?
|
| Furthermore the CLI proponent in me is saddened seeing this
| being largely another step away from CLI tools, although
| strictly speaking its true that the technology doesn't really
| define the interaction model.
| gjulianm wrote:
| > Indeed, if all the features of modern graphical/web
| applications are dragged into terminals, then what is the
| point of using terminal anymore instead of native
| graphics/web?
|
| It's not "all the features", but just being able to build a
| basic interface without too much trouble is a blessing.
| Several use cases:
|
| - The most important: you don't have access to native
| graphics/web. A lot of people still need to work with remote
| servers where installing X is not viable and you can't access
| web ports.
|
| - Simplicity. For simple interfaces, it's far easier to just
| use the terminal with an extra Python dependency, than it is
| to create a regular UI that will require a graphical server,
| graphics libraries and such. A web interface would be even
| harder to do.
|
| - Easy adding interfaces to existing scripts. In fact I used
| textualize precisely for this, a script that launched some
| long running tasks, and I wanted to check the progress and be
| able to stop/throttle them. Launching a simple interface was
| easy enough, the rest of the script is still a regular Python
| script, but for that situation it just pops up a TUI.
|
| Also, it's not like TUI apps are new. A lot of terminal
| applications will launch a TUI sometimes because it's just
| easier. See for example some configuration dialogs for APT.
| tcoff91 wrote:
| Another great thing is that they are keyboard driven.
| Keyboard driven computing is far more powerful than using a
| mouse for many things.
| zokier wrote:
| TUI apps are not inherently more keyboard driven than GUI
| apps. Indeed, if you look at the demo video linked in the
| article, majority of the interactions are done with
| mouse.
| willm wrote:
| Textual supports both keyboard and mouse control. But we
| are aiming for a keyboard-first interface, which I feel
| is a better fit for terminals.
| zasdffaa wrote:
| Powerful? you mean it can do more than is actually
| possible to do with a mouse?
| agentwiggles wrote:
| Power is the amount of work done over a period of time,
| so even if you can do the same exact set of things with a
| mouse and keyboard, if the keyboard is faster at doing
| them, it's more powerful.
|
| You can do all your text entry by clicking keys on an on-
| screen keyboard if you like, but saying that a physical
| keyboard is a more "powerful" way to enter text seems
| reasonable to me.
|
| (sorry in advance, I know this is needlessly "well
| ackchually" lol)
| zasdffaa wrote:
| > but saying that a physical keyboard is a more
| "powerful" way to enter text seems reasonable to me
|
| No. It's _faster_ and that 's all. So call it by that
| word which is very precise.
|
| If you say 'power' = 'speed' then you've destroyed the
| meaning of one of those words, just for the modern habit
| of co-opting a fancier word for a simpler one. I'd prefer
| people didn't do that, and differentiated 'speed' from a
| thing you call power which indicates "I can't do that at
| all, at any speed".
|
| If you don't like bullshit marketing and PR, don't follow
| it.
| Sparkle-san wrote:
| If we go by the physics definition power is work over
| time, so the same work over a shorter time is by
| definition more powerful. I don't think applying that
| term to software is inherently wrong.
| [deleted]
| clucas wrote:
| Interesting, so do you avoid describing one programming
| language as being "more powerful" than another? They're
| all Turing complete, after all... it's just a question of
| how fast you can develop in one, right?
| zasdffaa wrote:
| Good question, 'power' I reserve for turing completeness
| (some aren't, such as SQL before recursive CTEs were
| added, and... well, here's a list
| https://iq.opengenus.org/non-turing-complete-programming-
| lan...)
|
| For "how much crap do I have to write to get it to do
| something", I call that expressivity. Scala is more
| expressive than fractran (I guess...).
| robertlagrant wrote:
| What's the case for power equals Turing completeness over
| power equals speed of development?
| clucas wrote:
| Sounds like you are consistent with your usage of terms,
| and I understand the logic and the motivation.
|
| I would just caution that it's fairly idiosyncratic -
| plenty of people out there don't use the word "power" the
| way you do. For example, here is how Paul Graham talks
| about the "power" of programming languages:
| http://www.paulgraham.com/avg.html
|
| Just saying, as consistent as your definitions are
| internally, being too rigid about it may hinder your
| ability to communicate with others in the field. Good
| luck buddy <3
| zasdffaa wrote:
| Thoughtful reply and it is much appreciated dude, take
| care!
| [deleted]
| layer8 wrote:
| One benefit is that you can operate "blindly", without
| needing the hand-eye-coordination feedback loop. This
| tends to make frequent operations more automatic and
| decrease cognitive overhead.
|
| Another benefit is that keyboard input is higher-bandwith
| than mouse operations. Imagine a mouse-only interface for
| everything you can do on the Linux command line, or all
| the operations you can do in Vim or Emacs (beyond actual
| text input).
|
| It's more powerful in the sense of "power user".
| mark_l_watson wrote:
| Well said! I do a lot of my work over SSH or Mosh with tmux
| to remote servers. Projects like Textualize fulfill a real
| need here. Another cool hack: using a terminal backend for
| matplotlib to get inline plots while working via SSH/Mosh.
| jonpalmisc wrote:
| I agree. Seeing the next generation of terminal apps that
| often seem to use "pretty" and "fancy" output formatting
| (read: "non-parseable" and "overly-decorated") makes me sad.
| Plain, simple, human-readable, and machine-parseable output
| can't be beat in my mind.
| capitol_ wrote:
| More and more terminal apps come with a --json parameter,
| so that their output can be easily machine parseable.
|
| Cramming output intended for humans, and output intended
| for data transfer between processes into the same format
| makes the lives of both groups of recipients worse.
| dymk wrote:
| Human-readable and machine-readable: not the same thing in
| the general case.
|
| Hence -porcelain and friends.
| mrighele wrote:
| Not all console programs are meant to be batch tools whose
| output needs to be piped and parsed.
|
| Sometimes you need an interactive tool and you may want to
| run then in a console.
|
| Emacs is an example
| bigyikes wrote:
| I think there's room for two categories of terminal apps.
| "Library" apps, and "User" apps.
|
| Library apps are intended to be consumed by other terminal
| apps, or by advanced users. User apps are strictly intended
| for humans.
|
| Take ffmpeg as an example. This is an excellent "library"
| app, so much that there are many actual libraries that are
| thin wrappers around it. It's incredibly versatile.
|
| Do I want to interact with ffmpeg, though? For one-off
| tasks, no, I'll just fire up VLC or some other tool instead
| of reading the ffmpeg man pages.
|
| Friendly, stylized, non-parseable, "user" terminal apps are
| a comfortable middle ground between hard-core "library"
| apps and full-on GUI apps.
| diarrhea wrote:
| Git follows this model as well, calling it porcelain and
| plumbing (the internals). Arguably, there's a third layer
| in actual GUIs wrapping the porcelain (and sometimes
| plumbing).
| Beltalowda wrote:
| ffmpeg specifically is a bit of an outlier; together with
| some other tools like qemu.
|
| For the rest of things, you can go a long way by just
| aligning things nicely, indentation, wrapping/indenting
| properly according to the terminal width, and maybe
| adding a bit of bold text which is both easily parsed by
| machines _and_ human readable.
|
| I generally think these are often considerably more user-
| friendly than outputting 6 different colours - half of
| which don't work well on many background colours so it's
| unreadable - assuming the terminal is 290 characters wide
| - many tools these days seem to think you've got
| infinitely wide screens - and all the other things these
| "modern" things do.
|
| Something like "df" is a simple but classic example; GNU
| df at least aligns nicely no matter the column sizes
| (some other dfs, like NetBSD df, don't) and that's still
| easily used by machines _and_ humans. Maybe -h should be
| the default though (which would break scripts, so it can
| 't be changed for /usr/bin/df, but in an ideal world...)
|
| Basically, you can have your cake and eat it too.
| zozbot234 wrote:
| > I feel the opposite, these kinds of projects imho are just
| moving terminals away from their key benefits, being simple,
| predictable, brutally functional with no gratuitous
| animations or flourishes
|
| This stuff is not "new" at all. It's just the latest twist on
| the ANSI art of old, and the use case is similar.
| smolder wrote:
| I still use IRSSI as an IRC client, running in a screen
| session, through SSH, from multiple machines or even from my
| phone. The TUI in gnu screen over SSH setup is really handy
| for securely accessing a continuously-running application
| from anywhere you happen to be. I could use irccloud or some
| other web based thing, sure, but I like hosting my own
| services and having auth and device whitelisting uniformly
| handled the SSH way. Yet a chat client doesn't work well as a
| set of CLI commands as opposed to a TUI. Email from TUI might
| not be too bad either. There are lots of cases where I think
| it'd fit.
| wiseowise wrote:
| Nobody forces you to use them.
| BiteCode_dev wrote:
| Ah but that's the best part about TUI, you can fall back on
| the cli when you don't want the whole burrito.
| spicybright wrote:
| Well, sticking with the analogy you're falling back to a
| taco made from different ingredients rather than just a
| part of the burrito. That can be intrusive if they decide
| to put chicken instead of ground beef in it.
|
| More concretely, it's using a totally different tool to get
| a subset of functionality you want vs other solutions.
|
| Personally I don't see a reason why one would do that, but
| more power to you if you do. If anything, ordering the taco
| sometimes is going to give you a more refined palette than
| if you got the same burrito each time (i.e. more experience
| in the problem space you're working in).
|
| (I'm getting hungry now...)
| stjohnswarts wrote:
| .... if the tui app includes the functionality.
| leejoramo wrote:
| As someone who started out using pre-PC micro-computers
| (TRS-80, Apple ][, CP/M), I often would like to have access
| to a good suite of what we now call TUI programs.
|
| Having a common TUI would be a bonus, which briefly existed
| back in Borland's heyday.
| woodrowbarlow wrote:
| in practice, i rarely see a tool that _only_ offers a tui.
| most tui tools i encounter will respond helpfully to a
| `--help` flag and let me do anything i need from a script.
| any tool that doesn 't is nearly useless - i don't think this
| is lost on most cli app developers, and i don't think it's at
| odds with the quest for 'pretty' UIs in interactive mode.
| icedchai wrote:
| I feel the same. Simple ANSI color is enough. Call me old
| school, I don't want emojis in my terminal.
| cauefcr wrote:
| With emojis you usually also get unicode, which is great
| for all the non-ascii-languages out there.
| shreyshnaccount wrote:
| imagine cross platform apps that work just as well on phones,
| and built using this type of almost scripting like code. (check
| out pywebio too)
| ludston wrote:
| Like a Web browser?
| shreyshnaccount wrote:
| yes, minus the Javascript.
| K0nserv wrote:
| I wrote[0] something similar to the first part of this post a
| while back for one of the AoC 2019 puzzles. However, it didn't
| strike me that you can represent each frame as a set and use the
| difference to figure out the resulting render commands, that's
| super neat.
|
| Something strange that I found was: If you redraw only two
| characters in the terminal, neither iTerm nor macOS's terminal
| would render the update. In my solution I always rendered some
| characters redundantly to get around this.
|
| EDIT: I went back and looked at this code again based on the
| insights from this blog post and figured out a few more issues I
| had and fixed them.
|
| 0: https://hugotunius.se/2019/12/29/efficient-terminal-
| drawing-...
| silon42 wrote:
| The biggest problems with terminals are: - some terminals support
| escape sequences that can do bad stuff (like when you accidentaly
| 'cat' a binary file - keyboard support is severly limited,
| especially regarding the Esc key and the modifiers.
| ilc wrote:
| People underestimate this. But you are very right.
|
| I'll give a small story from my distant past:
|
| I went to a college with Sun IPCs and IPXs. It turns out, if
| you make the terminal beep on one, it is the HIGHEST priority
| thing the machine can do as far as we could tell. So when
| someone sent someone else, 2 megs of ^Gs via some mechanism
| usable in the 1990's, and recipient is sitting in the middle of
| a cathedral computing center. The machine literally will beep,
| and beep, and you can't stop it.
|
| That is a lot of bleeping, beeping. They had to power the poor
| machine off. Since I've used visual bell on every terminal
| program I use. Since I've turned on Virtual Bell in every
| terminal emulator, and I don't trust much on a terminal.
|
| May a terminal emulator author read my cautionary tale. (Before
| you ask: No I was not the user involved.)
| wrycoder wrote:
| Back in the day, this was called feeping creatures.
___________________________________________________________________
(page generated 2022-08-03 23:00 UTC)