#!/usr/bin/env sh # This script generates a menu from the given list of items. Choosing an item runs the command for that item. # Usage: # change_my_password="Change my password%passwd" # list_users="List all users%cut -d: -f1 /etc/passwd" # exit="kill -2 $$" # menu "User management options:" "$change_my_password" "$list_users" "$exit" # Use up/down arrow keys to select a menu item, then press Enter. Or cancel with ESC. . colors if [ ${#} -lt 2 ]; then mud-menu exit 0 fi description=$1 shift # Parse args. Each arg is "name%command" items="" commands="" while [ ${#} -gt 0 ]; do IFS='%' read -r item command < and the space between item and command truncated_command=$(echo "${command}" | cut -c -$max_command_length) if [ $i -eq $selected ]; then printf "${CYAN}> %-${max_name_length}s${RESET} ${GREY}%s${RESET}\n" "${item}" "$truncated_command" else printf " %-${max_name_length}s %*s\n" "${item}" "${#truncated_command}" fi i=$((i + 1)) done } # Define the function to handle key presses handle_key() { key=$(await-keypress) case "$key" in up) selected=$((selected - 1)) if [ $selected -lt 0 ]; then selected=$((num_rows - 1)) fi ;; down) selected=$((selected + 1)) if [ $selected -ge $num_rows ]; then selected=0 fi ;; enter) cursor-blink on command="${commands[$selected]}" printf "\n" eval $command exit 0 ;; escape) cursor-blink on echo ESC exit ;; esac } # Catch Ctrl-C and restore the cursor blink, so the user doesn't get stuck with an invisible cursor handle_ctrl_c() { trap 'cursor-blink on; exit' INT } handle_ctrl_c test_menu() { assert_equal "$(./menu "Please choose" "item1 item2 item3" "ls cat command3" -v)" "Please choose\n1) item1\n2) item2\n3) item3\n" "menu -v output differs" assert_equal "$(./menu "Please choose" "item1 item2 item3" "ls cat command3")" "1) item1\n2) item2\n3) item3\n" "menu output differs" } cursor-blink off # Display the menu's description echo $description # Menu loop while true; do display_menu handle_key $key done