What value does this messy method to reimplement GUI bring?
What value does this messy method to reimplement GUI bring?
If you want to integrate your TUI program more tightly with the terminal emulator it's running in, how about you rip out those half a dozen layers of abstraction and indirection and compatibility with half-a-century-old hardware that nobody produces anymore, that sit in between your program's display logic and the actual pixels on the screen? You can keep the grid-of-characters display style, but e.g.:
- implement text selection that works in sub-frames
- give your program an icon
- support key combos like Ctrl+Shift+F
- display an inline picture
...all while removing hundreds, probably thousands of lines of code.
GUIs UI conventions never became that powerful, and new GUIs don't even follow most of the useful UI conventions. That's so generalized a problem that the newest GUI toolkits don't even have native support for a lot of the GUI conventions.
That said, yes, without a doubt you can make a GUI that is as usable as a random TUI. You can even make it work well over ssh. And even get shorter code after it's done. You will just have a hard time communicating you did that to people.
Yes, that's unfortunately the status quo. TUI's main saving graces, and the reason why it's actually a popular choice for modern apps, are:
- It works everywhere (once you solve the portability quirks, which are present both at OS level and on each different terminal emulator)
- The API is simple and stupid (paint a character here)
- There's only this many things you can do, so you don't over-engineer your UI
- Accessibility. Screen readers are guaranteed to work (but lack a11y context)
I wish there was a simple and stupid, portable GUI framework that had all of these qualities, without the unnecessary historical baggage. htop or ranger are actually pretty good apps, just wish they weren't chained to an emulator.
The baggage may be unnecessary, but I think the key to the success of TUIs is that the terminal’s interaction mechanism is restrictive. To accomplish this in a similar way in the GUI, I think you need to design a toolkit that intentionally constrains the rendering target and input mechanisms that the GUIs can take advantage of. You might end up with something better, but I think it will be very reminiscent of current terminal emulators.
You could make app launchers with links that run other apps, and even non terminal people would want to use it.
I like to think that software developers are very smart people, and only need a little nudge to steer in the right direction. If all you have is PutRune(x,y,r) and intentionally omit PutPixel(x,y,p), you'll indeed just make a worse terminal emulator.
Any decent UI toolkit focuses on a high-level description of the user interface (that's how you get a11y, basic keyboard navigation, etc almost for free), and only provides the low-level operations as escape hatches. This has to be the default route, even for complex or highly customized interfaces (spreadsheet, DAW, etc).
I think our nudge could be direct support for terminals as a fallback rendering backend. Best of both worlds: you get a well-behaved GUI app, that you can also use over a serial console (with gradual loss of functionality) if things get dire.
I wonder how useful screen readers are in curses-style applications (I don't have any experience with screen readers)? Sure, it can probably read it, but applications like this is essentially just a screenful soup of character blocks. It sounds like it'd make for a very tedious screen reading experience.
High usability is also illustrated by the original post - you can't even switch to a TUI app properly!
A huge part of why I keep my workflow 100% terminal / TUI is because I know I can use anything with a solid shell (even my iPad or my phone) and instantly have my full workflow exactly where I left off with every single program looking and working exactly the same in exactly the same state.
Of course, so does a web app with port forwarding, or ssh -X with a bit of a bandwidth hit.
The other nice thing is that when I want to run Neovim, I start an app called Neovim. Not FNvim or Neovide or glrnvim or any of those other things. Neovim. It's a closer match to my intent and I don't have to try to remember some weird app name when I just want to edit code.
Which apps do you use actually it for?
> when I want to run Neovim, I start an app called Neovim
That's what aliases are for (or you could rename the binary?)! Or you could just bind it to shortcut+E for Edit and forget the name of the editor as you'd never type it The last trick could also solve the Cmd+Tab issue as you could set it up to open the in-terminal-editor, and it'll always be faster vs tabbing
P.S.
By the way, do you know the app https://github.com/sveinbjornt/Platypus that can generate app bundles on a Mac?
neovim, mutt, tig, weechat
> That's what aliases are for (or you could rename the binary?)!
Unfortunately, it's not that simple on macOS for app bundles. The human readable name of the app bundle really doesn't matter that much to the operating system -- it's the contents of Info.plist that matter. In order to have a separate app that can be Cmd+Tab'd to, you have to have a separate app bundle, separate app bundle identifier, etc. There's really not a way around it on macOS that I've seen.
(And to be clear, aliases do work on the command line. I'm talking specifically about GUI apps - which is my primary method of separating my different activities. Terminal emulator tabs are not good enough.)
This also doesn't solve the performance problems with any of the various GUI applications, nor does it solve my problem for other applications that I want to run.
> By the way, do you know the app https://github.com/sveinbjornt/Platypus that can generate app bundles on a Mac?
I do! I tried this route first, but it falls apart when you start a GUI application from the script that you supply to platypus. If your script is e.g. `wezterm start`, it'll just start up another instance of a wezterm-branded GUI app in addition to the wrapper app that Platypus spits out.
I meant you could edit the existing bundle for, e.g., FNvim, and change it's bundle id/name/icon to whatever you want instead of having to re-create a bundle for a weztermed neovim (aliases would only work for the launching part)
> but it falls apart when you
That's unfortunate
That doesn't solve it in a generalized way though, which is what I was going for here.
I also like the fact that it's hard to build a terminal application that needs a mouse. I don't want to touch a mouse if I can avoid it, so I run them. A personal computer is too powerful to operate with a single finger.
There's the low resource aspect too. Sure, you can build a TUI that hogs resources, but there's a culture of not doing it, and it's harder to do it even if you try. Contrast that to modern GUI software where it's like the developers look at the minimum requirements as a speed limit, that is, the bare minimum you have to use.
You might've forgotten due to no use, but mice don't use only 1 finger, and they don't prevent keyboard use either.
The comparison to some general GUI state also doesn't make sense - that class of software is miles ahead of the TUI in terms of functionality, so you'd need to limit the comparison to apps that are functionally similar
And sure, having a mouse doesn't preclude you from using a keyboard, but GUI applications are so mouse focused it's impossible to use most of them without a mouse. The 1 finger comment was hyperbole, but it's close enough to true.
I use various buttons and wheels and gestures and click sequences (LR switch tab left, RL switch tab right) and buttons-as-modifiers on a mouse, so not even remotely close
The other point is repeating the same generalization mistake, "most of them" don't even exist in a TUI form, and the level of keyboard customization for keyboard focused interface is often pretty lackluster in a TUI (terminal text editors famous for their customization can't differentiate between left and right modifiers and it's harder to fix that with an external utility because, guess what, it's not a separate app, so usual app detection fails!)
Keyboard centricity, and the decreased usage latency that follows.
Also terminals vary significantly in input latency (though you might mean something else with "usage" latency), some higher than those of a GUI app https://www.lkhrs.com/blog/2022/07/terminal-latency/