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:
@@ -0,0 +1,7 @@
|
||||
package project
|
||||
|
||||
// Project is a lightweight workspace identified by a directory name.
|
||||
type Project struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package project
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Store manages project directories under DataDir/projects.
|
||||
type Store interface {
|
||||
List() ([]Project, error)
|
||||
Ensure(id string) error
|
||||
}
|
||||
|
||||
// DirStore discovers projects as subdirectories of dataDir/projects.
|
||||
type DirStore struct {
|
||||
dataDir string
|
||||
}
|
||||
|
||||
// NewDirStore creates a project store rooted at dataDir.
|
||||
func NewDirStore(dataDir string) *DirStore {
|
||||
return &DirStore{dataDir: dataDir}
|
||||
}
|
||||
|
||||
func (s *DirStore) projectsRoot() string {
|
||||
return filepath.Join(s.dataDir, "projects")
|
||||
}
|
||||
|
||||
// List returns all project directories, sorted by name.
|
||||
func (s *DirStore) List() ([]Project, error) {
|
||||
root := s.projectsRoot()
|
||||
entries, err := os.ReadDir(root)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return []Project{}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("list projects: %w", err)
|
||||
}
|
||||
|
||||
var projects []Project
|
||||
for _, e := range entries {
|
||||
if !e.IsDir() {
|
||||
continue
|
||||
}
|
||||
name := e.Name()
|
||||
projects = append(projects, Project{ID: name, Name: name})
|
||||
}
|
||||
sort.Slice(projects, func(i, j int) bool {
|
||||
return projects[i].Name < projects[j].Name
|
||||
})
|
||||
return projects, nil
|
||||
}
|
||||
|
||||
// Ensure creates the project directory if it does not exist.
|
||||
func (s *DirStore) Ensure(id string) error {
|
||||
if id == "" {
|
||||
return fmt.Errorf("project id is required")
|
||||
}
|
||||
dir := filepath.Join(s.projectsRoot(), id)
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return fmt.Errorf("create project %s: %w", id, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user