summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Bütow <1224732+snonux@users.noreply.github.com>2025-06-21 10:53:10 +0300
committerPaul Bütow <1224732+snonux@users.noreply.github.com>2025-06-21 10:53:10 +0300
commit58c8b1bcfb4fbe5a14125952117a21caff7a2598 (patch)
tree399d76959940d62ca8a51e3e37fc30077b3df419
parent5be9563e9154c5b5cbe188601edd17cd1d8906d3 (diff)
fix search selection highlighting
-rw-r--r--internal/ui/table.go70
1 files changed, 55 insertions, 15 deletions
diff --git a/internal/ui/table.go b/internal/ui/table.go
index c03bc7e..796ce1d 100644
--- a/internal/ui/table.go
+++ b/internal/ui/table.go
@@ -44,8 +44,9 @@ type cellMatch struct {
// Model wraps a Bubble Tea table.Model to display tasks.
type Model struct {
- tbl atable.Model
- showHelp bool
+ tbl atable.Model
+ tblStyles atable.Styles
+ showHelp bool
annotating bool
annotateID int
@@ -104,7 +105,7 @@ func New(filters []string) (Model, error) {
return m, nil
}
-func newTable(rows []atable.Row) atable.Model {
+func newTable(rows []atable.Row) (atable.Model, atable.Styles) {
cols := []atable.Column{
{Title: "ID", Width: idWidth},
{Title: "Pri", Width: priWidth},
@@ -126,7 +127,7 @@ func newTable(rows []atable.Row) atable.Model {
styles.Selected = styles.Selected.Foreground(lipgloss.Color("229")).Background(lipgloss.Color("57"))
styles.Cell = styles.Cell.Padding(0, 1)
t.SetStyles(styles)
- return t
+ return t, styles
}
func (m *Model) reload() error {
@@ -143,7 +144,7 @@ func (m *Model) reload() error {
var rows []atable.Row
m.searchMatches = nil
for i, tsk := range tasks {
- rows = append(rows, taskToRowSearch(tsk, m.searchRegex))
+ rows = append(rows, taskToRowSearch(tsk, m.searchRegex, m.tblStyles, -1))
if m.searchRegex != nil {
tags := strings.Join(tsk.Tags, " ")
if m.searchRegex.MatchString(tags) {
@@ -170,10 +171,11 @@ func (m *Model) reload() error {
m.due = task.DueTasks(tasks, time.Now())
if m.tbl.Columns() == nil {
- m.tbl = newTable(rows)
+ m.tbl, m.tblStyles = newTable(rows)
} else {
m.tbl.SetRows(rows)
}
+ m.updateSelectionHighlight(-1, m.tbl.Cursor(), 0, m.tbl.ColumnCursor())
return nil
}
@@ -274,8 +276,11 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.reload()
if len(m.searchMatches) > 0 {
match := m.searchMatches[m.searchIndex]
+ prevRow := m.tbl.Cursor()
+ prevCol := m.tbl.ColumnCursor()
m.tbl.SetCursor(match.row)
m.tbl.SetColumnCursor(match.col)
+ m.updateSelectionHighlight(prevRow, m.tbl.Cursor(), prevCol, m.tbl.ColumnCursor())
}
return m, nil
case tea.KeyEsc:
@@ -421,16 +426,22 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if len(m.searchMatches) > 0 {
m.searchIndex = (m.searchIndex + 1) % len(m.searchMatches)
match := m.searchMatches[m.searchIndex]
+ prevRow := m.tbl.Cursor()
+ prevCol := m.tbl.ColumnCursor()
m.tbl.SetCursor(match.row)
m.tbl.SetColumnCursor(match.col)
+ m.updateSelectionHighlight(prevRow, m.tbl.Cursor(), prevCol, m.tbl.ColumnCursor())
return m, nil
}
case "N":
if len(m.searchMatches) > 0 {
m.searchIndex = (m.searchIndex - 1 + len(m.searchMatches)) % len(m.searchMatches)
match := m.searchMatches[m.searchIndex]
+ prevRow := m.tbl.Cursor()
+ prevCol := m.tbl.ColumnCursor()
m.tbl.SetCursor(match.row)
m.tbl.SetColumnCursor(match.col)
+ m.updateSelectionHighlight(prevRow, m.tbl.Cursor(), prevCol, m.tbl.ColumnCursor())
return m, nil
}
case "enter":
@@ -444,7 +455,12 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
var cmd tea.Cmd
+ prevRow := m.tbl.Cursor()
+ prevCol := m.tbl.ColumnCursor()
m.tbl, cmd = m.tbl.Update(msg)
+ if prevRow != m.tbl.Cursor() || prevCol != m.tbl.ColumnCursor() {
+ m.updateSelectionHighlight(prevRow, m.tbl.Cursor(), prevCol, m.tbl.ColumnCursor())
+ }
return m, cmd
}
@@ -649,10 +665,10 @@ func highlightCell(base lipgloss.Style, re *regexp.Regexp, raw string) string {
return b.String()
}
-func taskToRowSearch(t task.Task, re *regexp.Regexp) atable.Row {
- style := lipgloss.NewStyle()
+func taskToRowSearch(t task.Task, re *regexp.Regexp, styles atable.Styles, selectedCol int) atable.Row {
+ rowStyle := lipgloss.NewStyle()
if t.Start != "" {
- style = style.Background(lipgloss.Color("6"))
+ rowStyle = rowStyle.Background(lipgloss.Color("6"))
}
age := ""
@@ -669,16 +685,26 @@ func taskToRowSearch(t task.Task, re *regexp.Regexp) atable.Row {
anns = append(anns, a.Description)
}
- idStr := style.Render(strconv.Itoa(t.ID))
+ cellStyle := rowStyle.Copy().Inherit(styles.Cell)
+ selStyle := cellStyle.Copy().Inherit(styles.Selected)
+
+ getStyle := func(col int) lipgloss.Style {
+ if col == selectedCol {
+ return selStyle
+ }
+ return cellStyle
+ }
+
+ idStr := getStyle(0).Render(strconv.Itoa(t.ID))
priStr := formatPriority(t.Priority, priWidth)
- ageStr := style.Render(age)
+ ageStr := getStyle(2).Render(age)
dueStr := formatDue(t.Due, dueWidth)
- urgStr := style.Render(urg)
+ urgStr := getStyle(3).Render(urg)
- tagStr := highlightCell(style, re, tags)
- descStr := highlightCell(style, re, t.Description)
+ tagStr := highlightCell(getStyle(5), re, tags)
+ descStr := highlightCell(getStyle(6), re, t.Description)
annRaw := strings.Join(anns, "; ")
- annStr := highlightCell(style, re, annRaw)
+ annStr := highlightCell(getStyle(7), re, annRaw)
return atable.Row{
idStr,
@@ -728,3 +754,17 @@ func (m Model) expandedCellView() string {
style := lipgloss.NewStyle().Width(m.tbl.Width())
return style.Render(val)
}
+
+func (m *Model) updateSelectionHighlight(prevRow, newRow, prevCol, newCol int) {
+ if m.searchRegex == nil {
+ return
+ }
+ rows := m.tbl.Rows()
+ if prevRow >= 0 && prevRow < len(rows) {
+ rows[prevRow] = taskToRowSearch(m.tasks[prevRow], m.searchRegex, m.tblStyles, -1)
+ }
+ if newRow >= 0 && newRow < len(rows) {
+ rows[newRow] = taskToRowSearch(m.tasks[newRow], m.searchRegex, m.tblStyles, newCol)
+ }
+ m.tbl.SetRows(rows)
+}