a68d701d14
Issue 1: Fix recurrence calculation for overdue tasks - Use completion date (End) as base for next instance, not original due date - If task due Monday completed Wednesday, next is Wednesday+7d not Monday+7d - Fallback to Due date if End is not set - Update test to verify new behavior Issue 2: Fix description parsing to work without quotes - Add parseAddArgs() to extract description from non-modifier words - Description = all words that don't start with +, -, or contain : - Enables: opal add buy groceries +shop carrots → 'buy groceries carrots' - Validate description is required (error if only modifiers) - Validate recurring tasks require due date Issue 3: Implement flexible command syntax - Add preprocessArgs() to parse arguments before Cobra routing - Detect command position and split filters (left) from modifiers (right) - Rewrite os.Args so Cobra routes correctly - Enable both 'opal 2 done' and 'opal done 2' syntax - Commands without modifiers accept filters on either side - Commands with modifiers enforce [filters] command [modifiers] - Add confirmation for modify without filters (modifies all tasks) All commands updated to use preprocessed ParsedArgs from context. All tests passing (33 tests).
59 lines
1.3 KiB
Go
59 lines
1.3 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"git.jnss.me/joakim/opal/internal/engine"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var listCmd = &cobra.Command{
|
|
Use: "list [filter...]",
|
|
Short: "List tasks",
|
|
Long: `List tasks matching the filter criteria.
|
|
|
|
Examples:
|
|
opal list # List all pending tasks
|
|
opal list +home # List tasks with +home tag
|
|
opal list project:backend # List backend project tasks
|
|
opal list priority:H # List high priority tasks
|
|
opal 2 list # List using filter 2 (flexible syntax)`,
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
parsed := getParsedArgs(cmd)
|
|
if err := listTasks(parsed.Filters); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
},
|
|
}
|
|
|
|
func listTasks(args []string) error {
|
|
// Parse filter
|
|
var filter *engine.Filter
|
|
var err error
|
|
|
|
if len(args) == 0 {
|
|
filter = engine.DefaultFilter()
|
|
} else {
|
|
filter, err = engine.ParseFilter(args)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parse filter: %w", err)
|
|
}
|
|
}
|
|
|
|
// Build working set
|
|
ws, err := engine.BuildWorkingSet(filter)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to build working set: %w", err)
|
|
}
|
|
|
|
// Get tasks
|
|
tasks := ws.GetTasks()
|
|
|
|
// Display
|
|
fmt.Println(engine.FormatTaskList(tasks, ws))
|
|
|
|
return nil
|
|
}
|