summaryrefslogtreecommitdiff
path: root/apps/bash_shared
diff options
context:
space:
mode:
authorYehonal <yehonal.azeroth@gmail.com>2025-09-04 00:03:55 +0200
committerGitHub <noreply@github.com>2025-09-04 00:03:55 +0200
commit599d206584f801adf3e42fede6bf0496605b60c3 (patch)
treea8a5f3e49fa250941395e91641fe15dea2c24ba4 /apps/bash_shared
parentd5d8256bc5f733477966f70d0802abdedde0cd2d (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.sh218
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[@]}"
+}