feat: improve CLI output with relative dates, rich feedback, and recurring task info
Add relative date formatting (today, tomorrow, in 3d, etc.) for list and detail views. Add structured feedback helpers for add/complete/delete operations showing display IDs and parsed modifiers. Change Complete() to return spawned recurring instance so callers can display recurrence info. Add AppendTask to working set for immediate display ID assignment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+13
-5
@@ -63,11 +63,14 @@ func addTask(args []string) error {
|
||||
return fmt.Errorf("failed to create task: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Created task %s\n", task.UUID)
|
||||
if len(task.Tags) > 0 {
|
||||
fmt.Printf("Tags: %s\n", strings.Join(task.Tags, ", "))
|
||||
displayID, err := engine.AppendTask(task)
|
||||
if err != nil {
|
||||
// Non-fatal: task was created, just can't assign display ID
|
||||
fmt.Printf("Created task %s\n", task.UUID)
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Print(engine.FormatAddFeedback(task, displayID))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -110,8 +113,13 @@ func addRecurringTask(description string, mod *engine.Modifier) error {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Created recurring task %s\n", *instance.ParentUUID)
|
||||
fmt.Printf("First instance: %s\n", instance.UUID)
|
||||
displayID, err := engine.AppendTask(instance)
|
||||
if err != nil {
|
||||
fmt.Printf("Created recurring task %s\n", *instance.ParentUUID)
|
||||
fmt.Printf("First instance: %s\n", instance.UUID)
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Print(engine.FormatRecurringAddFeedback(instance, displayID))
|
||||
return nil
|
||||
}
|
||||
|
||||
+14
-6
@@ -53,17 +53,25 @@ func deleteTasks(args []string) error {
|
||||
return fmt.Errorf("no tasks matched filter")
|
||||
}
|
||||
|
||||
fmt.Printf("Delete %d task(s)? (y/N): ", len(tasks))
|
||||
var confirm string
|
||||
fmt.Scanln(&confirm)
|
||||
if confirm != "y" && confirm != "Y" {
|
||||
return nil
|
||||
if len(tasks) > 1 {
|
||||
fmt.Print(engine.FormatTaskConfirmList("delete", tasks, ws))
|
||||
fmt.Printf("Proceed? (y/N): ")
|
||||
var confirm string
|
||||
fmt.Scanln(&confirm)
|
||||
if confirm != "y" && confirm != "Y" {
|
||||
fmt.Println("Cancelled.")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
for _, task := range tasks {
|
||||
task.Delete(false) // Soft delete
|
||||
}
|
||||
|
||||
fmt.Printf("Deleted %d task(s).\n", len(tasks))
|
||||
if len(tasks) == 1 {
|
||||
fmt.Printf("Deleted task %s\n", engine.FormatTaskSummary(tasks[0], ws))
|
||||
} else {
|
||||
fmt.Printf("Deleted %d task(s).\n", len(tasks))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -66,9 +66,9 @@ func completeTasks(args []string) error {
|
||||
return fmt.Errorf("no tasks matched filter")
|
||||
}
|
||||
|
||||
// Confirm if multiple tasks
|
||||
if len(tasks) > 1 {
|
||||
fmt.Printf("About to complete %d tasks. Proceed? (y/N): ", len(tasks))
|
||||
fmt.Print(engine.FormatTaskConfirmList("complete", tasks, ws))
|
||||
fmt.Printf("Proceed? (y/N): ")
|
||||
var confirm string
|
||||
fmt.Scanln(&confirm)
|
||||
if confirm != "y" && confirm != "Y" {
|
||||
@@ -80,14 +80,18 @@ func completeTasks(args []string) error {
|
||||
// Complete tasks
|
||||
completed := 0
|
||||
for _, task := range tasks {
|
||||
if err := task.Complete(); err != nil {
|
||||
if _, err := task.Complete(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to complete task %s: %v\n", task.UUID, err)
|
||||
} else {
|
||||
completed++
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Completed %d task(s).\n", completed)
|
||||
if len(tasks) == 1 {
|
||||
fmt.Printf("Completed task %s\n", engine.FormatTaskSummary(tasks[0], ws))
|
||||
} else {
|
||||
fmt.Printf("Completed %d task(s).\n", completed)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -240,7 +240,8 @@ func applyEditedFields(task *engine.Task, fields map[string]string) error {
|
||||
return err
|
||||
}
|
||||
// Then complete (which saves automatically)
|
||||
return task.Complete()
|
||||
_, err := task.Complete()
|
||||
return err
|
||||
}
|
||||
|
||||
// If changing to deleted, use Delete() method
|
||||
|
||||
@@ -87,7 +87,8 @@ func modifyTasks(filterArgs, modifierArgs []string) error {
|
||||
|
||||
// Confirm if multiple tasks or no filters specified
|
||||
if len(tasks) > 1 || len(filterArgs) == 0 {
|
||||
fmt.Printf("About to modify %d task(s). Proceed? (y/N): ", len(tasks))
|
||||
fmt.Print(engine.FormatTaskConfirmList("modify", tasks, ws))
|
||||
fmt.Printf("Proceed? (y/N): ")
|
||||
var confirm string
|
||||
fmt.Scanln(&confirm)
|
||||
if confirm != "y" && confirm != "Y" {
|
||||
|
||||
Reference in New Issue
Block a user