summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-08 16:04:36 +0300
committerPaul Buetow <paul@buetow.org>2026-04-08 16:16:20 +0300
commit0fc1d8445bd5b2dad6552db87528b6e196236c44 (patch)
treefa23f0e221fc5f332eec980b4cac357fe294b807 /internal
parentd13795080cb8a177d93e593ce91ba3a30b64c5ad (diff)
task 1: remove ultra exit duplication
Diffstat (limited to 'internal')
-rw-r--r--internal/ui/keyhandlers.go38
-rw-r--r--internal/ui/table_test.go28
-rw-r--r--internal/ui/ultra.go60
3 files changed, 66 insertions, 60 deletions
diff --git a/internal/ui/keyhandlers.go b/internal/ui/keyhandlers.go
index f688679..4fe3efb 100644
--- a/internal/ui/keyhandlers.go
+++ b/internal/ui/keyhandlers.go
@@ -152,24 +152,7 @@ func (m *Model) handleQuitKey() (tea.Model, tea.Cmd) {
return m, nil
}
if m.showUltra {
- // Active search: q clears the search filter first, same as in normal
- // table mode. Only proceed to exit/quit when no search is active.
- if m.ultraSearchRegex != nil {
- m.ultraSearchRegex = nil
- m.ultraFiltered = nil
- m.ultraCursor = 0
- m.ultraOffset = 0
- return m, nil
- }
- // When started via --ultra flag there is no table view to return to,
- // so q exits the application directly.
- if m.ultraStartup {
- return m, tea.Quit
- }
- m.ultraClearFocusedID()
- m.showUltra = false
- m.ultraSearchInput.SetValue("")
- return m, nil
+ return m.handleUltraExitKey(true)
}
if m.showTaskDetail {
m.showTaskDetail = false
@@ -207,24 +190,7 @@ func (m *Model) handleEscapeKey() (tea.Model, tea.Cmd) {
return m, nil
}
if m.showUltra {
- // Active search: esc clears the search filter first, same as in
- // normal table mode. It never quits the application.
- if m.ultraSearchRegex != nil {
- m.ultraSearchRegex = nil
- m.ultraFiltered = nil
- m.ultraCursor = 0
- m.ultraOffset = 0
- return m, nil
- }
- // When started via --ultra flag there is no table view to return to,
- // so esc just stays in ultra mode.
- if m.ultraStartup {
- return m, nil
- }
- m.ultraClearFocusedID()
- m.showUltra = false
- m.ultraSearchInput.SetValue("")
- return m, nil
+ return m.handleUltraExitKey(false)
}
if m.showTaskDetail {
m.showTaskDetail = false
diff --git a/internal/ui/table_test.go b/internal/ui/table_test.go
index 7ad079b..ae99206 100644
--- a/internal/ui/table_test.go
+++ b/internal/ui/table_test.go
@@ -1098,7 +1098,7 @@ func TestUltraHelpSearchUsesUltraHelpLines(t *testing.T) {
func TestUltraExitHotkeysClearUltraState(t *testing.T) {
tmp := t.TempDir()
- taskPath := setupBasicTask(t, tmp)
+ taskPath := setupUltraTaskSet(t, tmp)
setupEnv(t, taskPath)
m, err := New(nil, "firefox")
@@ -1191,6 +1191,32 @@ func TestUltraExitHotkeysClearUltraState(t *testing.T) {
if m.ultraFocusedID != 0 {
t.Fatalf("esc did not clear ultraFocusedID, got %d", m.ultraFocusedID)
}
+
+ 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 re-enter ultra mode")
+ }
+ m.ultraCursor = 2
+ m.ultraFocusedID = 31
+
+ mv, cmd = (&m).Update(tea.KeyPressMsg{Code: 'u', Text: "u"})
+ if cmd != nil {
+ t.Fatalf("u in ultra mode unexpectedly returned a command")
+ }
+ m = *mv.(*Model)
+ if m.showUltra {
+ t.Fatalf("u did not exit ultra mode")
+ }
+ if got := m.tbl.Cursor(); got != 2 {
+ t.Fatalf("u did not preserve table cursor: got %d want 2", got)
+ }
+ if m.ultraFocusedID != 0 {
+ t.Fatalf("u did not clear ultraFocusedID, got %d", m.ultraFocusedID)
+ }
}
func TestUltraSearchFiltersNavigatesAndHighlights(t *testing.T) {
diff --git a/internal/ui/ultra.go b/internal/ui/ultra.go
index 4bb9542..e84b472 100644
--- a/internal/ui/ultra.go
+++ b/internal/ui/ultra.go
@@ -475,10 +475,7 @@ func (m *Model) handleUltraSearchMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd)
case "enter":
// Empty input clears the filter; non-empty confirms and keeps it.
if strings.TrimSpace(m.ultraSearchInput.Value()) == "" {
- m.ultraSearchRegex = nil
- m.ultraFiltered = nil
- m.ultraCursor = 0
- m.ultraOffset = 0
+ m.clearUltraSearchState()
}
m.ultraSearching = false
m.ultraSearchInput.Blur()
@@ -488,10 +485,7 @@ func (m *Model) handleUltraSearchMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd)
m.ultraSearching = false
m.ultraSearchInput.SetValue("")
m.ultraSearchInput.Blur()
- m.ultraSearchRegex = nil
- m.ultraFiltered = nil
- m.ultraCursor = 0
- m.ultraOffset = 0
+ m.clearUltraSearchState()
return m, nil
}
@@ -513,10 +507,7 @@ func (m *Model) handleUltraSearchMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd)
func (m *Model) ultraApplySearch(value string) {
value = strings.TrimSpace(value)
if value == "" {
- m.ultraSearchRegex = nil
- m.ultraFiltered = nil
- m.ultraCursor = 0
- m.ultraOffset = 0
+ m.clearUltraSearchState()
return
}
// Prepend (?i) for case-insensitive matching unless the user already
@@ -1016,19 +1007,13 @@ func (m *Model) handleUltraMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
case "esc":
return m.handleEscapeKey()
case "u":
- // Toggle back to the traditional table view. Works even when started
- // via --ultra because the table model always exists; it was just never
- // shown. The user can press u again to return to ultra mode.
- m.ultraClearFocusedID()
- m.showUltra = false
- m.ultraStartup = false // no longer forced into ultra-only mode
- m.ultraSearchRegex = nil
- m.ultraFiltered = nil
- m.ultraSearchInput.SetValue("")
+ cursor := m.ultraCursor
+ m.leaveUltraMode()
+ m.ultraStartup = false
// Sync the table cursor to the task we were on in ultra mode.
tasks := m.ultraTaskList()
- if m.ultraCursor >= 0 && m.ultraCursor < len(tasks) {
- m.tbl.SetCursor(m.ultraCursor)
+ if cursor >= 0 && cursor < len(tasks) {
+ m.tbl.SetCursor(cursor)
}
return m, nil
case "/":
@@ -1142,6 +1127,35 @@ func (m *Model) ultraClearFocusedID() {
m.ultraFocusedID = 0
}
+func (m *Model) clearUltraSearchState() {
+ m.ultraSearchRegex = nil
+ m.ultraFiltered = nil
+ m.ultraCursor = 0
+ m.ultraOffset = 0
+}
+
+func (m *Model) leaveUltraMode() {
+ m.ultraClearFocusedID()
+ m.showUltra = false
+ m.ultraSearchInput.SetValue("")
+ m.clearUltraSearchState()
+}
+
+func (m *Model) handleUltraExitKey(quit bool) (tea.Model, tea.Cmd) {
+ if m.ultraSearchRegex != nil {
+ m.clearUltraSearchState()
+ return m, nil
+ }
+ if m.ultraStartup {
+ if quit {
+ return m, tea.Quit
+ }
+ return m, nil
+ }
+ m.leaveUltraMode()
+ return m, nil
+}
+
func (m *Model) ultraPrepareSelectedTask() (int, bool) {
id, err := m.getUltraSelectedTaskID()
if err != nil {