diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-08 16:04:36 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-08 16:16:20 +0300 |
| commit | 0fc1d8445bd5b2dad6552db87528b6e196236c44 (patch) | |
| tree | fa23f0e221fc5f332eec980b4cac357fe294b807 /internal | |
| parent | d13795080cb8a177d93e593ce91ba3a30b64c5ad (diff) | |
task 1: remove ultra exit duplication
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/ui/keyhandlers.go | 38 | ||||
| -rw-r--r-- | internal/ui/table_test.go | 28 | ||||
| -rw-r--r-- | internal/ui/ultra.go | 60 |
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 { |
