You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.3 KiB
98 lines
2.3 KiB
2 years ago
|
#!/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: menu "Please choose" "item1 item2 item3" "ls cat command3"
|
||
|
# Use up/down arrow keys to select a menu item, then press Enter. Or cancel with ESC.
|
||
|
|
||
|
. colors
|
||
|
|
||
|
description=$1
|
||
|
items=($2)
|
||
|
commands=($3)
|
||
|
selected=0
|
||
|
displayed=0
|
||
|
|
||
|
# Calculate the position of the menu
|
||
|
menu_x=$((0))
|
||
|
menu_y=$(fathom-cursor -y)
|
||
|
|
||
|
# Calculate the number of rows that the menu will occupy
|
||
|
num_rows=${#items[@]}
|
||
|
|
||
|
# Calculate the maximum length of the item names
|
||
|
max_name_length=$(max-length "${items[*]}")
|
||
|
max_name_length=$((max_name_length))
|
||
|
|
||
|
# Define the function to display the menu
|
||
|
display_menu() {
|
||
|
# Get the dimensions of the terminal window (again each time in case window is resized)
|
||
|
window_width=$(fathom-terminal -w)
|
||
|
window_height=$(fathom-terminal -h)
|
||
|
|
||
|
# Recalculate the position of the menu
|
||
|
menu_y=$(fathom-cursor -y)
|
||
|
|
||
|
# Move the cursor to the correct position
|
||
|
if [ $displayed -eq 0 ]; then
|
||
|
# Don't move the cursor or clear the screen the first time
|
||
|
displayed=1
|
||
|
else
|
||
|
if [ $((menu_y + num_rows)) -ge $window_height ]; then
|
||
|
menu_y=$((window_height))
|
||
|
fi
|
||
|
move-cursor $menu_x $((menu_y - num_rows))
|
||
|
fi
|
||
|
|
||
|
# Print the items and commands
|
||
|
for i in "${!items[@]}"; do
|
||
|
if [ $i -eq $selected ]; then
|
||
|
printf "${CYAN}> %-${max_name_length}s${RESET} ${GREY}%s${RESET}\n" "${items[$i]}" "${commands[$i]}"
|
||
|
else
|
||
|
# Print the menu item plus extra spaces to cover up its command, since it's not selected
|
||
|
printf " %-${max_name_length}s %*s\n" "${items[$i]}" "${#commands[$i]}"
|
||
|
fi
|
||
|
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
|
||
|
}
|
||
|
|
||
|
cursor-blink off
|
||
|
|
||
|
# Display the menu's description
|
||
|
echo $description
|
||
|
|
||
|
# Menu loop
|
||
|
while true; do
|
||
|
display_menu
|
||
|
handle_key $key
|
||
|
done
|