Go back to the Programming Article Index.
I'm one of those individuals who like to customize Linux desktops. One mainstay of these types of setups is a good program launcher. dmenu and rofi are favorites among most individuals. However, what's annoying to me is that these two programs are essentially just fzy but for Xorg instead of the tty. Surely we could just Unix Philosophy™ our way out of this one?
Yes we can.
Okay, so we have a terminal emulator and a terminal
dmenu
clone as our building blocks. I'm using
st
and fzy
, respectively.
Surely this would work?
$ st -e fzy
Oh right, fzy
accepts input on standard in, so that
won't work. We need some way to smuggle that standard in into
fzy
.
We could try writing the input to fzy
into a file, then
passing it in:
$ temp=$(mktemp)
$ echo $temp
/run/user/1000/tmp.funnytext
$ cat <<EOF > temp
some
choices
EOF
$ st -e sh -c "fzy < $temp"
Now, we get a terminal that pops up with various choices, and we can
use the trditional fzy
controls to handle it. But we still
need fzy
's output back -- it's going to standard out which
is then immediately closed (because sh
, the process in
st
, terminates as soon as it finishes running commands in
-c
).
Let's try writing to another file.
$ st -e sh -c "fzy < $temp > /tmp/really_special_output_file"
$ cat /tmp/really_special_output_file
my choice
Nice; we now have a somewhat working dmenu replacement with just a terminal emulator and fzy.
You can polish this up and make it into a series of shell scripts.
I've already done that here,
in tmenu
, tmenu-backend
, and
tmenu_run
.
If you're running bspwm
, you can add a rule like so:
bspc rule -a tmenu-prompt border=on sticky=on state=floating
This makes the window float. Now, you just call st
like
so:
st -c tmenu-prompt -e <...>
And we get a centered result:
From the lemonbar
Arch Wiki
page:
lemonbar prints no information on its own. To get any text into lemonbar you need to pipe text into it.
Sounds an awful lot like a terminal, right?
This one's easier though -- we just have a specially arranged terminal at the top of the desktop running our program. But how do we put it up there?
Define a bspwm
rule:
bspc rule -a statusbar border=off sticky=on state=floating manage=off
(That manage=off
part makes bspwm
not
resize the window at all.)
Now, you need to figure out where the statusbar goes, and then start
the statusbars where they need to go. Here's some Python to do that:
(statusbar
is the statusbar program executed in
st
)
= subprocess.Popen(['xrandr'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
xrandr = list(xrandr.stdout)
output = [i.decode("utf-8") for i in output if " connected" in i.decode("utf-8")]
output = []
serialized for i in output:
= i.split(' ')
splitted print(splitted)
= splitted[0]
displayname = splitted[2]
geometry if geometry == "primary":
= splitted[3]
geometry
try:
= [int(i) for i in geometry.replace('x', '+').split('+')]
geometry_splitted except ValueError:
continue
1] = 20
geometry_splitted[print(displayname, geometry_splitted)
"st -c statusbar -p -g {}x{}+{}+{} -e statusbar {} & disown".format(
os.system(*map(str, geometry_splitted),
displayname ))
The above does depend on you having a 'pixel-perfect' st patch such
as anysize. I
wrote my own, and it's enabled by using -p
.