mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 17:59:44 +00:00
150 lines
4.1 KiB
Bash
150 lines
4.1 KiB
Bash
#!/bin/bash
|
|
|
|
# Simple, clean menu implementation that properly separates output
|
|
|
|
# Simple single-select menu - returns selected index
|
|
simple_select() {
|
|
local title="$1"
|
|
shift
|
|
local -a options=("$@")
|
|
local selected=0
|
|
local key
|
|
|
|
# Clear screen and show header
|
|
clear >&2
|
|
echo "=== $title ===" >&2
|
|
echo "" >&2
|
|
|
|
while true; do
|
|
# Show options
|
|
for ((i = 0; i < ${#options[@]}; i++)); do
|
|
if [[ $i -eq $selected ]]; then
|
|
echo "▶ ${options[i]}" >&2
|
|
else
|
|
echo " ${options[i]}" >&2
|
|
fi
|
|
done
|
|
echo "" >&2
|
|
echo "Use ↑/↓ to navigate, ENTER to select, Q to quit" >&2
|
|
|
|
# Read key
|
|
read -rsn1 key
|
|
case "$key" in
|
|
$'\x1b')
|
|
# Arrow key sequence
|
|
read -rsn2 key
|
|
case "$key" in
|
|
'[A') # Up
|
|
((selected--))
|
|
if [[ $selected -lt 0 ]]; then
|
|
selected=$((${#options[@]} - 1))
|
|
fi
|
|
;;
|
|
'[B') # Down
|
|
((selected++))
|
|
if [[ $selected -ge ${#options[@]} ]]; then
|
|
selected=0
|
|
fi
|
|
;;
|
|
esac
|
|
;;
|
|
'') # Enter
|
|
echo "$selected"
|
|
return 0
|
|
;;
|
|
'q'|'Q')
|
|
return 1
|
|
;;
|
|
esac
|
|
|
|
# Clear screen for next iteration
|
|
clear >&2
|
|
echo "=== $title ===" >&2
|
|
echo "" >&2
|
|
done
|
|
}
|
|
|
|
# Multi-select menu - returns space-separated indices
|
|
simple_multi_select() {
|
|
local title="$1"
|
|
shift
|
|
local -a options=("$@")
|
|
local selected=0
|
|
local -a selected_items=()
|
|
local key
|
|
|
|
# Initialize selected items array
|
|
for ((i = 0; i < ${#options[@]}; i++)); do
|
|
selected_items[i]=false
|
|
done
|
|
|
|
clear >&2
|
|
echo "=== $title ===" >&2
|
|
echo "" >&2
|
|
|
|
while true; do
|
|
# Show options
|
|
for ((i = 0; i < ${#options[@]}; i++)); do
|
|
local checkbox="☐"
|
|
if [[ ${selected_items[i]} == "true" ]]; then
|
|
checkbox="☑"
|
|
fi
|
|
|
|
if [[ $i -eq $selected ]]; then
|
|
echo "▶ $checkbox ${options[i]}" >&2
|
|
else
|
|
echo " $checkbox ${options[i]}" >&2
|
|
fi
|
|
done
|
|
echo "" >&2
|
|
echo "Use ↑/↓ to navigate, SPACE to select/deselect, ENTER to confirm, Q to quit" >&2
|
|
|
|
# Read key
|
|
read -rsn1 key
|
|
case "$key" in
|
|
$'\x1b')
|
|
# Arrow key sequence
|
|
read -rsn2 key
|
|
case "$key" in
|
|
'[A') # Up
|
|
((selected--))
|
|
if [[ $selected -lt 0 ]]; then
|
|
selected=$((${#options[@]} - 1))
|
|
fi
|
|
;;
|
|
'[B') # Down
|
|
((selected++))
|
|
if [[ $selected -ge ${#options[@]} ]]; then
|
|
selected=0
|
|
fi
|
|
;;
|
|
esac
|
|
;;
|
|
' ') # Space - toggle selection
|
|
if [[ ${selected_items[selected]} == "true" ]]; then
|
|
selected_items[selected]=false
|
|
else
|
|
selected_items[selected]=true
|
|
fi
|
|
;;
|
|
'') # Enter - confirm
|
|
local result=""
|
|
for ((i = 0; i < ${#options[@]}; i++)); do
|
|
if [[ ${selected_items[i]} == "true" ]]; then
|
|
result="$result $i"
|
|
fi
|
|
done
|
|
echo "${result# }" # Remove leading space
|
|
return 0
|
|
;;
|
|
'q'|'Q')
|
|
return 1
|
|
;;
|
|
esac
|
|
|
|
# Clear screen for next iteration
|
|
clear >&2
|
|
echo "=== $title ===" >&2
|
|
echo "" >&2
|
|
done
|
|
} |