Add things

This commit is contained in:
Martin Pander
2026-02-10 15:54:08 +01:00
parent e35f480248
commit 703ed981ac
13 changed files with 901 additions and 50 deletions

View File

@@ -27,6 +27,7 @@ type Model struct {
focus bool
styles common.TableStyle
styleFunc StyleFunc
taskTree *taskwarrior.TaskTree
viewport viewport.Model
start int
@@ -242,9 +243,31 @@ func (m *Model) parseColumns(cols []Column) []Column {
return cols
}
// Calculate max tree depth for indentation
maxTreeWidth := 0
if m.taskTree != nil {
for _, node := range m.taskTree.FlatList {
// Calculate indentation: depth * 2 spaces + tree characters (3 chars for "└─ ")
treeWidth := 0
if node.Depth > 0 {
treeWidth = node.Depth*2 + 3
}
// Add progress indicator width for parent tasks (e.g., " (3/5)" = 6 chars max)
if node.HasChildren() {
treeWidth += 7
}
maxTreeWidth = max(maxTreeWidth, treeWidth)
}
}
for i, col := range cols {
for _, task := range m.rows {
col.ContentWidth = max(col.ContentWidth, lipgloss.Width(task.GetString(col.Name)))
contentWidth := lipgloss.Width(task.GetString(col.Name))
// Add tree width to description column
if strings.Contains(col.Name, "description") {
contentWidth += maxTreeWidth
}
col.ContentWidth = max(col.ContentWidth, contentWidth)
}
cols[i] = col
}
@@ -351,6 +374,13 @@ func WithKeyMap(km KeyMap) Option {
}
}
// WithTaskTree sets the task tree for hierarchical display.
func WithTaskTree(tree *taskwarrior.TaskTree) Option {
return func(m *Model) {
m.taskTree = tree
}
}
// Update is the Bubble Tea update loop.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
if !m.focus {
@@ -571,6 +601,21 @@ func (m Model) headersView() string {
func (m *Model) renderRow(r int) string {
var s = make([]string, 0, len(m.cols))
// Extract tree metadata for this row
var depth int
var hasChildren bool
var progress string
if m.taskTree != nil && r < len(m.taskTree.FlatList) {
node := m.taskTree.FlatList[r]
depth = node.Depth
hasChildren = node.HasChildren()
if hasChildren {
completed, total := node.GetChildrenStatus()
progress = fmt.Sprintf(" (%d/%d)", completed, total)
}
}
for i, col := range m.cols {
// for i, task := range m.rows[r] {
if m.cols[i].Width <= 0 {
@@ -589,8 +634,16 @@ func (m *Model) renderRow(r int) string {
cellStyle = cellStyle.Inherit(m.styles.Selected)
}
// Render cell content with tree formatting for description column
var cellContent string
if strings.Contains(col.Name, "description") && m.taskTree != nil {
cellContent = m.renderTreeDescription(r, depth, hasChildren, progress)
} else {
cellContent = m.rows[r].GetString(col.Name)
}
style := lipgloss.NewStyle().Width(m.cols[i].Width).MaxWidth(m.cols[i].Width).Inline(true)
renderedCell := cellStyle.Render(style.Render(runewidth.Truncate(m.rows[r].GetString(col.Name), m.cols[i].Width, "…")))
renderedCell := cellStyle.Render(style.Render(runewidth.Truncate(cellContent, m.cols[i].Width, "…")))
s = append(s, renderedCell)
}
@@ -603,6 +656,25 @@ func (m *Model) renderRow(r int) string {
return row
}
// renderTreeDescription renders the description column with tree indentation and progress
func (m *Model) renderTreeDescription(rowIdx int, depth int, hasChildren bool, progress string) string {
task := m.rows[rowIdx]
desc := task.Description
// Build indentation and tree characters
prefix := ""
if depth > 0 {
prefix = strings.Repeat(" ", depth) + "└─ "
}
// Add progress indicator for parent tasks
if hasChildren {
desc = desc + progress
}
return prefix + desc
}
func max(a, b int) int {
if a > b {
return a

View File

@@ -187,14 +187,14 @@ func (t *TimestampEditor) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
t.adjustDate(1)
}
// Time field adjustments (uppercase - 30 minutes) or date adjustments (week)
// Time field adjustments (uppercase - 60 minutes) or date adjustments (week)
case "J":
// Set current time on first edit if empty
if t.isEmpty {
t.setCurrentTime()
}
if t.currentField == TimeField {
t.adjustTime(-30)
t.adjustTime(-60)
} else {
t.adjustDate(-7)
}
@@ -204,7 +204,7 @@ func (t *TimestampEditor) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
t.setCurrentTime()
}
if t.currentField == TimeField {
t.adjustTime(30)
t.adjustTime(60)
} else {
t.adjustDate(7)
}