package cmd import ( "fmt" "os" "git.jnss.me/joakim/opal/internal/engine" "github.com/spf13/cobra" ) var uncompleteCmd = &cobra.Command{ Use: "uncomplete [filter...]", Short: "Restore a completed task to pending", Long: `Restore a completed task back to pending status. Unlike undo, this is a targeted action that works on any completed task regardless of when it was completed. Examples: opal 2 uncomplete opal uncomplete +errand`, Run: func(cmd *cobra.Command, args []string) { parsed := getParsedArgs(cmd) if err := uncompleteTasks(parsed.Filters); err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } }, } func uncompleteTasks(args []string) error { if len(args) == 0 { return fmt.Errorf("no task specified") } filter, err := engine.ParseFilter(args) if err != nil { return fmt.Errorf("failed to parse filter: %w", err) } ws, err := engine.LoadWorkingSet() if err != nil { return fmt.Errorf("failed to load working set: %w", err) } var tasks []*engine.Task if len(filter.IDs) > 0 { for _, id := range filter.IDs { task, err := ws.GetTaskByDisplayID(id) if err != nil { return err } tasks = append(tasks, task) } } else { tasks, err = engine.GetTasks(filter) if err != nil { return fmt.Errorf("failed to get tasks: %w", err) } } if len(tasks) == 0 { return fmt.Errorf("no tasks matched filter") } uncompleted := 0 for _, task := range tasks { if task.Status != engine.StatusCompleted { fmt.Fprintf(os.Stderr, "Warning: task %s is not completed, skipping\n", task.UUID) continue } task.Status = engine.StatusPending task.End = nil if err := task.Save(); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to uncomplete task %s: %v\n", task.UUID, err) } else { uncompleted++ } } if uncompleted == 1 { fmt.Printf("Restored task %s to pending\n", engine.FormatTaskSummary(tasks[0], ws)) } else { fmt.Printf("Restored %d task(s) to pending.\n", uncompleted) } return nil }