summaryrefslogtreecommitdiff
path: root/internal/ui/table.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-03 23:20:17 +0200
committerPaul Buetow <paul@buetow.org>2026-03-03 23:20:30 +0200
commit991f31649cf97a94a04c6e9862acab042cbedec0 (patch)
treed42208f281db952691e4418cdb048c2d8ce0d793 /internal/ui/table.go
parentb3dfd2441f1448eaa21d0e92346dbb966ccc5163 (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
Diffstat (limited to 'internal/ui/table.go')
-rw-r--r--internal/ui/table.go107
1 files changed, 29 insertions, 78 deletions
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")
-}