1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-07 14:29:17 +00:00

🔥 remove useless files

This commit is contained in:
Tw93
2025-09-28 00:15:04 +08:00
parent 00103ae75b
commit 5e784e98d7
6 changed files with 0 additions and 1123 deletions

View File

@@ -1,248 +0,0 @@
#!/bin/bash
# Better menu system with proper terminal handling
# Uses tried-and-true approach for better compatibility
# Terminal state management
save_terminal() {
stty -g 2>/dev/null || true
}
restore_terminal() {
stty "$(save_terminal)" 2>/dev/null || true
printf '\033[?25h' >&2 # Show cursor
printf '\033[0m' >&2 # Reset colors
}
# Read a single key (handles arrow keys properly)
read_key() {
local key
read -rsn1 key
case "$key" in
$'\033') # ESC sequence
read -rsn2 key 2>/dev/null || key=""
case "$key" in
'[A') echo "UP" ;;
'[B') echo "DOWN" ;;
*) echo "ESC" ;;
esac
;;
' ') echo "SPACE" ;;
'') echo "ENTER" ;;
'q'|'Q') echo "QUIT" ;;
*) echo "OTHER" ;;
esac
}
# Multi-select menu with proper pagination
multi_select_menu() {
local title="$1"
shift
local -a items=("$@")
if [[ ${#items[@]} -eq 0 ]]; then
echo "Error: No items provided" >&2
return 1
fi
local -a selected=()
local current=0
local page_size=10
local total=${#items[@]}
# Initialize selection array
for ((i = 0; i < total; i++)); do
selected[i]=false
done
# Save terminal state
local saved_state=""
saved_state=$(save_terminal)
trap 'test -n "$saved_state" && stty "$saved_state" 2>/dev/null; restore_terminal' EXIT INT TERM
while true; do
# Calculate pagination
local start_page=$((current / page_size))
local start_idx=$((start_page * page_size))
local end_idx=$((start_idx + page_size - 1))
if [[ $end_idx -ge $total ]]; then
end_idx=$((total - 1))
fi
# Clear screen and show header
printf '\033[2J\033[H' >&2
echo "┌─── $title ───┐" >&2
echo "│ Found $total items (Page $((start_page + 1)) of $(((total + page_size - 1) / page_size))) │" >&2
echo "└─────────────────────────────────────────────┘" >&2
echo "" >&2
# Show items for current page
for ((i = start_idx; i <= end_idx; i++)); do
local marker=" "
local checkbox="☐"
if [[ $i -eq $current ]]; then
marker="▶ "
fi
if [[ ${selected[i]} == "true" ]]; then
checkbox="☑"
fi
printf "%s%s %s\n" "$marker" "$checkbox" "${items[i]}" >&2
done
echo "" >&2
echo "Controls: ↑/↓=Navigate Space=Select/Deselect Enter=Confirm Q=Quit" >&2
# Show selection summary
local count=0
for ((i = 0; i < total; i++)); do
if [[ ${selected[i]} == "true" ]]; then
((count++))
fi
done
echo "Selected: $count items" >&2
echo "" >&2
# Read key
local key
key=$(read_key)
case "$key" in
"UP")
((current--))
if [[ $current -lt 0 ]]; then
current=$((total - 1))
fi
;;
"DOWN")
((current++))
if [[ $current -ge $total ]]; then
current=0
fi
;;
"SPACE")
if [[ ${selected[current]} == "true" ]]; then
selected[current]=false
else
selected[current]=true
fi
;;
"ENTER")
# Build result string
local result=""
for ((i = 0; i < total; i++)); do
if [[ ${selected[i]} == "true" ]]; then
result="$result $i"
fi
done
# Clean up and return
restore_terminal
echo "${result# }" # Remove leading space
return 0
;;
"QUIT"|"ESC")
restore_terminal
return 1
;;
esac
done
}
# Simple single-select menu
single_select_menu() {
local title="$1"
shift
local -a items=("$@")
if [[ ${#items[@]} -eq 0 ]]; then
echo "Error: No items provided" >&2
return 1
fi
local current=0
local total=${#items[@]}
# Save terminal state
local saved_state=""
saved_state=$(save_terminal)
trap 'test -n "$saved_state" && stty "$saved_state" 2>/dev/null; restore_terminal' EXIT INT TERM
while true; do
# Clear screen and show header
printf '\033[2J\033[H' >&2
echo "┌─── $title ───┐" >&2
echo "│ Choose one of $total items │" >&2
echo "└────────────────────────────┘" >&2
echo "" >&2
# Show all items
for ((i = 0; i < total; i++)); do
local marker=" "
if [[ $i -eq $current ]]; then
marker="▶ "
fi
printf "%s%s\n" "$marker" "${items[i]}" >&2
done
echo "" >&2
echo "Controls: ↑/↓=Navigate Enter=Select Q=Quit" >&2
echo "" >&2
# Read key
local key
key=$(read_key)
case "$key" in
"UP")
((current--))
if [[ $current -lt 0 ]]; then
current=$((total - 1))
fi
;;
"DOWN")
((current++))
if [[ $current -ge $total ]]; then
current=0
fi
;;
"ENTER")
restore_terminal
echo "$current"
return 0
;;
"QUIT"|"ESC")
restore_terminal
return 1
;;
esac
done
}
# Demo function for testing
demo() {
echo "=== Multi-select Demo ===" >&2
local result
result=$(multi_select_menu "Test Multi-Select" "Option 1" "Option 2" "Option 3" "Option 4" "Option 5")
if [[ $? -eq 0 ]]; then
echo "You selected indices: $result" >&2
else
echo "Selection cancelled" >&2
fi
echo "" >&2
echo "=== Single-select Demo ===" >&2
result=$(single_select_menu "Test Single-Select" "Choice A" "Choice B" "Choice C")
if [[ $? -eq 0 ]]; then
echo "You selected index: $result" >&2
else
echo "Selection cancelled" >&2
fi
}
# Run demo if script is executed directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
demo
fi

