From b06f53cb17336114beb87d521440880bdc88d3b5 Mon Sep 17 00:00:00 2001 From: Michel Abboud Date: Wed, 28 Jan 2026 23:28:56 +0000 Subject: [PATCH] fix: Interactive menu not displaying and slow status checks - Send menu prompts to stderr so they display in terminal - Read user input from /dev/tty for proper interactive mode - Add status cache to fetch all container states in one Docker call - Handle interactive_select errors properly in all callers Co-Authored-By: Claude Opus 4.5 --- winctl.sh | 145 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 101 insertions(+), 44 deletions(-) diff --git a/winctl.sh b/winctl.sh index 46abb4c..4130ffd 100755 --- a/winctl.sh +++ b/winctl.sh @@ -321,24 +321,55 @@ compose_cmd() { fi } +# Cache for container statuses (populated by refresh_status_cache) +declare -A _STATUS_CACHE=() +_STATUS_CACHE_VALID=false + +# Refresh the status cache with a single docker call +refresh_status_cache() { + _STATUS_CACHE=() + local line + while IFS= read -r line; do + if [[ -n "$line" ]]; then + local name state + name="${line%%:*}" + state="${line#*:}" + _STATUS_CACHE["$name"]="$state" + fi + done < <(docker ps -a --format '{{.Names}}:{{.State}}' 2>/dev/null) + _STATUS_CACHE_VALID=true +} + # Check if a container is running is_running() { local version="$1" - docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${version}$" + if [[ "$_STATUS_CACHE_VALID" == "true" ]]; then + [[ "${_STATUS_CACHE[$version]:-}" == "running" ]] + else + docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${version}$" + fi } # Check if a container exists (running or stopped) container_exists() { local version="$1" - docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "^${version}$" + if [[ "$_STATUS_CACHE_VALID" == "true" ]]; then + [[ -n "${_STATUS_CACHE[$version]:-}" ]] + else + docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "^${version}$" + fi } # Get container status get_status() { local version="$1" - local status - status=$(docker ps -a --filter "name=^${version}$" --format '{{.State}}' 2>/dev/null) - echo "${status:-not created}" + if [[ "$_STATUS_CACHE_VALID" == "true" ]]; then + echo "${_STATUS_CACHE[$version]:-not created}" + else + local status + status=$(docker ps -a --filter "name=^${version}$" --format '{{.State}}' 2>/dev/null) + echo "${status:-not created}" + fi } # Get compose file path for version @@ -389,21 +420,23 @@ get_versions_by_category() { echo "${versions[*]}" } -# Show category menu +# Show category menu (prompts to stderr, result to stdout) select_category() { - header "Select Category" - echo "" - echo " ${BOLD}1${RESET}) Desktop (Win 11, 10, 8.1, 7)" - echo " ${BOLD}2${RESET}) Legacy (Vista, XP, 2000)" - echo " ${BOLD}3${RESET}) Server (2025, 2022, 2019, 2016, 2012, 2008, 2003)" - echo " ${BOLD}4${RESET}) Tiny (Tiny11, Tiny10)" - echo " ${BOLD}5${RESET}) All versions" - echo " ${BOLD}6${RESET}) Select individual versions" - echo "" - echo -n " Select [1-6]: " + { + header "Select Category" + echo "" + echo " ${BOLD}1${RESET}) Desktop (Win 11, 10, 8.1, 7)" + echo " ${BOLD}2${RESET}) Legacy (Vista, XP, 2000)" + echo " ${BOLD}3${RESET}) Server (2025, 2022, 2019, 2016, 2012, 2008, 2003)" + echo " ${BOLD}4${RESET}) Tiny (Tiny11, Tiny10)" + echo " ${BOLD}5${RESET}) All versions" + echo " ${BOLD}6${RESET}) Select individual versions" + echo "" + echo -n " Select [1-6]: " + } >&2 local choice - read -r choice + read -r choice &2 local input - read -r input + read -r input