I fell for the hype that Textual always gets on HN and actually used it for a mid-sized commercial app a few months ago. I figured it was a 'safe' choice, given all the developers here who seem to like it, and it was the only TUI library I could find with corporate backing. Here are my notes.
1. Considering it has actual paid developers working on it for quite a while and VC funding, it still lacks a great many features that I took for granted in all the non-commercial TUI libraries, e.g. menus and dialog boxes.
2. The async nature of the library is unpleasant. Can never be sure when/where your code will run.
3. Lots of 'magic' Python variables and methods that you have to override, but there's no way to discover them in your IDE through the type system.
4. Using CSS for laying out a TUI app makes no sense (unless you are a web developer and have Stockholm syndrome from using it for web apps?)
5. It seems to leak memory.
Eventually re-wrote the app from scratch using a different library that gets far less hype and spends no time marketing itself. The result was much better in every way.
> 4. Using CSS for laying out a TUI app makes no sense (unless you are a web developer and have Stockholm syndrome from using it for web apps?)
Fun fact: CSS had, since CSS 2.0, the media type ‘tty’, for use in media queries targeting text browsers like links or lynx or such:
@media tty {
body {
max-width: 80ch;
}
}
With the powers of flexbox and grid and a limitation on those new character-based lengths I could imagine an alternative future with TUIs in a CSS layout.
But afaik ‘tty’ has never been implemented and as such never been used. In CSS Media Queries Level 4 all media types outside of ‘all’ and ‘screen’ have been deprecated.
(Also observe the note: “it is expected that all of the media types will also be deprecated in time, as appropriate media features are defined which capture their important differences.” Although features are a technically superior approach, replacing print in this way is never going to be particularly practical or pragmatic. I’m not convinced they’ll ever get to that point, and am confident they will never take the same deprecation route for ‘print’ as they have for the rest, making them never-matching (and ‘all’ and ‘screen’ are certainly not going to get that treatment).)
When did you try it out? Textual is still at zero-ver but has come a long way recently.
You can build menus and dialogs with Textual with a little effort, but you are correct that there is no explicit builtin widgets for those yet. The type of apps we've been building are more like web-apps than desktop apps, which is why we've eschewed the classic menu bar and drop down menus. But I'd expect to see both in the widget library (https://textual.textualize.io/widget_gallery/) soon.
I don't know what you find unpleasant about async. Personally I enjoy async. But you barely need to use async with the current iteration of the API. See this example in the docs https://textual.textualize.io/guide/widgets/#attributes-down No async or await in sight.
Re "magic methods". I guess you mean the message passing system, which uses a naming convention rather than names defined in a base class. This is because you can send arbitrary messages from one widget to another, and if we didn't use a naming convention you would have to implement your own dispatch method anyway. Yeah, the downside is that tooling might not pick up on `on_click` and similar messages but the convention is staightforward enough.
CSS makes a lot of sense to lay out a TUI. You can get a dynamic layout up and running in minutes, and refine the UI by tweaking a few lines. It lets you iterate faster, and separates the logic in your app from the presentation. Similar benefits to the browser.
I'm not aware of Textual ever leaking memory. If there was a memory leak, I'd make it a priority to fix.
Hey Will, thanks for building Textual! I'm using it in a simple side project and really enjoyed using Textual. However, I do feel that the magic methods used in the message passing system and reactive system are questionable, especially in large projects.
You recently renamed the widget "Checkbox" to "Switch" in a newer version. I easily did a rename in my single file app. But imagine that someone built an extremely complicated TUI app containing dozens of files, you can easily miss a rename, which won't be caught by any static checking tools and only result in runtime error.
I had fun building simple apps using Textual, but I probably won't use it to build any complicated TUI apps. I feel that IDE/static checking tools unfriendly magic may directly hurt Textual adoption because it doesn't work with automated tasks like refactoring, and that prevents people from using it in large projects.
Related to #1 you mentioned, to me Textual looks just ugly - like if someone thought it wasn't enough for desktop GUIs to be infested with mobile phone UIs, it also has to be the terminal apps too.
Like, hell, their examples have some *HUGE* buttons, starting with a calculator app that is all buttons - who is going to click on those? The calculator-with-buttons barely makes sense for desktop GUI apps (it was helpful back in the 80s when everyone had a physical calculator on their desk to help see the metaphor of the "virtual desktop" and it is arguably helpful on touch screen devices today for obvious reasons, but on a machine with a keyboard it is superfluous), let alone TUIs.
If you want to see a TUI that actually looks good (though a bit too much on the fancy side, but it doesn't pretend to be something it isn't) check btop:
What coldtea mentioned, the examples in the site you linked look better (well, most of them, some still use these pointless gigantic buttons). And the thing is every time i see the Textual linked here, it isn't with screens/examples like in the site you linked but with screens/examples like in the official site linked above.
From what i see the screenshots in the site you linked at are from programs made by others instead of Textualize themselves, so perhaps they should take a note of how the people who actually use their library and make TUI applications style their programs and redesign theirs accordingly.
>2. The async nature of the library is unpleasant. Can never be sure when/where your code will run.
>3. Lots of 'magic' Python variables and methods that you have to override, but there's no way to discover them in your IDE through the type system ...
Python libs can and do use dunder method overrides, operator overloading, and so on. If it was common to rewrite the AST, or have other action-at-a-distance, I'd give this some credit, but those are still century old PL features, and well specified mechanisms, not something one can't reason about.
Python I find to be (and I'd say most find it to be, hence its popularity on fields like Physics and such, even by non-programmers by trade) one of the easiest languages to read programs in and understand their intent.
Which exacly library, say of the 100 most commonly used ones on Pypi to keep this focused, is particularly problematic?
Exact same experience I had. I would also add that the CSS styling doesn't really work. And it's frustrating because I would prefer if it didn't work all time, but it seems to only not work some of the time and I can't figure out the algorithm of when it doesn't work.
I tried to use urwid too and gave up. Python needs a library as good as ftxui for C++
> unless you are a web developer and have Stockholm syndrome
Reminder that “Stockholm Syndrome” is not only universally invoked as a dismissive, thought-terminating cliché, it was also literally invented out of a whole cloth for just that purpose, as a pretext for dismissing legitimate criticism by a person with significant responsibility for the decision being criticized.
ld: library not found for -liconv
clang-13: error: linker command failed with exit code 1 (use -v to see invocation)
`clang' failed in phase `Linker'. (Exit code: 1
I’m not sure that’s really accurate. I found the API rather unpythonic, with lots of use of magic variables and things.
The only criticisms above that really apply to Python are the async nature, and that’s only because getting async right in Python frameworks and libraries is hard, it is possible though, Django being a great example.
Textual is fantastic, and with all the recent widget additions, provides functionality on-par with Go's Bubble Tea[0] / Bubbles[1] combo.
The Textual blog[2] is a great place to keep up with new features, along with interesting articles about problems encountered (and solved) during development.
Incidentally, Textual[3] is also the name of a very popular open-source[4] IRC client for macOS
Textual keeps coming up — a perennial favorite on Hacker News. But I have yet to encounter high-quality TUI applications that use it. Why is that? Maybe I've messed them and people can post their favorites.
Judging only by the screenshots it feels like this library is embracing the same "modern" design as mobile apps. Huge buttons, lots of whitespace everywhere.
I use terminal apps precisely because I want a lot of information density and responsiveness.
But perhaps the screenshots are not comprehensive enough to show what it can do.
I really like Textual. I'm very much the TUI type, and upon discovering it, I decided it would be my go-to for interfaces going forward, as - ideally - I'd be able to run the same apps on my desktop as my home server as my cloud servers.
Well on the latter two, I realized I had a huge uphill battle, as SSH apparently uses CRLF over LF, and I was finding myself having to rewrite half the library to accommodate that.*
And on the former, it occurred to me that I hate everything about Python's asyncio. I'm sure that'll anger some, but sorry, it's terrible, and it doesn't help that every major version deprecates something in favor of something new.
[*] Any advice here would be welcome. I can't find much literature on the subject.
Should've been more clear - I've had to update significant portions of Textual and rich to enable propagating custom line-endings from the top level, but most of the code I touched was in rich.
As for the CRLF/LF issue, I paired textual with AsyncSSH, and was successful in making an SSH service hosting the app. However, connecting resulted in a text soup that I initially assumed was the fault of AsyncSSH. After some time, I realized it was due to the line-endings being defaulted to LF by rich (a reasonable decision in any other scenario.)
On both points, I'd be happy to share some snippets, but I'm halfway around the world from my home computer currently. If this is more than just a passing interest, I'd be happy to follow up upon my return.
Same, but I only run Debian-flavored Linux, so that theory was ruled out pretty quickly. It appears to be a default behavior of pseudo-terminals leftover from the days of yore, when CRLF/LF was still an open debate.
I don't really know why this post is appearing now given textual is already at version 2 and not a new thing, but I love love looovve textual. Alongside rich (also from textualize) its one of those rare libraries that I can't find a single thing I'd change in it.
i invite you change my view: there is absolutely no reason to fetishize the terminal. it’s a shitty interactive window with needless constraints. anything you can do in a tui can be done better in an actual graphical window.
GUI apps are ever more bloated and often aren't written for power users (many shortcuts etc). Sure they can have all those things, but they don't. Also, UI designers are really strong trend followers meaning their apps will waste a lot of screen real estate and are often white on light gray right now because that seems to be the current fashion.
Also running apps remotely with a simple and fast interface is often really a big plus.
This submission is about a library for building TUIs, though- what I was getting at is that as developers, we can choose to instead build guis and we’ll get better results.
I do agree with you that many gui apps are poorly built and bloated.
At least for me, apart from all the other obvious reasons to use a TUI, a big part of it is the fact that it's so much easier to get a coherent and consistent user interface with TUIs compared to GUIs. Every GUI uses a different UI system and as such will look incoherent with other apps. Just take GTK vs Qt.The UI of my daily machine looks extremely coherent and most of that is contributed to most of my programs being CLI or TUI.
How? Every single TUI app i have on my system has its own look and feel, down to even using different keys for the same or similar tasks. At best a few have vi-like hjkl keys for movement (but no number prefix) and some might use ? for showing the available keys or some sort of help, but there is pretty much zero consistency beyond that.
At least in comparison the overwhelming majority of GUI applications agree on things like what Ctrl+C/X/V, Backspace, Del, Arrow, etc will do and they tend to react the same when you press the left mouse button on something that vaguely resembles a push button or a check box (most also agree how scrollbars work, though not all of them).
You could, but it's not exactly a great comparison. Contrast with Apple's history of HIGs and similar for a company that puts effort into consistency. Where's the equivalent in the TUI?
I am not a huge fan of the TUI(Graphical terminal application) But I do think the CLI(an App you control only via a command line) is the better interface method for many application. mainly because they provide the highest code ratio of any methodology. That is, you get more interface with less code using a cli than any other method
But one thing I love about terminal applications is how nice they work on remote sessions.
> anything you can do in a tui can be done better in an actual graphical window.
Almost certainly. But for whatever reason, most GUIs created happen to be really bad at the things that most TUIs I've used happen to be really good at, namely searchability, reflowability (mostly used to increase text size and change font face for legibilit), and keyboard navigation.
GUIs that nail these things are delightful. They're highly accessible and extremely efficient to use. But it also seems to me like the full power afforded by GUI toolkits leads a lot of developers to pour a lot of time and effort into other things (which matter less, at least to me, personally) while totally neglecting those aspects of their apps.
I’d suggest that the proliferation of software with many possible interactions adding features that let you invoke actions via a command-line like interface (see Ctrl+P command palettes etc) prove that there is a place for these sorts of interfaces. Using a mouse is inefficient, and there are only so many hot keys one can assign and learn.
I agree that terminals are fetishised a bit, and I personally find a mix of GUIs and terminals to be the most effective combination, but I think there’s something valuable in the interaction pattern.
nothing is stopping gui programs from using keyboard shortcuts though. vs code and emacs use them to great effect. and there’s no quirks with the alt key.
As I said though, there are only so many keys on a keyboard, and only so many combinations one can learn, which is why command palette style interfaces have become so popular.
In VSCode there are probably ~1000 actions I can perform, and maybe ~50 keyboard shortcuts that I use, but I can still access all those actions quickly and fairly efficiently. This shows the value of command line interfaces.
My point is not that terminals themselves are good, but that there's clearly value in a terminal-style interface where commands are input instead of buttons clicked.
The original comment was suggesting that the value was outdated, but I think command palettes are a good counter-example.
The biggest problem with GUIs is that there is no reliable standard that works everywhere. The VT100 standard is 45 years old and will most likely work for the next 45 years. It is dead simple to implement GUIs (just write to stdout) and all those programs that use that protocol to render their GUI are immediately portable to almost every platform on the planet and work over the network via ssh without any additional need for programming.
All non-electron terminals have better latency story than cross platform GUIs. Surprised you mentioned Emacs here as it is notoriously laggish in this department.
It's very nice that Textual has a text input widgets. Seems like many TUI libraries have widgets, but lack one to handle text input. So you have to implement this yourself over and over, often forgetting shortcuts people expect (e.g. ctrl+a/e).
According to its official website, Textual lets you get a dynamic layout up and running in minutes and refine the UI by tweaking a few lines. It separates the application logic from the presentation layer, making it easier to maintain and test your code. Textual supports UI elements such as buttons, text boxes, and menus.
The top comment is several paragraphs of reasoned comment about the features the poster tried and found lacking in the library
If you have experience of the library, which I guess you do to arrive at your conclusion please share it - what was crap about the library. What context was your experience? What could be improved (even maybe the top posters decision - you can't improve it just try something else).
1. Considering it has actual paid developers working on it for quite a while and VC funding, it still lacks a great many features that I took for granted in all the non-commercial TUI libraries, e.g. menus and dialog boxes.
2. The async nature of the library is unpleasant. Can never be sure when/where your code will run.
3. Lots of 'magic' Python variables and methods that you have to override, but there's no way to discover them in your IDE through the type system.
4. Using CSS for laying out a TUI app makes no sense (unless you are a web developer and have Stockholm syndrome from using it for web apps?)
5. It seems to leak memory.
Eventually re-wrote the app from scratch using a different library that gets far less hype and spends no time marketing itself. The result was much better in every way.