Add offline-first task-master TUI with tickets, board lists, and undo.

Charm-based CLI with JSON persistence, status/list filters, external editor editing, command-history undo/redo, and glamour markdown without AutoStyle OSC hangs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Skruecken
2026-10-19 10:21:48 +02:00
co-authored by Cursor
parent 4a3d0d777b
commit 24c1e146ec
37 changed files with 3259 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
package views
import (
"github.com/charmbracelet/bubbles/list"
"task/internal/project"
)
// ProjectItem wraps a project for bubbles/list.
type ProjectItem struct {
Project project.Project
Active bool
}
func (i ProjectItem) Title() string {
if i.Active {
return i.Project.Name + " *"
}
return i.Project.Name
}
func (i ProjectItem) Description() string { return i.Project.ID }
func (i ProjectItem) FilterValue() string { return i.Project.Name }
// NewProjectList builds a list of projects.
func NewProjectList(projects []project.Project, activeID string, width, height int) list.Model {
items := make([]list.Item, len(projects))
selected := 0
for i, p := range projects {
items[i] = ProjectItem{Project: p, Active: p.ID == activeID}
if p.ID == activeID {
selected = i
}
}
delegate := list.NewDefaultDelegate()
delegate.ShowDescription = false
l := list.New(items, delegate, width, height)
l.Title = "Projects"
l.SetShowStatusBar(false)
l.SetShowHelp(false)
l.SetFilteringEnabled(false)
l.DisableQuitKeybindings()
if len(items) > 0 {
l.Select(selected)
}
return l
}
// ProjectsToItems converts projects to list items.
func ProjectsToItems(projects []project.Project, activeID string) []list.Item {
items := make([]list.Item, len(projects))
for i, p := range projects {
items[i] = ProjectItem{Project: p, Active: p.ID == activeID}
}
return items
}