October 12, 2021 by Olivier Goffart and Simon Hausmann
Showing GUIs from Shell Scripts
Ever written a quick (shell) script to automate a small task at some point? Then that script grew over the years and perhaps ended up in the hands of way more users than you originally anticipated? If you were lucky enough to experience this, maybe you wondered: Wouldn't it be nice to have a GUI for that script?
Update: (April 2024) Converted naming from SixtyFPS to Slint and updated to Slint 1.0 syntax.
Now, you probably don't want to rewrite this script in another language to get access to powerful GUI libraries. But you still want to use a proper GUI library. And you also want something that accepts and returns complex, structured data. Finally, this GUI should run everywhere that script runs.
Teaser
If you have rust/cargo installed, copy this code snippet and paste it into your shell on Linux or macOS.
#!/bin/bash
# install slint-viewer (do nothing if it is already installed)
cargo install slint-viewer
output=$(slint-viewer - --save-data - << EOF
import { StandardButton, LineEdit, GridBox } from "std-widgets.slint";
export component _ inherits Dialog {
StandardButton { kind: ok; }
StandardButton { kind: cancel; }
in-out property name <=> name-le.text;
in-out property address <=> address-le.text;
GridBox {
Row {
Text { text: "Enter your name:"; }
name-le := LineEdit { }
}
Row {
Text { text: "Address:"; }
address-le := LineEdit { }
}
}
}
EOF
)
if [ $? -eq 0 ]; then
name=`echo $output | grep -o '"name": *"[^"]*"' | grep -o '"[^"]*"$'`
address=`echo $output | grep -o '"address": *"[^"]*"' | grep -o '"[^"]*"$'`
echo "Your name is $name and you live in $address"
fi
You should see the following dialog. When you click OK, it prints
Your name is "Olivier" and you live in "Berlin"
.
Using Slint from Shell Scripts
Slint is a new GUI framework for desktop and embedded applications.
It is written in Rust but can be used from other programming languages.
The slint-viewer
utility is a tool that we introduced to preview .slint
design markup files.
Since it is written in Rust, you can install it by running cargo install slint-viewer
. Besides the preview functionality, we have added
features that help you show GUIs from shell scripts.
The .slint
design markup language describes your UI in a declarative way
with a familiar syntax. Check out our language
reference for details.
With slint-viewer
, you can either load a .slint file, or pass a "-
" to load from stdin.
The design is then shown on the screen and you can interact with it like a real application.
What's new is that any properties declared at the top-level can be loaded and saved with JSON. The
--save-data -
option causes the the viewer to write the properties as key-value pairs
to stdout when quitting, or you could also write it into a temporary file. The --load-data
option reads a JSON object and populates the key-value pairs to the properties declared at the top-level.
To persist the value of widgets like LineEdit
, declare aliases, similar to the teaser
example: property name <=> name-le.text;
This re-exports the name-le
's text property as
"name".
SysInfo Example
You can find a more advanced example in our Git repository:
This
sysinfo_linux.sh
script collects information about your system, formats it to JSON, feeds it into slint-viewer
and presents a system
information dialog. Next to it is sysinfo_mac.sh
script that does the same for macOS, and they both use the same user interface file
.
On Linux it looks like this:
Conclusion
These examples demonstrate a simple way of separating a dialog user interface from input and output data. There are many ways how this could be extended, for example by feeding dynamically data updates via another file descriptor on the side, or by specifying custom callbacks.
What kind of features would you be interested in using to enhance your shell scripts with a UI? Let us know in the comments.
Slint is a Rust-based toolkit for creating reactive and fluent user interfaces across a range of targets, from embedded devices with limited resources to powerful mobile devices and desktop machines. Supporting Android, Windows, Mac, Linux, and bare-metal systems, Slint features an easy-to-learn domain-specific language (DSL) that compiles into native code, optimizing for the target device's capabilities. It facilitates collaboration between designers and developers on shared projects and supports business logic development in Rust, C++, JavaScript, or Python.