View File

@@ -1,300 +0,0 @@
#!/bin/bash
# Simple interactive menu selector with arrow key support
# No external dependencies, compatible with most bash versions
declare -a menu_options=()
declare -i selected=0
declare -i menu_size=0
# ANSI escape sequences
readonly ESC=$'\033'
readonly UP="${ESC}[A"
readonly DOWN="${ESC}[B"
readonly ENTER=$'\n'
readonly CLEAR_LINE="${ESC}[2K"
readonly HIDE_CURSOR="${ESC}[?25l"
readonly SHOW_CURSOR="${ESC}[?25h"
# Set terminal to raw mode for reading single characters
setup_terminal() {
stty -echo -icanon time 0 min 0
}
# Restore terminal to normal mode
restore_terminal() {
stty echo icanon
printf "%s" "$SHOW_CURSOR"
}
# Draw the menu
draw_menu() {
printf "%s" "$HIDE_CURSOR"
for ((i = 0; i < menu_size; i++)); do
printf "\r%s" "$CLEAR_LINE"
if [[ $i -eq $selected ]]; then
printf "▶ \033[1;32m%s\033[0m\n" "${menu_options[i]}"
else
printf " %s\n" "${menu_options[i]}"
fi
done
# Move cursor back to the beginning
printf "${ESC}[%dA" $menu_size
}
# Read a single key
read_key() {
local key
IFS= read -r -n1 key 2>/dev/null
if [[ $key == $ESC ]]; then
# Handle escape sequences
IFS= read -r -n2 key 2>/dev/null
case "$key" in
'[A') echo "UP" ;;
'[B') echo "DOWN" ;;
*) echo "ESC" ;;
esac
elif [[ $key == "" ]]; then
echo "ENTER"
else
echo "$key"
fi
}
# Main menu function
# Usage: show_menu "Title" "option1" "option2" "option3" ...
show_menu() {
local title="$1"
shift
# Initialize menu options
menu_options=("$@")
menu_size=${#menu_options[@]}
selected=0
# Check if we have options
if [[ $menu_size -eq 0 ]]; then
echo "Error: No menu options provided" >&2
return 1
fi
# Setup terminal
setup_terminal
trap restore_terminal EXIT INT TERM
# Display title
if [[ -n "$title" ]]; then
printf "\n\033[1;34m%s\033[0m\n\n" "$title"
fi
# Initial draw
draw_menu
# Main loop
while true; do
local key=$(read_key)
case "$key" in
"UP")
((selected--))
if [[ $selected -lt 0 ]]; then
selected=$((menu_size - 1))
fi
draw_menu
;;
"DOWN")
((selected++))
if [[ $selected -ge $menu_size ]]; then
selected=0
fi
draw_menu
;;
"ENTER")
# Clear the menu
for ((i = 0; i < menu_size; i++)); do
printf "\r%s\n" "$CLEAR_LINE" >&2
done
printf "${ESC}[%dA" $menu_size >&2
# Show selection
printf "Selected: \033[1;32m%s\033[0m\n\n" "${menu_options[selected]}"
restore_terminal
return $selected
;;
"q"|"Q")
restore_terminal
echo "Cancelled." >&2
return 255
;;
[0-9])
# Jump to numbered option
local num=$((key - 1))
if [[ $num -ge 0 && $num -lt $menu_size ]]; then
selected=$num
draw_menu
fi
;;
esac
done
}
# Multi-select menu function
# Usage: show_multi_menu "Title" "option1" "option2" "option3" ...
show_multi_menu() {
local title="$1"
shift
# Initialize menu options
menu_options=("$@")
menu_size=${#menu_options[@]}
selected=0
# Array to track selected items
declare -a selected_items=()
for ((i = 0; i < menu_size; i++)); do
selected_items[i]=false
done
# Check if we have options
if [[ $menu_size -eq 0 ]]; then
echo "Error: No menu options provided" >&2
return 1
fi
# Setup terminal
setup_terminal
trap restore_terminal EXIT INT TERM
# Display title
if [[ -n "$title" ]]; then
printf "\n\033[1;34m%s\033[0m\n" "$title" >&2
printf "\033[0;36mUse SPACE to select/deselect, ENTER to confirm, Q to quit\033[0m\n\n" >&2
fi
# Draw multi-select menu
draw_multi_menu() {
printf "%s" "$HIDE_CURSOR" >&2
for ((i = 0; i < menu_size; i++)); do
printf "\r%s" "$CLEAR_LINE" >&2
local checkbox="☐"
if [[ ${selected_items[i]} == "true" ]]; then
checkbox="\033[1;32m☑\033[0m"
fi
if [[ $i -eq $selected ]]; then
printf "▶ %s \033[1;32m%s\033[0m\n" "$checkbox" "${menu_options[i]}" >&2
else
printf " %s %s\n" "$checkbox" "${menu_options[i]}" >&2
fi
done
# Move cursor back to the beginning
printf "${ESC}[%dA" $menu_size >&2
}
# Initial draw
draw_multi_menu
# Main loop
while true; do
local key=$(read_key)
case "$key" in
"UP")
((selected--))
if [[ $selected -lt 0 ]]; then
selected=$((menu_size - 1))
fi
draw_multi_menu
;;
"DOWN")
((selected++))
if [[ $selected -ge $menu_size ]]; then
selected=0
fi
draw_multi_menu
;;
" ")
# Toggle selection
if [[ ${selected_items[selected]} == "true" ]]; then
selected_items[selected]="false"
else
selected_items[selected]="true"
fi
draw_multi_menu
;;
"ENTER")
# Clear the menu
for ((i = 0; i < menu_size; i++)); do
printf "\r%s\n" "$CLEAR_LINE" >&2
done
printf "${ESC}[%dA" $menu_size >&2
# Show selections to stderr so it doesn't interfere with return value
local has_selection=false
printf "Selected items:\n" >&2
for ((i = 0; i < menu_size; i++)); do
if [[ ${selected_items[i]} == "true" ]]; then
printf " \033[1;32m%s\033[0m\n" "${menu_options[i]}" >&2
has_selection=true
fi
done
if [[ $has_selection == "false" ]]; then
printf " None\n" >&2
fi
printf "\n" >&2
restore_terminal
# Return selected indices as space-separated string
local result=""
for ((i = 0; i < menu_size; i++)); do
if [[ ${selected_items[i]} == "true" ]]; then
result="$result $i"
fi
done
echo "${result# }" # Remove leading space
return 0
;;
"q"|"Q")
restore_terminal
echo "Cancelled." >&2
return 255
;;
esac
done
}
# Example usage function
demo_menu() {
echo "=== Single Select Demo ==="
if show_menu "Choose an action:" "Install package" "Update system" "Clean cache" "Exit"; then
local choice=$?
echo "You selected option $choice"
fi
echo -e "\n=== Multi Select Demo ==="
local selections=$(show_multi_menu "Choose packages to install:" "git" "vim" "curl" "htop" "tree")
if [[ $? -eq 0 && -n "$selections" ]]; then
echo "Selected indices: $selections"
# Convert indices to actual values
local options=("git" "vim" "curl" "htop" "tree")
echo "Selected packages:"
for idx in $selections; do
echo " - ${options[idx]}"
done
fi
}
# If script is run directly, show demo
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
demo_menu
fi

