Simple Prompt Dialog with YAD

Recently I've been playing around with YAD (Yet Another Dialog). Yad is a simple, yet powerful, command-line tool to create graphical dialog windows of various uses from shell scripts. I found yad while I was looking for an alternative for the prompt box in AwesomeWM.

Unfortunately, the documentation on how to use YAD is pretty sparse - at least the official documentation. Luckily I found a site with many examples, enabling me to piece together something that (mostly) suits my needs. I may come back to it later, but for now it does everything I want.

I first set up a zsh script with very simple parameters. For starters I wanted to be able to type a command and have it execute. Here's that script:

#!/bin/zsh

# we want this to evaluate our aliases as well
source ~/.zshrc

$CMD=`yad --entry`

eval ${CMD}

This worked pretty well for what I needed at first, but I soon got lazy and wanted some completion. Poking around the web, I found an example for the --completion flag. Then, I created a history file in my home directory and wrote the following code:

#!/bin/zsh

source ~/.zshrc

yad --completion --entry="" $(cat ~/.exec_history) | while read cmd;
    do
        echo $cmd >> ~/.exec_history
        eval ${cmd}
    done

Awesome. We're getting somewhere. But, there's still a bit more I wanted. I figured if I added commands to a history file then that file would get pretty big if there were duplicates. Also, when yad is already running, do I really want to open another instance? Here's the final update (for now):

#!/bin/zsh

HISTFILE=~/.exec_history
HISTSTR=("${(f)$(cat $HISTFILE)}")

source ~/.zshrc

# run only if yad not already running (-z checks for an empty string)
if [ -z $(pidof yad) ];
then
    yad --no-buttons\
        --fixed\
        --on-top\
        --undecorated\
        --mouse\
        --skip-taskbar\
        --geometry=1x1\
        --timeout=5\
        --completion\
        --entry="" $HISTSTR | while read cmd;
        do
            # add to history file only if not already in there
            grep -qF -- "$cmd" "$HISTFILE" || echo $cmd >> $HISTFILE

            eval ${cmd}
        done
fi

This works really well. It just shows the input box, doesn't allow resizing, and is always on top. Also it has no busy border or title bar, appears where my cursor is, and doesn't show up in the task bar. The geometry ensures that it's the smallest possible size, and the timeout sets it to only persist for 5 seconds.

I have a few other things I'd like to add such as only saving the command if it's valid, possibly looking into tab completion (if that's possible in yad), and maybe using the up and down arrows to cycle through previous commands. For now, though, I think I'm pleased with the results.

I'm sure there are better ways to do this, but this way works for me so I don't see any need to change it. Look out for more similar posts as I'll probably be using more of yad in the future. It's quite the handy tool.

dustin
2019-10-03