summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-28 09:14:22 +0200
committerPaul Buetow <paul@buetow.org>2026-04-07 09:24:18 +0300
commitf82d40e06b5346218819fb22fea34f598dd4157d (patch)
tree9a73d9013a3b8ff3a0fac2e5c43a92eea47ed860
parent305e1954e73ba0247033918be8ebc68e6fd4969c (diff)
ui: add ultra mode entry and exit hotkeys (vl vm)
-rw-r--r--internal/ui/keyhandlers.go12
-rw-r--r--internal/ui/table_test.go70
-rw-r--r--internal/ui/ultra.go4
3 files changed, 86 insertions, 0 deletions
diff --git a/internal/ui/keyhandlers.go b/internal/ui/keyhandlers.go
index 528a8c8..b645a9c 100644
--- a/internal/ui/keyhandlers.go
+++ b/internal/ui/keyhandlers.go
@@ -110,6 +110,11 @@ func (m *Model) handleNormalMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
return m.handleShowTaskDetail()
case "i":
return m.handleEnterOrEdit()
+ case "u":
+ m.showUltra = true
+ m.ultraCursor = m.tbl.Cursor()
+ m.ultraOffset = 0
+ return m, nil
case "1":
return m.handleJumpToRandomTask()
case "2":
@@ -139,6 +144,13 @@ func (m *Model) handleToggleHelp() (tea.Model, tea.Cmd) {
}
func (m *Model) handleQuitOrEscape() (tea.Model, tea.Cmd) {
+ if m.showUltra {
+ m.showUltra = false
+ m.ultraSearchRegex = nil
+ m.ultraFiltered = nil
+ m.ultraSearchInput.SetValue("")
+ return m, nil
+ }
if m.showTaskDetail {
m.showTaskDetail = false
m.currentTaskDetail = nil
diff --git a/internal/ui/table_test.go b/internal/ui/table_test.go
index 25eea72..ec2b9bc 100644
--- a/internal/ui/table_test.go
+++ b/internal/ui/table_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
+ "regexp"
"strings"
"testing"
"time"
@@ -659,6 +660,75 @@ func TestEscClosesHelp(t *testing.T) {
}
}
+func TestUltraExitHotkeysClearUltraState(t *testing.T) {
+ tmp := t.TempDir()
+ taskPath := setupBasicTask(t, tmp)
+ setupEnv(t, taskPath)
+
+ m, err := New(nil, "firefox")
+ if err != nil {
+ t.Fatalf("New: %v", err)
+ }
+
+ mv, cmd := (&m).Update(tea.KeyPressMsg{Code: 'u', Text: "u"})
+ if cmd != nil {
+ t.Fatalf("u unexpectedly returned a command")
+ }
+ m = *mv.(*Model)
+ if !m.showUltra {
+ t.Fatalf("u did not enter ultra mode")
+ }
+
+ m.ultraSearchRegex = regexp.MustCompile("alpha")
+ m.ultraFiltered = []int{0, 1}
+ m.ultraSearchInput.SetValue("ultra needle")
+
+ mv, cmd = (&m).Update(tea.KeyPressMsg{Code: 'q', Text: "q"})
+ if cmd != nil {
+ t.Fatalf("q in ultra mode unexpectedly returned a command")
+ }
+ m = *mv.(*Model)
+ if m.showUltra {
+ t.Fatalf("q did not exit ultra mode")
+ }
+ if m.ultraSearchRegex != nil {
+ t.Fatalf("q did not clear ultraSearchRegex")
+ }
+ if m.ultraFiltered != nil {
+ t.Fatalf("q did not clear ultraFiltered")
+ }
+ if got := m.ultraSearchInput.Value(); got != "" {
+ t.Fatalf("q did not clear ultraSearchInput, got %q", got)
+ }
+
+ mv, cmd = (&m).Update(tea.KeyPressMsg{Code: 'u', Text: "u"})
+ if cmd != nil {
+ t.Fatalf("u unexpectedly returned a command on re-entry")
+ }
+ m = *mv.(*Model)
+ m.ultraSearchRegex = regexp.MustCompile("beta")
+ m.ultraFiltered = []int{2}
+ m.ultraSearchInput.SetValue("second needle")
+
+ mv, cmd = (&m).Update(tea.KeyPressMsg{Code: tea.KeyEsc})
+ if cmd != nil {
+ t.Fatalf("esc in ultra mode unexpectedly returned a command")
+ }
+ m = *mv.(*Model)
+ if m.showUltra {
+ t.Fatalf("esc did not exit ultra mode")
+ }
+ if m.ultraSearchRegex != nil {
+ t.Fatalf("esc did not clear ultraSearchRegex")
+ }
+ if m.ultraFiltered != nil {
+ t.Fatalf("esc did not clear ultraFiltered")
+ }
+ if got := m.ultraSearchInput.Value(); got != "" {
+ t.Fatalf("esc did not clear ultraSearchInput, got %q", got)
+ }
+}
+
// TestExpandedCellViewNoDoubleRender is a regression test for a bug where
// expandedCellView() was appended to the layout unconditionally AND again
// inside the cellExpanded guard, producing a duplicate line when expanded.
diff --git a/internal/ui/ultra.go b/internal/ui/ultra.go
index 551ece8..f4b7cf4 100644
--- a/internal/ui/ultra.go
+++ b/internal/ui/ultra.go
@@ -10,5 +10,9 @@ func (m *Model) renderUltraModus() string {
// handleUltraMode handles keyboard input in ultra mode.
func (m *Model) handleUltraMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
+ switch msg.String() {
+ case "q", "esc":
+ return m.handleQuitOrEscape()
+ }
return m, nil
}