TUI: Ctrl-O cycles tabs (Alt-digits die in tmux/vterm)
ober
5da02b692071c181c70418c05bcf7df02b004468
--- a/src/jcode/ui/tui.ss +++ b/src/jcode/ui/tui.ss @@ -410,6 +410,14 @@ (toast-add! 'success "Theme" "Theme cycled") (app-state-dirty?-set! state #t)) + ;; Global: Ctrl-O cycle to the next tab. The Alt-1..9 direct jumps + ;; don't survive tmux/emacs-vterm (Alt is eaten or remapped), and + ;; Ctrl-Tab has no distinct byte sequence in a raw terminal (Tab IS + ;; Ctrl-I) -- a plain Ctrl-letter is what reliably gets through. + ((= key TB_KEY_CTRL_O) + (tui-log " -> cycle-tab (ctrl-o)") + (cycle-tab! state)) + ;; Global: Ctrl-R toggle Reasoning (<think>) on latest assistant block ((= key TB_KEY_CTRL_R) (tui-log " -> toggle-reasoning") @@ -655,7 +663,7 @@ " /grok [prompt] Open/focus a Grok CLI tab (sessioned)" " /resume <id> Resume a stored session in this tab (/sessions lists)" " /side [prompt] Open a parallel jcode conversation (own tab)" - " /tab N Switch to tab N (also Alt-1..Alt-9)" + " /tab N Switch to tab N (Ctrl-O cycles; Alt-1..9 where it works)" " /tabs List open tabs" " /activity Live harness activity screen (Esc returns)" " /jcode Switch back to the main jcode tab" @@ -2326,6 +2334,16 @@ (app-state-dirty?-set! state #t) #t))))) +(def (cycle-tab! state) + ;; Ctrl-O: hop to the next tab, wrapping. The reliable way to switch + ;; under tmux/vterm where Alt-digit jumps never arrive. + (ensure-tabs-seeded! state) + (let ((n (length (app-state-tabs state)))) + (if (< n 2) + (toast-add! 'info "Tabs" "Only one tab -- /side opens another") + (switch-tab! state + (modulo (+ (app-state-active-tab state) 1) n))))) + (def (find-external-tab-idx state provider) (let loop ((tabs (app-state-tabs state)) (i 0)) (cond @@ -2404,7 +2422,7 @@ (app-state-active-tab-set! state new-idx) (add-message! state (msg-block-system - (format "Side conversation (tab ~a). Alt-1..Alt-9 or /tab N to switch; /tabs to list; /close-tab to close." + (format "Side conversation (tab ~a). Ctrl-O or /tab N to switch; /tabs to list; /close-tab to close." new-idx))) (when (and (string? initial-prompt) (not (string=? (string-trim initial-prompt) "")))