Scripting with spmenu15 Oct 2023 14:59
Home All

Scripting with spmenu

This wiki article walks you through how to actually write a script using spmenu.

Deciding what to write

Before you write anything, you need to have a concept. For this example, we're going to write a script which lists out all Arch packages you could install and then installs it. You could of course do anything you want, though.

spmenu basics

The core concept of spmenu is to take standard input, list out items separated by a newline character, and output the selected item. For example printf "1\n2\n3\n" | spmenu --lines 30 --prompt 'Select a number' will allow you to choose between 1, 2 and 3. The selected item is then output to standard output (stdout)

Starting off

First, I like to start off my scripts with a main function. I would start like this:

#!/bin/sh
# My super awesome shell script
# Licensed under the GNU General Public License version 3.0
# See LICENSE file for more information.

main() {
    :
}

Now, I know the command to list out all packages in the Arch repositories on your system is pacman -Sl. This is going to list out the repository name followed by a space though, and we don't really need to see that. So what I'm going to do is pacman -Sl | awk '{ print $2 }', which gets the second and final column.

[speedie@arch ~]$ pacman -Sl | awk '{ print $2 }'
acl
amd-ucode
archlinux-keyring
argon2
attr
audit
autoconf
automake
b43-fwctter
base
...

Then what I would do is create another function, and perhaps call it list_packages() or something like that, and then I would replace the placeholder : with assigning a variable.

...

list_packages() {
    pacman -Sl | awk '{ print $2 }'
}

main() {
    sel_item="$(list_packages | spmenu --lines 10 --columns 3 --prompt "Select a package to install:"
}

Checking the output

Alright, now we have the selected item in a variable called sel_item. We can easily print what this variable contains by running something like printf "%s\n" "$sel_item". Now we need to use this variable for something. What I would do next is use something like sudo or doas, and enable root without a password. This could be insecure, so be careful. For this example though, I'm going to assume you're using sudo, and sudo can execute pacman -S without a password.

...

main() {
    sel_item="$(list_packages | spmenu --lines 10 --columns 3 --prompt "Select a package to install:")"
    sudo pacman -S --noconfirm "${sel_item}"
}

Notify

Now what I like to do is add a nice litte notification if the package installed successfully. This is optional but I would do it like this:

...

main() {
    sel_item="$(list_packages | spmenu --lines 10 --columns 3 --prompt "Select a package to install:")"
    sudo pacman -S --noconfirm "${sel_item}" && notify-send "Installed" "Installed '${sel_item}'." || notify-send "Failed" "Installation of package '${sel_item}' failed."
}

Now, finally we need to call the main() function, so simply add main to the bottom of the script.

The script should look something like this:

#!/bin/sh
# My super awesome shell script
# Licensed under the GNU General Public License version 3.0
# See LICENSE file for more information.

list_packages() {
    pacman -Sl | awk '{ print $2 }'
}

main() {
    sel_item="$(list_packages | spmenu --lines 10 --columns 3 --prompt "Select a package to install:")"
    [ -z "${sel_item}" ] && exit # This will exit if we didn't select anything.
    sudo pacman -S --noconfirm "${sel_item}" && notify-send "Installed" "Installed '${sel_item}'." || notify-send "Failed" "Installation of package '${sel_item}' failed."
}

main

Now, you could easily expand this to do removal as well, but I'm not going to cover that.