From 1c0f5ce0d07434cad0f82a80d08a08df50db38b7 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 29 Jun 2025 13:23:36 +0300 Subject: feat: add random task jump hotkeys and document navigation keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add hotkey '1' to jump to a random pending task - Add hotkey '2' to jump to a random pending task without due date - Both hotkeys include visual feedback with blink animation - Document '0' key as synonym for 'g' and 'Home' in help screen - Update help screen navigation section with all new hotkeys 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- internal/ui/keyhandlers.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++ internal/ui/table.go | 5 +++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/internal/ui/keyhandlers.go b/internal/ui/keyhandlers.go index 14f6abc..027d5db 100644 --- a/internal/ui/keyhandlers.go +++ b/internal/ui/keyhandlers.go @@ -2,6 +2,7 @@ package ui import ( "fmt" + "math/rand" "os/exec" "strings" "time" @@ -107,6 +108,10 @@ func (m *Model) handleNormalMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { return m.handleShowTaskDetail() case "i": return m.handleEnterOrEdit() + case "1": + return m.handleJumpToRandomTask() + case "2": + return m.handleJumpToRandomTaskNoDue() default: // Pass through to table for navigation return m.handleTableNavigation(msg) @@ -735,4 +740,63 @@ func (m *Model) handleTableNavigation(msg tea.KeyMsg) (tea.Model, tea.Cmd) { func (m *Model) showError(err error) { m.statusMsg = fmt.Sprintf("Error: %v", err) // Note: we can't return a Cmd from here, so the error will stay until next update +} + +// handleJumpToRandomTask jumps to a random pending task +func (m *Model) handleJumpToRandomTask() (tea.Model, tea.Cmd) { + if len(m.tasks) == 0 { + m.statusMsg = "No tasks to jump to" + return m, nil + } + + // Pick a random index + randomIndex := rand.Intn(len(m.tasks)) + + // Update cursor position + prevRow := m.tbl.Cursor() + prevCol := m.tbl.ColumnCursor() + m.tbl.SetCursor(randomIndex) + m.updateSelectionHighlight(prevRow, randomIndex, prevCol, m.tbl.ColumnCursor()) + + // Blink the task to indicate jump + if randomIndex < len(m.tasks) { + taskID := m.tasks[randomIndex].ID + return m, m.startBlink(taskID, false) + } + + return m, nil +} + +// handleJumpToRandomTaskNoDue jumps to a random pending task without a due date +func (m *Model) handleJumpToRandomTaskNoDue() (tea.Model, tea.Cmd) { + // Find all tasks without due dates + var noDueTasks []int + for i, task := range m.tasks { + if task.Due == "" { + noDueTasks = append(noDueTasks, i) + } + } + + if len(noDueTasks) == 0 { + m.statusMsg = "No tasks without due date to jump to" + return m, nil + } + + // Pick a random task from the no-due list + randomChoice := rand.Intn(len(noDueTasks)) + randomIndex := noDueTasks[randomChoice] + + // Update cursor position + prevRow := m.tbl.Cursor() + prevCol := m.tbl.ColumnCursor() + m.tbl.SetCursor(randomIndex) + m.updateSelectionHighlight(prevRow, randomIndex, prevCol, m.tbl.ColumnCursor()) + + // Blink the task to indicate jump + if randomIndex < len(m.tasks) { + taskID := m.tasks[randomIndex].ID + return m, m.startBlink(taskID, false) + } + + return m, nil } \ No newline at end of file diff --git a/internal/ui/table.go b/internal/ui/table.go index a3157af..65837a6 100644 --- a/internal/ui/table.go +++ b/internal/ui/table.go @@ -684,8 +684,11 @@ func (m Model) buildHelpContent() string { sections = append(sections, headerStyle.Render("Navigation"), m.formatHelpLine("↑/k, ↓/j", "move up/down", keyStyle, descStyle), m.formatHelpLine("←/h, →/l", "move left/right", keyStyle, descStyle), - m.formatHelpLine("g/Home, G/End", "go to start/end", keyStyle, descStyle), + m.formatHelpLine("0, g, Home", "go to start", keyStyle, descStyle), + m.formatHelpLine("G, End", "go to end", keyStyle, descStyle), m.formatHelpLine("pgup/pgdn, b", "page up/down", keyStyle, descStyle), + m.formatHelpLine("1", "jump to random task", keyStyle, descStyle), + m.formatHelpLine("2", "jump to random task (no due date)", keyStyle, descStyle), "") // Task Management section -- cgit v1.2.3