diff --git a/lib/core/ui.sh b/lib/core/ui.sh index fe98143..c9feab4 100755 --- a/lib/core/ui.sh +++ b/lib/core/ui.sh @@ -170,7 +170,43 @@ read_key() { case "$key" in $'\n' | $'\r') echo "ENTER" ;; $'\x7f' | $'\x08') echo "DELETE" ;; - $'\x1b') echo "QUIT" ;; + $'\x1b') + # Check if this is an escape sequence (arrow keys) or ESC key + if IFS= read -r -s -n 1 -t 0.1 rest 2> /dev/null; then + if [[ "$rest" == "[" ]]; then + if IFS= read -r -s -n 1 -t 0.1 rest2 2> /dev/null; then + case "$rest2" in + "A") echo "UP" ;; + "B") echo "DOWN" ;; + "C") echo "RIGHT" ;; + "D") echo "LEFT" ;; + "3") + IFS= read -r -s -n 1 -t 0.1 rest3 2> /dev/null + [[ "$rest3" == "~" ]] && echo "DELETE" || echo "OTHER" + ;; + *) echo "OTHER" ;; + esac + else echo "QUIT"; fi + elif [[ "$rest" == "O" ]]; then + if IFS= read -r -s -n 1 -t 0.1 rest2 2> /dev/null; then + case "$rest2" in + "A") echo "UP" ;; + "B") echo "DOWN" ;; + "C") echo "RIGHT" ;; + "D") echo "LEFT" ;; + *) echo "OTHER" ;; + esac + else echo "OTHER"; fi + else + # Not an escape sequence, it's ESC key + echo "QUIT" + fi + else + # No following characters, it's ESC key + echo "QUIT" + fi + ;; + ' ') echo "SPACE" ;; # Allow space in filter mode for selection [[:print:]]) echo "CHAR:$key" ;; *) echo "OTHER" ;; esac diff --git a/lib/ui/menu_paginated.sh b/lib/ui/menu_paginated.sh index 6722947..26e8661 100755 --- a/lib/ui/menu_paginated.sh +++ b/lib/ui/menu_paginated.sh @@ -201,7 +201,6 @@ paginated_multi_select() { export MOLE_MENU_SORT_MODE="$sort_mode" export MOLE_MENU_SORT_REVERSE="$sort_reverse" restore_terminal - unset MOLE_READ_KEY_FORCE_CHAR } # Interrupt handler @@ -595,7 +594,6 @@ paginated_multi_select() { "QUIT") if [[ "$filter_mode" == "true" ]]; then filter_mode="false" - unset MOLE_READ_KEY_FORCE_CHAR filter_query="" applied_query="" top_index=0 @@ -791,7 +789,6 @@ paginated_multi_select() { else # Enter filter mode filter_mode="true" - export MOLE_READ_KEY_FORCE_CHAR=1 filter_query="" top_index=0 cursor_pos=0 @@ -839,6 +836,46 @@ paginated_multi_select() { continue fi ;; + "TOUCHID") + if [[ "$filter_mode" == "true" ]]; then + filter_query+="t" + rebuild_view + need_full_redraw=true + continue + fi + ;; + "RIGHT") + if [[ "$filter_mode" == "true" ]]; then + filter_query+="l" + rebuild_view + need_full_redraw=true + continue + fi + ;; + "LEFT") + if [[ "$filter_mode" == "true" ]]; then + filter_query+="h" + rebuild_view + need_full_redraw=true + continue + fi + ;; + "MORE") + if [[ "$filter_mode" == "true" ]]; then + filter_query+="m" + rebuild_view + need_full_redraw=true + continue + fi + ;; + "UPDATE") + if [[ "$filter_mode" == "true" ]]; then + filter_query+="u" + rebuild_view + need_full_redraw=true + continue + fi + ;; "CHAR:f" | "CHAR:F") if [[ "$filter_mode" == "true" ]]; then filter_query+="${key#CHAR:}" @@ -906,17 +943,9 @@ paginated_multi_select() { if [[ "$filter_mode" == "true" ]]; then applied_query="$filter_query" filter_mode="false" - unset MOLE_READ_KEY_FORCE_CHAR - top_index=0 - cursor_pos=0 - - searching="true" - draw_menu # paint "searching..." - drain_pending_input # drop any extra keypresses (e.g., double-Enter) + # Preserve cursor/top_index so navigation during search is respected rebuild_view - searching="false" - draw_menu - continue + # Fall through to confirmation logic fi # In normal mode: smart Enter behavior # 1. Check if any items are already selected