The last thing I want in my shell script is to have it depend on a brand-new utility, which is part of the Rust ecosystem that is itself still new and evolving. Shell scripts need to be super stable and portable.
Edit: If I need GUI in my scripts, I'd probablyjust use dialog and other curses stuff.
Imtui is not the same things as it is a C++ library, so you don't write shell code anymore, you write C++
dialog is an option but is quite limited in what you can do.
There are many alternatives, and this is just another one to choose from.
Depending on where your script is required to run, a Rust tool might not be a problem. Not all shell scripts need to be super portable.
Yes, you're right about ImTui, removed that line. Disagree about portability. I mean, yes, you could write a shell script targeting even a single specific machine, but generally you want to assume as little as possible beyond a GNU operating system and its common utilities.
While it is true that some shell scripts need to be portable, many don't.
Many shell scripts are written just to run in one single machine. Or they run in a controlled environment. Maybe even a docker container that provide anyway a set of tools and dependencies.
It's a native program; it's not going to morph out from under you. The Rust build system swears by semver compatibility, and crates.io is a permanent repository; it's not going to stop building. So what critique are you actually making, that {random C++ project} survives?
I still prefer the plain question and answer approach.
The OpenBSD installer follows it, for example, and makes for a very simple interaction. When SSHing to a remote host, it's quite snappy , and has no drawing overhead.
I've used wish (https://linux.die.net/man/1/wish) for this in the past and it works pretty well. It used to come installed on many Linux distros but probably does not anymore.
And tksh (shell with tk builtins), which made (makes, if you take the trouble to install it now) it trivial to add a simple GUI to an existing shell script.
Do you happen to know where there's a copy of the source? The stuff on the tcl wiki all seems to be dead and that sounds fascinating to take apart to learn how it works.
There's not really much to it; it's just an example of extending ksh with more builtins, which is simple by design. (I really miss what this did for Sun's dbx debugger — instead of being inside some tool with yet another idiosyncratic command language, your shell just grew commands for interacting with the process being debugged.)
I usually add bottle.py[0] in my project (it's single file!) and add a simple HTML form with a submit button. When I need to show a UI, I start a server, open up the URL and when the form is submitted, I shutdown the server and continue executing the script.
Using HTML means I can start off with plain HTML and no style (except user-agent) and keep building on it (change font, center it in the page, etc.). I can keep HTML, JS, CSS on the same page, add AlpineJS[1] if I need a reactive UI and so on.
The only thing missing is that I can't close the tab using JavaScript when it's finished, so the user (usually me) has to close it himself.
Why's that?
The logic might be easy to do in shell. And if there is an easy way to give a good presentation from your shell script, then let's just use that.
The big advantage of Zenity is that is it installed by default. A lot of other systems have fantastic usability and better options, but they aren't installed on the machine so it's moot.
I like yad[0] for this. For example, I use it to present a GUI color picker to change/insert colors in Vim (via a plugin called vCoolor[1]). I also use it in some i3/sway scripts that need user input or to show a progress bar.
YAD is, in fact, the source of inspiration for this blog post.
I seen YAD mentioning and that you can do pretty advanced stuff with it. Since we're developing a GUI framework I thought we could do the same with our viewer utility, and be even more flexible.
One of the lesson that I believe is being learned is that general purpose programming languages for UIs make it difficult to do tooling, especially with dynamic typing.
This particular approach (.60) is not a general purpose programming language and it's strongly typed.
It's designed for the user interface, not for writing the rest of the program in it.
I feel this is rather different from the tcl/tk applications we used to see?
Very cool project! It's exciting to see two reputable Qt & KDE devs doing fresh stuff.
(as a long-time linux user and Qt and KDE hobbyist I recognize their names like a sports fan recognizes their favorite players' names)
I don't believe Cargo install is meant to be used as a general purpose distribution tool; though I know it's tempting to bypass the package manager especially when it's so easy.
From what I understand cargo install is supposed to help around rust ecosystem tooling such as installing clippy, xargo and rls, where cargo has much more context than the package manager.
From the RFC the motivations for `cargo install` existing:
> Simple tasks like installing a new cargo subcommand, installing an editor plugin, etc,
If you're adding IPC mechanisms to a shell script, seriously consider if you should be writing it in a lower level language, like python or go or rust...
You can use it from whatever you want; it's not just for shell scripts.
Although why you'd go for a lower level language if you don't have to for some specific reason is beyond me. GUIs specifically have been historically very friendly towards very high level languages - see Tcl/Tk.
Also, by your logic, shell scripts should never use pipes; you should always use pipes from Python or Go or Rust. But I suspect that's not how other people usually think.
My experience with anything involving tcl/tk has always been suboptimal.
Also, we're specifically talking about shell scripts.
I'd argue that if you're implementing an entire protocol into a shell script, yes, you should consider more efficient languages. If you're just dumping data into a pipe like you would to std out, sure that's fine.
The key here, at least for me, is complexity. Are you bludgeoning shell scripts into something it wasn't meant for? Is there a better alternative meant to do the thing you're doing?
The original graphical shell was written by J. Stephen Pendergrast and documented in the book "Desktop KornShell Graphical Programming," ISBN 0-201-63375-2. This book is hard to find.
Pendergrast's shell was included in the CDE standard, directly accesses Motif and X11 primitives, and builds on modern systems.
On Windows, I use the built-in Microsoft HTML Applications (HTAs) to build single-file, double-clickable GUIs in JS. Using ActiveXObject from within your HTA, you can write scripts for pretty much anything on your PC. (So this isn't showing a GUI from a script, but scripting from within a GUI application).
I've started writing a guide about it: https://marksweb.site/hta/ It's still very much work in progress, but maybe it helps if you wanna try developing HTAs.
56 comments
[ 6.2 ms ] story [ 142 ms ] threadEdit: If I need GUI in my scripts, I'd probablyjust use dialog and other curses stuff.
dialog is an option but is quite limited in what you can do. There are many alternatives, and this is just another one to choose from. Depending on where your script is required to run, a Rust tool might not be a problem. Not all shell scripts need to be super portable.
The OpenBSD installer follows it, for example, and makes for a very simple interaction. When SSHing to a remote host, it's quite snappy , and has no drawing overhead.
Zenity is also an option.
But the system UI that is also linked in there is something that goes beyond what you can do with e.g. zenity.
This kind of puts (almost) all the power of a modern UI description language in reach of shell scripts.
There's not really much to it; it's just an example of extending ksh with more builtins, which is simple by design. (I really miss what this did for Sun's dbx debugger — instead of being inside some tool with yet another idiosyncratic command language, your shell just grew commands for interacting with the process being debugged.)
Thank you kindly.
[1] https://github.com/chriskiehl/Gooey
Using HTML means I can start off with plain HTML and no style (except user-agent) and keep building on it (change font, center it in the page, etc.). I can keep HTML, JS, CSS on the same page, add AlpineJS[1] if I need a reactive UI and so on.
The only thing missing is that I can't close the tab using JavaScript when it's finished, so the user (usually me) has to close it himself.
[0]: https://bottlepy.org/docs/dev/
[1]: https://alpinejs.dev
how come? doesn't window.close() work for you?
From MDN:
> This method can only be called on windows that were opened by a script using the Window.open() method.
I was unable to get `window.close()` to work on root windows, but your comment prompted me research it again. This seems to work:
[0]: https://developer.mozilla.org/en-US/docs/Web/API/Window/clos...https://help.gnome.org/users/zenity/stable/
[0]: https://github.com/v1cont/yad
[1]: https://github.com/KabbAmine/vCoolor.vim
This particular approach (.60) is not a general purpose programming language and it's strongly typed.
It's designed for the user interface, not for writing the rest of the program in it.
I feel this is rather different from the tcl/tk applications we used to see?
The problem is that current generations cannot see beyond their vi/emacs CLI setups and are too invested into HTML/CS/JS stacks to see otherwise.
Some quickly picked examples,
https://en.wikipedia.org/wiki/NeWS
"Smalltalk usage for UI prototyping in Thales industrial context"
https://youtu.be/Oq1RSDn2P5Y?t=1030
"Interface Builder's Alternative Lisp Timeline"
https://news.ycombinator.com/item?id=21828622
Which by the way, makes the binding Objective-C / Smalltalk /Lisp in UI design.
https://hal.inria.fr/hal-02966704/document
Not sure users who prefer a GUI over the command line, would be too happy about having to fix compile errors prior to running the program?
Right now there is not, but work is being done to cover the common platforms.
I don't believe Cargo install is meant to be used as a general purpose distribution tool; though I know it's tempting to bypass the package manager especially when it's so easy.
From what I understand cargo install is supposed to help around rust ecosystem tooling such as installing clippy, xargo and rls, where cargo has much more context than the package manager.
From the RFC the motivations for `cargo install` existing:
> Simple tasks like installing a new cargo subcommand, installing an editor plugin, etc,
https://rust-lang.github.io/rfcs/1200-cargo-install.html
It's not perfect though, and I think we're going to try to create binaries for download alternatively.
Can communicate using nine IPC mechanisms AND as a loadable library with a small C API.
Also, if you're running a Gtk desktop, it obviously obeys your Gtk theme.
Although why you'd go for a lower level language if you don't have to for some specific reason is beyond me. GUIs specifically have been historically very friendly towards very high level languages - see Tcl/Tk.
Also, by your logic, shell scripts should never use pipes; you should always use pipes from Python or Go or Rust. But I suspect that's not how other people usually think.
Also, we're specifically talking about shell scripts.
I'd argue that if you're implementing an entire protocol into a shell script, yes, you should consider more efficient languages. If you're just dumping data into a pipe like you would to std out, sure that's fine.
The key here, at least for me, is complexity. Are you bludgeoning shell scripts into something it wasn't meant for? Is there a better alternative meant to do the thing you're doing?
Pendergrast's shell was included in the CDE standard, directly accesses Motif and X11 primitives, and builds on modern systems.
The source code is in this collection:
https://sourceforge.net/projects/cdesktopenv/