diff options
author | Yehonal <yehonal.azeroth@gmail.com> | 2025-09-04 00:03:55 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-09-04 00:03:55 +0200 |
commit | 599d206584f801adf3e42fede6bf0496605b60c3 (patch) | |
tree | a8a5f3e49fa250941395e91641fe15dea2c24ba4 /apps/bash_shared | |
parent | d5d8256bc5f733477966f70d0802abdedde0cd2d (diff) |
feat(MenuSystem): Implement unified menu system for AzerothCore management (#22786)
Diffstat (limited to 'apps/bash_shared')
-rw-r--r-- | apps/bash_shared/menu_system.sh | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/apps/bash_shared/menu_system.sh b/apps/bash_shared/menu_system.sh new file mode 100644 index 0000000000..e7ae8b5646 --- /dev/null +++ b/apps/bash_shared/menu_system.sh @@ -0,0 +1,218 @@ +#!/usr/bin/env bash + +# ============================================================================= +# AzerothCore Menu System Library +# ============================================================================= +# This library provides a unified menu system for AzerothCore scripts. +# It supports ordered menu definitions, short commands, numeric selection, +# and proper argument handling. +# +# Features: +# - Single source of truth for menu definitions +# - Automatic ID assignment (1, 2, 3...) +# - Short command aliases (c, i, q, etc.) +# - Interactive mode: numbers + long/short commands +# - Direct mode: only long/short commands (no numbers) +# - Proper argument forwarding +# +# Usage: +# source "path/to/menu_system.sh" +# menu_items=("command|short|description" ...) +# menu_run "Menu Title" callback_function "${menu_items[@]}" "$@" +# ============================================================================= + +# Global arrays for menu state (will be populated by menu_define) +declare -a _MENU_KEYS=() +declare -a _MENU_SHORTS=() +declare -a _MENU_OPTIONS=() + +# Parse menu items and populate global arrays +# Usage: menu_define array_elements... +function menu_define() { + # Clear previous state + _MENU_KEYS=() + _MENU_SHORTS=() + _MENU_OPTIONS=() + + # Parse each menu item: "key|short|description" + local item key short desc + for item in "$@"; do + IFS='|' read -r key short desc <<< "$item" + _MENU_KEYS+=("$key") + _MENU_SHORTS+=("$short") + _MENU_OPTIONS+=("$key ($short): $desc") + done +} + +# Display menu with numbered options +# Usage: menu_display "Menu Title" +function menu_display() { + local title="$1" + + echo "==== $title ====" + for idx in "${!_MENU_OPTIONS[@]}"; do + local num=$((idx + 1)) + printf "%2d) %s\n" "$num" "${_MENU_OPTIONS[$idx]}" + done + echo "" +} + +# Find menu index by user input (number, long command, or short command) +# Returns: index (0-based) or -1 if not found +# Usage: index=$(menu_find_index "user_input") +function menu_find_index() { + local user_input="$1" + + # Try numeric selection first + if [[ "$user_input" =~ ^[0-9]+$ ]]; then + local num=$((user_input - 1)) + if [[ $num -ge 0 && $num -lt ${#_MENU_KEYS[@]} ]]; then + echo "$num" + return 0 + fi + fi + + # Try long command name + local idx + for idx in "${!_MENU_KEYS[@]}"; do + if [[ "$user_input" == "${_MENU_KEYS[$idx]}" ]]; then + echo "$idx" + return 0 + fi + done + + # Try short command + for idx in "${!_MENU_SHORTS[@]}"; do + if [[ "$user_input" == "${_MENU_SHORTS[$idx]}" ]]; then + echo "$idx" + return 0 + fi + done + + echo "-1" + return 1 +} + +# Handle direct execution (command line arguments) +# Disables numeric selection to prevent confusion with command arguments +# Usage: menu_direct_execute callback_function "$@" +function menu_direct_execute() { + local callback="$1" + shift + local user_input="$1" + shift + + # Handle help requests directly + if [[ "$user_input" == "--help" || "$user_input" == "help" || "$user_input" == "-h" ]]; then + echo "Available commands:" + printf '%s\n' "${_MENU_OPTIONS[@]}" + return 0 + fi + + # Disable numeric selection in direct mode + if [[ "$user_input" =~ ^[0-9]+$ ]]; then + echo "Invalid option. Numeric selection is not allowed when passing arguments." + echo "Use command name or short alias instead." + return 1 + fi + + # Find command and execute + local idx + idx=$(menu_find_index "$user_input") + if [[ $idx -ge 0 ]]; then + "$callback" "${_MENU_KEYS[$idx]}" "$@" + return $? + else + echo "Invalid option. Use --help to see available commands." >&2 + return 1 + fi +} + +# Handle interactive menu selection +# Usage: menu_interactive callback_function "Menu Title" +function menu_interactive() { + local callback="$1" + local title="$2" + + while true; do + menu_display "$title" + read -r -p "Please enter your choice: " REPLY + + # Handle help request + if [[ "$REPLY" == "--help" || "$REPLY" == "help" || "$REPLY" == "h" ]]; then + echo "Available commands:" + printf '%s\n' "${_MENU_OPTIONS[@]}" + echo "" + continue + fi + + # Find and execute command + local idx + idx=$(menu_find_index "$REPLY") + if [[ $idx -ge 0 ]]; then + "$callback" "${_MENU_KEYS[$idx]}" + else + echo "Invalid option. Please try again or use 'help' for available commands." >&2 + echo "" + fi + done +} + +# Main menu runner function +# Usage: menu_run "Menu Title" callback_function menu_item1 menu_item2 ... "$@" +function menu_run() { + local title="$1" + local callback="$2" + shift 2 + + # Extract menu items (all arguments until we find command line args) + local menu_items=() + local found_args=false + + # Separate menu items from command line arguments + while [[ $# -gt 0 ]]; do + if [[ "$1" =~ \| ]]; then + # This looks like a menu item (contains pipe) + menu_items+=("$1") + shift + else + # This is a command line argument + found_args=true + break + fi + done + + # Define menu from collected items + menu_define "${menu_items[@]}" + + # Handle direct execution if arguments provided + if [[ $found_args == true ]]; then + menu_direct_execute "$callback" "$@" + return $? + fi + + # Run interactive menu + menu_interactive "$callback" "$title" +} + +# Utility function to show available commands (for --help) +# Usage: menu_show_help +function menu_show_help() { + echo "Available commands:" + printf '%s\n' "${_MENU_OPTIONS[@]}" +} + +# Utility function to get command key by index +# Usage: key=$(menu_get_key index) +function menu_get_key() { + local idx="$1" + if [[ $idx -ge 0 && $idx -lt ${#_MENU_KEYS[@]} ]]; then + echo "${_MENU_KEYS[$idx]}" + fi +} + +# Utility function to get all command keys +# Usage: keys=($(menu_get_all_keys)) +function menu_get_all_keys() { + printf '%s\n' "${_MENU_KEYS[@]}" +} |