I've been workin with ionic the last days and when starting on an machine with multiple network interfaces you get a nice looking selectmenu. Found that far more beatiful than having that via ncurses, etc.

I've thought about this nearliy the whole day. And startet to work on an bash script to get a simple menu working.

After reading some SO questions and manuals I've ended up with this:

#!/bin/bash
# Copyright (C) 2017 Ingo Hollmann - All Rights Reserved
# Permission to copy and modify is granted under the Creative Commons Attribution 4.0 license
# Last revised 2017-09-08

declare -a menu=("Option 1" "Option 2" "Option 3" "Option 4" "Option 5" "Option 6")
cur=0

draw_menu() {
    for i in "${menu[@]}"; do
        if [[ ${menu[$cur]} == $i ]]; then
            tput setaf 2; echo " > $i"; tput sgr0
        else
            echo "   $i";
        fi
    done
}

clear_menu()  {
    for i in "${menu[@]}"; do tput cuu1; done
    tput ed
}

# Draw initial Menu
draw_menu
while read -sN1 key; do # 1 char (not delimiter), silent
    # Check for enter/space
    if [[ "$key" == "" ]]; then break; fi

    # catch multi-char special key sequences
    read -sN1 -t 0.0001 k1; read -sN1 -t 0.0001 k2; read -sN1 -t 0.0001 k3
    key+=${k1}${k2}${k3}

    case "$key" in
        # cursor up, left: previous item
        i|j|$'\e[A'|$'\e0A'|$'\e[D'|$'\e0D') ((cur > 0)) && ((cur--));;
        # cursor down, right: next item
        k|l|$'\e[B'|$'\e0B'|$'\e[C'|$'\e0C') ((cur < ${#menu[@]}-1)) && ((cur++));;
        # home: first item
        $'\e[1~'|$'\e0H'|$'\e[H')  cur=0;;
        # end: last item
        $'\e[4~'|$'\e0F'|$'\e[F') ((cur=${#menu[@]}-1));;
         # q, carriage return: quit
        q|''|$'\e')echo "Aborted." && exit;;
    esac
    # Redraw menu
    clear_menu
    draw_menu
done

echo "Selected item $cur: ${menu[$cur]}";

It looks nice and works as I'd like to have it. Here a little screencast while running:

Found information here:

  • http://linuxcommand.org/lc3_adv_tput.php
  • https://stackoverflow.com/questions/10679188/casing-arrow-keys-in-bash
  • https://unix.stackexchange.com/questions/76566/where-do-i-find-a-list-of-terminal-key-codes-to-remap-shortcuts-in-bash
  • https://stackoverflow.com/questions/8880603/loop-through-an-array-of-strings-in-bash

Previous Post