View File

@@ -1,157 +0,0 @@
#!/bin/bash
# Simple native bash menu using the built-in select command
# This is the most reliable approach with zero dependencies
# Multi-select using native bash select with checkboxes simulation
multi_select_native() {
local title="$1"
shift
local -a items=("$@")
if [[ ${#items[@]} -eq 0 ]]; then
echo "Error: No items provided" >&2
return 1
fi
echo "=== $title ===" >&2
echo "Select multiple items (enter numbers separated by spaces, or 'done' when finished):" >&2
echo "" >&2
# Display items with numbers
for ((i = 0; i < ${#items[@]}; i++)); do
printf "%2d) %s\n" $((i + 1)) "${items[i]}" >&2
done
echo "" >&2
local -a selected_indices=()
while true; do
echo "Currently selected: ${#selected_indices[@]} items" >&2
if [[ ${#selected_indices[@]} -gt 0 ]]; then
echo "Selected indices: ${selected_indices[*]}" >&2
fi
echo "" >&2
read -p "Enter selection (numbers, 'all', 'none', or 'done'): " -r input >&2
case "$input" in
"done"|"")
break
;;
"all")
selected_indices=()
for ((i = 0; i < ${#items[@]}; i++)); do
selected_indices+=($i)
done
echo "Selected all ${#items[@]} items" >&2
;;
"none")
selected_indices=()
echo "Cleared all selections" >&2
;;
*)
# Parse space-separated numbers
read -ra nums <<< "$input"
for num in "${nums[@]}"; do
if [[ "$num" =~ ^[0-9]+$ ]] && [[ $num -ge 1 ]] && [[ $num -le ${#items[@]} ]]; then
local idx=$((num - 1))
# Check if already selected
local already_selected=false
if [[ ${#selected_indices[@]} -gt 0 ]]; then
for selected in "${selected_indices[@]}"; do
if [[ $selected -eq $idx ]]; then
already_selected=true
break
fi
done
fi
if [[ $already_selected == false ]]; then
selected_indices+=($idx)
echo "Added: ${items[idx]}" >&2
else
echo "Already selected: ${items[idx]}" >&2
fi
else
echo "Invalid selection: $num (must be 1-${#items[@]})" >&2
fi
done
;;
esac
echo "" >&2
done
# Convert to space-separated string and return
local result=""
if [[ ${#selected_indices[@]} -gt 0 ]]; then
for idx in "${selected_indices[@]}"; do
result="$result $idx"
done
echo "${result# }" # Remove leading space
else
echo "" # Return empty string for no selections
fi
return 0
}
# Simple single-select using native bash select
single_select_native() {
local title="$1"
shift
local -a items=("$@")
if [[ ${#items[@]} -eq 0 ]]; then
echo "Error: No items provided" >&2
return 1
fi
echo "=== $title ===" >&2
# Use PS3 to customize the select prompt
local PS3="Please select an option (1-${#items[@]}): "
select item in "${items[@]}" "Cancel"; do
if [[ -n "$item" ]]; then
if [[ "$item" == "Cancel" ]]; then
return 1
else
# Find the index of selected item
for ((i = 0; i < ${#items[@]}; i++)); do
if [[ "${items[i]}" == "$item" ]]; then
echo "$i"
return 0
fi
done
fi
else
echo "Invalid selection. Please try again." >&2
fi
done 2>&2 # Redirect select dialog to stderr
}
# Demo function
demo_native() {
echo "=== Multi-select Demo ===" >&2
local result
result=$(multi_select_native "Choose Applications" "App 1" "App 2" "App 3" "App 4" "App 5")
if [[ $? -eq 0 ]]; then
echo "You selected indices: '$result'" >&2
else
echo "Selection cancelled" >&2
fi
echo "" >&2
echo "=== Single-select Demo ===" >&2
result=$(single_select_native "Choose One App" "Option A" "Option B" "Option C")
if [[ $? -eq 0 ]]; then
echo "You selected index: $result" >&2
else
echo "Selection cancelled" >&2
fi
}
# Run demo if script is executed directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
demo_native
fi

View File

@@ -1,150 +0,0 @@
#!/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
}

View File

@@ -1,268 +0,0 @@
#!/bin/bash
# Smart menu with pagination and search for large lists
# Much better UX for handling many items
# Smart multi-select with search and pagination
smart_multi_select() {
local title="$1"
shift
local -a all_items=("$@")
if [[ ${#all_items[@]} -eq 0 ]]; then
echo "Error: No items provided" >&2
return 1
fi
local -a selected_indices=()
local -a filtered_items=()
local -a filtered_indices=()
local search_term=""
local page_size=15
local current_page=0
# Function to filter items based on search
filter_items() {
filtered_items=()
filtered_indices=()
if [[ -z "$search_term" ]]; then
# No search, show all items
filtered_items=("${all_items[@]}")
for ((i = 0; i < ${#all_items[@]}; i++)); do
filtered_indices+=($i)
done
else
# Filter items that contain search term (case insensitive)
for ((i = 0; i < ${#all_items[@]}; i++)); do
if [[ "${all_items[i],,}" == *"${search_term,,}"* ]]; then
filtered_items+=("${all_items[i]}")
filtered_indices+=($i)
fi
done
fi
}
# Function to display current page
show_page() {
local total_filtered=${#filtered_items[@]}
local total_pages=$(( (total_filtered + page_size - 1) / page_size ))
local start_idx=$((current_page * page_size))
local end_idx=$((start_idx + page_size - 1))
if [[ $end_idx -ge $total_filtered ]]; then
end_idx=$((total_filtered - 1))
fi
printf '\033[2J\033[H' >&2
echo "╭─────────────────────────────────────────────────────╮" >&2
echo "$title" >&2
echo "├─────────────────────────────────────────────────────┤" >&2
echo "│ Total: ${#all_items[@]} | Filtered: $total_filtered | Selected: ${#selected_indices[@]}" >&2
if [[ -n "$search_term" ]]; then
echo "│ Search: '$search_term' │" >&2
fi
if [[ $total_pages -gt 1 ]]; then
echo "│ Page $(($current_page + 1)) of $total_pages" >&2
fi
echo "╰─────────────────────────────────────────────────────╯" >&2
echo "" >&2
if [[ $total_filtered -eq 0 ]]; then
echo "No items match your search." >&2
echo "" >&2
else
# Show items for current page
for ((i = start_idx; i <= end_idx && i < total_filtered; i++)); do
local item_idx=${filtered_indices[i]}
local display_num=$((i + 1))
# Check if this item is selected
local is_selected=false
if [[ ${#selected_indices[@]} -gt 0 ]]; then
for selected in "${selected_indices[@]}"; do
if [[ $selected -eq $item_idx ]]; then
is_selected=true
break
fi
done
fi
if [[ $is_selected == true ]]; then
printf "%3d) ✓ %s\n" "$display_num" "${filtered_items[i]}" >&2
else
printf "%3d) %s\n" "$display_num" "${filtered_items[i]}" >&2
fi
done
fi
echo "" >&2
echo "Commands:" >&2
echo " Numbers: Select items (e.g., '1-5', '1 3 7', '10-15')" >&2
echo " /search: Filter items (e.g., '/chrome')" >&2
echo " n/p: Next/Previous page | all: Select all | none: Clear all" >&2
echo " done: Finish selection | quit: Cancel" >&2
echo "" >&2
}
# Main loop
while true; do
filter_items
show_page
read -p "Enter command: " -r input >&2
case "$input" in
"done"|"")
break
;;
"quit"|"q")
return 1
;;
"all")
selected_indices=()
for idx in "${filtered_indices[@]}"; do
selected_indices+=($idx)
done
echo "Selected all filtered items (${#filtered_indices[@]})" >&2
;;
"none")
selected_indices=()
echo "Cleared all selections" >&2
;;
"n"|"next")
local total_pages=$(( (${#filtered_items[@]} + page_size - 1) / page_size ))
if [[ $((current_page + 1)) -lt $total_pages ]]; then
((current_page++))
else
echo "Already on last page" >&2
fi
;;
"p"|"prev")
if [[ $current_page -gt 0 ]]; then
((current_page--))
else
echo "Already on first page" >&2
fi
;;
/*)
# Search functionality
search_term="${input#/}"
current_page=0
echo "Searching for: '$search_term'" >&2
;;
*)
# Parse selection input
parse_selection "$input"
;;
esac
[[ "$input" != "n" && "$input" != "next" && "$input" != "p" && "$input" != "prev" ]] && sleep 1
done
# Return selected indices
local result=""
if [[ ${#selected_indices[@]} -gt 0 ]]; then
for idx in "${selected_indices[@]}"; do
result="$result $idx"
done
echo "${result# }"
else
echo ""
fi
return 0
}
# Parse selection input (supports ranges and individual numbers)
parse_selection() {
local input="$1"
local start_idx=$((current_page * page_size))
# Split input by spaces
read -ra parts <<< "$input"
for part in "${parts[@]}"; do
if [[ "$part" =~ ^[0-9]+$ ]]; then
# Single number
local display_num=$part
local array_idx=$((display_num - 1))
if [[ $array_idx -ge 0 && $array_idx -lt ${#filtered_items[@]} ]]; then
local real_idx=${filtered_indices[array_idx]}
toggle_selection "$real_idx"
else
echo "Invalid selection: $part (range: 1-${#filtered_items[@]})" >&2
fi
elif [[ "$part" =~ ^([0-9]+)-([0-9]+)$ ]]; then
# Range like 1-5
local start_num=${BASH_REMATCH[1]}
local end_num=${BASH_REMATCH[2]}
for ((num = start_num; num <= end_num; num++)); do
local array_idx=$((num - 1))
if [[ $array_idx -ge 0 && $array_idx -lt ${#filtered_items[@]} ]]; then
local real_idx=${filtered_indices[array_idx]}
toggle_selection "$real_idx"
fi
done
else
echo "Invalid format: $part (use numbers, ranges like '1-5', or commands)" >&2
fi
done
}
# Toggle selection of an item
toggle_selection() {
local idx=$1
local already_selected=false
local pos_to_remove=-1
# Check if already selected
if [[ ${#selected_indices[@]} -gt 0 ]]; then
for ((i = 0; i < ${#selected_indices[@]}; i++)); do
if [[ ${selected_indices[i]} -eq $idx ]]; then
already_selected=true
pos_to_remove=$i
break
fi
done
fi
if [[ $already_selected == true ]]; then
# Remove from selection
unset selected_indices[$pos_to_remove]
selected_indices=("${selected_indices[@]}") # Reindex array
echo "Removed: ${all_items[idx]}" >&2
else
# Add to selection
selected_indices+=($idx)
echo "Added: ${all_items[idx]}" >&2
fi
}
# Demo function
demo_smart() {
local test_apps=()
for i in {1..50}; do
test_apps+=("Test App $i (${RANDOM}MB)")
done
echo "=== Smart Multi-select Demo ===" >&2
local result
result=$(smart_multi_select "Choose Applications to Remove" "${test_apps[@]}")
if [[ $? -eq 0 ]]; then
echo "You selected indices: '$result'" >&2
echo "Selected ${result// /,} out of ${#test_apps[@]} items" >&2
else
echo "Selection cancelled" >&2
fi
}
# Run demo if script is executed directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
demo_smart
fi