We often write quick bash scripts and judging by the comments, half of us use bash or a similar shell to pop out quick, useful scripts, and half of us think that’s an abomination, and you should only use bash for your command line and resort to something more like a traditional language to do anything else. If you’re in the former camp, you’re probably cursing your allegiance when you need to make your bash scripts more interactive.
Gum can help. It’s a utility that can handle your script input and output with a little flair while requiring almost no effort on your part.
The command looks simple, but it has twelve subcommands, each with myriad options. But you can break down the functions into a few simple categories. The input commands let you prompt for a line of input or a bunch of lines of input. You can also create a pick list or a yes/no type of prompt. There’s also a file picker and a filter, sort of like
The output commands let you display markdown, code, and tables. You can make output look nice with borders and colors. There’s a pager for lengthy output and a spinner for showing that something is happening. You can also use template strings with different placeholders.
Perhaps the best way to see the kinds of things that gum can do is to watch the little animated demo from the project page and read the associated source code.
Everything is a subcommand of the main gum executable: choose, confirm, file, filter, format, input, join, pager, spin, style, table, and write. You can guess what most of these do, but a few are less obvious. Running gum by itself will give you a little reminder:
Commands: choose Choose an option from a list of choices confirm Ask a user to confirm an action file Pick a file from a folder filter Filter items from a list format Format a string using a template input Prompt for some input join Join text vertically or horizontally pager Scroll through a file spin Display spinner while running a command style Apply coloring, borders, spacing to text table Render a table of data write Prompt for long-form text
You can get more help by picking a command and adding –help. The join command glues text together with alignment and works even if the text has more than one line. The write command accepts multiline input. One of the examples, for instance, uses it to gather a Git commit message.
If you browse the script, you might note that you can use HTML-style color numbers like:
echo "Do you like $(gum style -- foreground "#04b575" "Bubble Gum?")"
Note that any leading zeros are not optional. As far as I can tell, though, it doesn’t accept named colors, which would be handy. Of course, you could always do something like:
RED="#ff0000" FG=$RED gum style --foreground $FG Alert!
According to the project’s GitHub page, many distributions already know about gum, so you can install it using your normal package manager. I used Neon, so I had to follow the Debian instructions to get it, but that’s not hard to do at all. You can also download prebuilt binaries or packages. The program is written in go, so you can use go to install it, also.
A More Practical Example
One of my favorite ways to exercise a new language is to write a simple program to have the computer guess your number in a high-low game using a binary search algorithm. If the number you pick is between 1 and 1000, the program will guess 500. If you tell the computer that the number is too high, it will guess 250 next time. If 500 was too low, it would guess 750. You get the idea.
Try it out. For a shell script, it is reasonably attractive, and I’m not known for my aesthetic design sensibilities. I’m sure you can do better, but the point is the tools made it relatively painless to create the prompts and the nicely-formatted output. I didn’t even scratch the ability to handle markdown or tables. You will notice, though, that something seems to have broken recently with the syntax coloring of source files.
Walk and Chew Gum
We like how easy gum is to use. We did notice a few oddities. Bold text didn’t work in Konsole, at least not the way ours is set up, since the “intense” foreground color was set to be the same as the normal color. That isn’t really gum’s fault, but it does mean you can’t depend on the user having a configuration that will show all of your pretty layouts.
The format subcommand has a readme file in its subdirectory. (It is the only one, by the way.) In it, you’ll find some tidbits that might help. For example, formatting markdown, code, and emojis are actually done by something called Glamour, so reading its documentation might be helpful. Chroma ultimately handles the source code formatting. In particular, until we read through the Chroma docs, we were unsure how code formatting identified languages or which ones might be supported. Reading about Glamour and Lipgloss will help explain the themes, joining, and colors, too. Doesn’t hurt to read some of the go code, too.
Still, with a light learning curve, you can create or refit scripts to be more user-friendly and appealing quickly, even if they aren’t going to run under a GUI. In the examples directory, you can even see how to embed gum inside things like Python or Ruby.
Sure, there are tools like dialog, and for more advanced scripts, you might need that. But for a quick one-off that just needs a little pizazz, think about gum. If you are going to write serious bash, think about some of the gotchas. You might even consider running through shell check as opposed to spell check.
11 thoughts on “Linux Fu: Gum Up Your Script”
I use linux working solo, but with a team doing the same job.
My principles; do all linux generic, so others can pickup my work & conversely. just do the task, appearance is don’t-care. i never want to be forced to be a sysadmin or support help-desk.
I just want to point out that there is an alternative to gum available: dialog
dialog has been around for ages (the changelog begins 1993) and it is quite stable now, so it is a good choice if you want your script to run on many different distros. There are also bindings for python, perl, ruby etc. available for it.
I don’t use bash for anything more than executing repetitive commands. Like doing an rsync backup of my system. More complicated than that — use a different language to handle process (like Python, Perl, etc.) . So in my mind, GUM isn’t going to be in my tool box. I am a Keep it Simple guy.
Keep it simple but use a second, third, or etcetera, language isn’t keeping it simple; it requires learning a second, third, or etcetera language. Since I’m starting with bash (and my rock-solid AP Pascal from the early 90s), NOT learning another language IS KISS.
It’s not because you can do it, that you must.
To stay simple, use the correct tool for the job.
Wanting to use bash for everything is trusting your golden hammer, and it will eventually yield some awful or over complex scripts.
I don’t even want to know how you would parse a json file in bash.
And I am sure you will tell me “simple, do this, that, and install that tool, and presto, you have a solution that works on my machine!”.
Whereas using the correct tool (ie a scripting language or a programming language) would make the code way clearer and serviceable.
But, hey, whatever floats your goat.
A good tool is better than a dodgy one.
But a dodgy on is better than nothing.
If it’s something that’s a little too long for a one-liner, I’m going to use it more than once, and it doesn’t need any flexibility: bash. Otherwise: perl.
I’m saving my “learning new languages” brain cells for things that will make me money.
I just ask ChatGPT: write a python script that…
Am I the only one who thinks this thing is cool for the sake of being cool? You’d think a website dedicated to that very thing would attract more like-minded readers.
Commenters are not the only readers.
Cool for the sake of being cool, while nifty, don’t pay the bills. And gum isn’t cool for the sake of cool enough to learn just because.
Always nice learning about a tool previously unknown (to me), thanks for the write-up. Gum seems to take the pain out of the most annoying part of writing interactive bash scripts.
A plain “yes/no” prompt was usually the best that I could do. Anything more complicated quickly became cumbersome. Let alone having to edit multiple choice options. Creating boxes around text also was hell; anything more than one line of output text and either your box or the code to generate it become garbled. Not to mention always having to look up the horrible Unicode points for the correct corner or line characters. Only to realise that you need T-segments or crossing lines as well for tables.
And finally, hex color codes instead of excruciating bash coloring codes – that’s a sure win.
I do guess I’ll continue using awk, sed and grep and other more well known tooling. But maybe gums subcommands may prove their advantage in actual use cases.
Little side note: your first example seemed to have an extra space between the `–` and `foreground`, which I only found out after copying it and trying it out (on my outdated termux even, so I guess gum is not that obscure).
Please be kind and respectful to help make the comments section excellent. (Comment Policy)