CLI Menu - My Super Power

I started making myself simple CLI menus about a year ago, and now I don’t know how I lived without it. Essentially my menu command takes a list of inputs, and allows you to select one, and return that value. Seems too simple to be useful, right? Let’s see the real world example:

$ ls
Dockerfile Rakefile Gemfile Gemfile.lock
$ echo "You selected: $(ls | menu)"
1) Dockerfile
2) Rakefile
3) Gemfile
4) Gemfile.lock
#? 3
You selected: Gemfile

Ok, but what good is that?! Let’s say you want to edit a specific file but you don’t remember the name:

$ vi $(find ./ | grep -i controller | menu)
1) app/controllers/home_controller.rb
2) app/controllers/awesome_controller.rb
#?

One last modification: If only one item is found, just return it.

$ echo "You selected: $(find ./ | grep -i awesome | menu)"
You selected: app/controllers/awesome_controller.rb

Now, I use two flavors of my menu command. If fzf (Fuzzy Finder) is installed, it uses that, and if not it falls back to bash’s select command. fzf has the advantage of being able to type partial file names, and it allows multi-select which I leave on by default, so I rather recommend giving it a chance, even if it’s not available on every machine.

Here is my menu command at the time of writing:

#!/usr/bin/env bash
if [[ -x "$(which fzf)" ]]; then
  exec fzf -0 -1 -m --bind ctrl-a:select-all
else
  in=$(</dev/stdin)
  if [[ -z "$in" ]]; then
    echo "menu - nothing to display"
    exit 1
  fi
  readarray lines <<< $in
  if [[ "${#lines[@]}" == "1" ]]; then
    echo "${lines[0]}"
  else
    IFS=$'\n'
    select sel in ${lines[@]}; do
      echo "$sel"
      exit
    done < /dev/tty
  fi
fi