package cmd import ( "fmt" "os" "strings" "git.jnss.me/joakim/opal/internal/engine" "github.com/spf13/cobra" ) var addCmd = &cobra.Command{ Use: "add [modifiers...]", Short: "Add a new task", Long: `Add a new task with optional modifiers. Examples: opal add "Buy groceries" opal add "Review PR" priority:H project:backend opal add "Team meeting" due:mon recur:1w +meetings`, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { if err := addTask(args); err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } }, } func addTask(args []string) error { // First arg is description, rest are modifiers description := args[0] modifierArgs := args[1:] // Parse modifiers var mod *engine.Modifier var err error if len(modifierArgs) > 0 { mod, err = engine.ParseModifier(modifierArgs) if err != nil { return fmt.Errorf("failed to parse modifiers: %w", err) } } // Check if this is a recurring task isRecurring := mod != nil && mod.SetAttributes["recur"] != nil if isRecurring { // Create recurring task (template + first instance) return addRecurringTask(description, mod) } // Create regular task task, err := engine.CreateTaskWithModifier(description, mod) if err != nil { 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, ", ")) } return nil } func addRecurringTask(description string, mod *engine.Modifier) error { // Extract recurrence pattern recurPattern := mod.SetAttributes["recur"] if recurPattern == nil { return fmt.Errorf("no recurrence pattern specified") } duration, err := engine.ParseRecurrencePattern(*recurPattern) if err != nil { return fmt.Errorf("invalid recurrence pattern: %w", err) } // Create template task template, err := engine.CreateTask(description) if err != nil { return fmt.Errorf("failed to create template: %w", err) } template.Status = engine.StatusRecurring template.RecurrenceDuration = &duration // Apply other modifiers to template (except recur) if mod != nil { tempMod := &engine.Modifier{ SetAttributes: make(map[string]*string), AddTags: mod.AddTags, RemoveTags: mod.RemoveTags, } // Copy all attributes except recur for key, val := range mod.SetAttributes { if key != "recur" { tempMod.SetAttributes[key] = val } } if err := tempMod.Apply(template); err != nil { return fmt.Errorf("failed to apply modifiers to template: %w", err) } } // Create first instance instance, err := engine.CreateTask(description) if err != nil { return fmt.Errorf("failed to create first instance: %w", err) } instance.ParentUUID = &template.UUID instance.Due = template.Due instance.Project = template.Project instance.Priority = template.Priority if err := instance.Save(); err != nil { return fmt.Errorf("failed to save first instance: %w", err) } // Copy tags to instance for _, tag := range template.Tags { instance.AddTag(tag) } fmt.Printf("Created recurring task %s\n", template.UUID) fmt.Printf("First instance: %s\n", instance.UUID) fmt.Printf("Recurrence: %s\n", engine.FormatRecurrenceDuration(duration)) return nil }