diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-03 23:20:17 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-03 23:20:30 +0200 |
| commit | 991f31649cf97a94a04c6e9862acab042cbedec0 (patch) | |
| tree | d42208f281db952691e4418cdb048c2d8ce0d793 | |
| parent | b3dfd2441f1448eaa21d0e92346dbb966ccc5163 (diff) | |
bump up version to 0.11.2
Patch release: code quality improvements based on 100 Go Mistakes analysis.
- Fixed race condition in global RNG
- Optimized render performance by lazy-calling .View()
- Improved map pre-allocation
- Handled or explicitly silenced unchecked errors
- Removed unused functions and fields
- Updated deprecated library methods
| -rw-r--r-- | TODO.md | 3 | ||||
| -rw-r--r-- | internal/task/task.go | 2 | ||||
| -rw-r--r-- | internal/ui/handlers.go | 16 | ||||
| -rw-r--r-- | internal/ui/helpers.go | 20 | ||||
| -rw-r--r-- | internal/ui/keyhandlers.go | 10 | ||||
| -rw-r--r-- | internal/ui/table.go | 107 | ||||
| -rw-r--r-- | internal/ui/theme.go | 3 |
7 files changed, 44 insertions, 117 deletions
diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 9a61cff..0000000 --- a/TODO.md +++ /dev/null @@ -1,3 +0,0 @@ -# To-do's - -* As of now nothing here. diff --git a/internal/task/task.go b/internal/task/task.go index d8e2e72..51d1451 100644 --- a/internal/task/task.go +++ b/internal/task/task.go @@ -61,7 +61,7 @@ var dbg debugConfig func SetDebugLog(path string) error { // Close existing debug file if open before re-configuring. if dbg.file != nil { - dbg.file.Close() + _ = dbg.file.Close() dbg.file = nil dbg.writer = nil } diff --git a/internal/ui/handlers.go b/internal/ui/handlers.go index d447c31..11a78cd 100644 --- a/internal/ui/handlers.go +++ b/internal/ui/handlers.go @@ -58,7 +58,7 @@ func (m *Model) handleAnnotationMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { return err } } - m.reload() + _ = m.reload() return nil } @@ -84,7 +84,7 @@ func (m *Model) handleDescriptionMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { if err := task.SetDescription(m.descID, value); err != nil { return err } - m.reload() + _ = m.reload() return nil } @@ -114,9 +114,7 @@ func (m *Model) handleTagsMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { removes = append(removes, tagName) } } else { - if strings.HasPrefix(w, "+") { - w = w[1:] - } + w = strings.TrimPrefix(w, "+") if w != "" { if err := validateTagName(w); err != nil { return fmt.Errorf("add tag '%s': %w", w, err) @@ -135,7 +133,7 @@ func (m *Model) handleTagsMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { return err } } - m.reload() + _ = m.reload() return nil } @@ -204,7 +202,7 @@ func (m *Model) handleRecurrenceMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { if err := task.SetRecurrence(m.recurID, value); err != nil { return err } - m.reload() + _ = m.reload() return nil } @@ -298,7 +296,7 @@ func (m *Model) handlePriorityMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { func (m *Model) handleFilterMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { onEnter := func(value string) error { m.filters = strings.Fields(value) - m.reload() + _ = m.reload() return nil } @@ -313,7 +311,7 @@ func (m *Model) handleFilterMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { func (m *Model) handleAddTaskMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { switch msg.Type { case tea.KeyEnter: - oldIDs := make(map[int]struct{}) + oldIDs := make(map[int]struct{}, len(m.tasks)) for _, tsk := range m.tasks { oldIDs[tsk.ID] = struct{}{} } diff --git a/internal/ui/helpers.go b/internal/ui/helpers.go index 9846811..4cdf3cc 100644 --- a/internal/ui/helpers.go +++ b/internal/ui/helpers.go @@ -22,16 +22,6 @@ func parseTaskDate(dateStr string) (time.Time, error) { return time.Parse(taskDateFormat, dateStr) } -// formatTaskDate formats a time as a Taskwarrior date string -func formatTaskDate(t time.Time) string { - return t.UTC().Format(taskDateFormat) -} - -// daysSince returns the number of days since the given time -func daysSince(t time.Time) int { - return int(time.Since(t).Hours() / 24) -} - // daysUntil returns the number of days until the given time func daysUntil(t time.Time) int { now := time.Now() @@ -101,16 +91,6 @@ func validateTagName(tag string) error { return nil } -// validateTags validates a list of tags -func validateTags(tags []string) error { - for _, tag := range tags { - if err := validateTagName(tag); err != nil { - return fmt.Errorf("invalid tag '%s': %w", tag, err) - } - } - return nil -} - // validateDueDate validates a due date string func validateDueDate(due string) error { if due == "" { diff --git a/internal/ui/keyhandlers.go b/internal/ui/keyhandlers.go index 3db0725..0a2bc62 100644 --- a/internal/ui/keyhandlers.go +++ b/internal/ui/keyhandlers.go @@ -28,16 +28,16 @@ func (m *Model) handleNormalMode(msg tea.KeyMsg) (tea.Model, tea.Cmd) { case "N": return m.handlePrevHelpSearchMatch() case "up", "k": - m.helpViewport.LineUp(1) + m.helpViewport.ScrollUp(1) return m, nil case "down", "j": - m.helpViewport.LineDown(1) + m.helpViewport.ScrollDown(1) return m, nil case "pgup", "b": - m.helpViewport.ViewUp() + m.helpViewport.PageUp() return m, nil case "pgdown", " ": - m.helpViewport.ViewDown() + m.helpViewport.PageDown() return m, nil case "g", "home": m.helpViewport.GotoTop() @@ -337,7 +337,7 @@ func (m *Model) handleRandomDueDate() (tea.Model, tea.Cmd) { return m, nil } - days := rng.Intn(31) + 7 + days := rand.Intn(31) + 7 due := time.Now().AddDate(0, 0, days).Format("2006-01-02") if err := task.SetDueDate(id, due); err != nil { diff --git a/internal/ui/table.go b/internal/ui/table.go index bfdc803..05c0548 100644 --- a/internal/ui/table.go +++ b/internal/ui/table.go @@ -2,7 +2,6 @@ package ui import ( "fmt" - "math/rand" "os" "os/exec" "regexp" @@ -27,7 +26,6 @@ var priorityOptions = []string{"H", "M", "L", ""} var ( urlRegex = regexp.MustCompile(`https?://\S+`) searchRegexCache = make(map[string]*regexp.Regexp) - rng = rand.New(rand.NewSource(time.Now().UnixNano())) ) type cellMatch struct { @@ -78,7 +76,6 @@ type detailViewState struct { // detailDescEditing lives here (not in editState) because it drives an // external-editor launch from the detail overlay, not inline text input. detailDescEditing bool // whether the description editor is open - detailDescTempFile string // temp file path for description editing } // editState holds inline field-editing state for the task table. @@ -208,9 +205,9 @@ func editDescriptionCmd(description string) tea.Cmd { // Write current description to temp file _, err = tmpFile.WriteString(description) - tmpFile.Close() + _ = tmpFile.Close() if err != nil { - os.Remove(tmpPath) + _ = os.Remove(tmpPath) return descEditDoneMsg{err: err, tempFile: ""} } @@ -524,7 +521,7 @@ func (m *Model) handleEditDone(msg editDoneMsg) (tea.Model, tea.Cmd) { // handleDescEditDone handles the completion of description editing func (m *Model) handleDescEditDone(msg descEditDoneMsg) (tea.Model, tea.Cmd) { m.detailDescEditing = false - defer os.Remove(msg.tempFile) // Clean up temp file + _ = os.Remove(msg.tempFile) // Clean up temp file if msg.err != nil { m.statusMsg = fmt.Sprintf("Edit error: %v", msg.err) @@ -642,26 +639,32 @@ func (m Model) View() string { // (annotate, due, priority, desc, tags, recur, project, filter, add, search) // should be displayed below the table. At most one is active at a time. func (m Model) appendInlineInputOverlay(view string) string { - type overlay struct { - active bool - widget string - } - overlays := []overlay{ - {m.annotating, m.annotateInput.View()}, - {m.dueEditing, m.dueView(true)}, - {m.prioritySelecting, m.priorityView(true)}, - {m.descEditing, m.descInput.View()}, - {m.tagsEditing, m.tagsInput.View()}, - {m.recurEditing, m.recurInput.View()}, - {m.projEditing, m.projInput.View()}, - {m.filterEditing, m.filterInput.View()}, - {m.addingTask, m.addInput.View()}, - {m.searching, m.searchInput.View()}, - } - for _, o := range overlays { - if o.active { - view = lipgloss.JoinVertical(lipgloss.Left, view, o.widget) - } + var overlay string + switch { + case m.annotating: + overlay = m.annotateInput.View() + case m.dueEditing: + overlay = m.dueView(true) + case m.prioritySelecting: + overlay = m.priorityView(true) + case m.descEditing: + overlay = m.descInput.View() + case m.tagsEditing: + overlay = m.tagsInput.View() + case m.recurEditing: + overlay = m.recurInput.View() + case m.projEditing: + overlay = m.projInput.View() + case m.filterEditing: + overlay = m.filterInput.View() + case m.addingTask: + overlay = m.addInput.View() + case m.searching: + overlay = m.searchInput.View() + } + + if overlay != "" { + view = lipgloss.JoinVertical(lipgloss.Left, view, overlay) } return view } @@ -888,49 +891,6 @@ func (m Model) topStatusLine() string { Render(line) } -func (m Model) taskToRow(t task.Task) atable.Row { - style := lipgloss.NewStyle() - if t.Start != "" { - style = style.Background(lipgloss.Color(m.theme.StartBG)) - } - if t.ID == m.blinkID && m.blinkOn { - style = style.Reverse(true) - } - - age := "" - if ts, err := time.Parse(task.DateFormat, t.Entry); err == nil { - days := int(time.Since(ts).Hours() / 24) - age = fmt.Sprintf("%dd", days) - } - - tags := strings.Join(t.Tags, " ") - urg := fmt.Sprintf("%.1f", t.Urgency) - recur := t.Recur - - var anns []string - for _, a := range t.Annotations { - anns = append(anns, a.Description) - } - - annStr := "" - if n := len(anns); n > 0 { - annStr = strconv.FormatInt(int64(n), 16) - } - - return atable.Row{ - m.formatPriority(t.Priority, m.priWidth), - style.Render(strconv.Itoa(t.ID)), - style.Render(age), - m.formatDue(t.Due, m.dueWidth), - style.Render(recur), - style.Render(t.Project), - style.Render(tags), - style.Render(annStr), - style.Render(t.Description), - style.Render(m.formatUrgency(urg, m.urgWidth)), - } -} - // formatDue returns a formatted due date string. Dates due today or tomorrow // are returned as "today" or "tomorrow" respectively. Past due dates are // highlighted in red. @@ -1292,12 +1252,3 @@ func (m *Model) applyTheme() { func (m *Model) SetDisco(d bool) { m.disco = d } - -func centerLines(s string, width int) string { - lines := strings.Split(strings.TrimRight(s, "\n"), "\n") - style := lipgloss.NewStyle().Width(width).Align(lipgloss.Center) - for i, l := range lines { - lines[i] = style.Render(l) - } - return strings.Join(lines, "\n") -} diff --git a/internal/ui/theme.go b/internal/ui/theme.go index 7faebf5..9d81aab 100644 --- a/internal/ui/theme.go +++ b/internal/ui/theme.go @@ -1,6 +1,7 @@ package ui import ( + "math/rand" "strconv" ) @@ -63,7 +64,7 @@ func RandomTheme() Theme { } func randColor() string { - return strconv.Itoa(rng.Intn(256)) + return strconv.Itoa(rand.Intn(256)) } func contrastColor(bg string) string { |
