diff options
| author | Ben Sima <ben@bsima.me> | 2025-11-20 11:37:45 -0500 |
|---|---|---|
| committer | Ben Sima <ben@bsima.me> | 2025-11-20 11:37:45 -0500 |
| commit | 054e3f2c1611250664105f5b6b6db97adb41643b (patch) | |
| tree | 81ee9e7fd32d69087bea9388922290becaa6f07f /Omni | |
| parent | d49ad52d35a9c5141265d4fb91421a09033c57f9 (diff) | |
Add task show command for detailed task inspection
- Implemented 'task show <id>' command with human-readable output -
Shows all task fields: title, type, status, priority, timestamps -
Displays dependencies with their types - Supports --json flag for
programmatic use - Added CLI tests for show command - Includes priority
descriptions (Critical/High/Medium/Low/Backlog)
Diffstat (limited to 'Omni')
| -rw-r--r-- | Omni/Task.hs | 25 | ||||
| -rw-r--r-- | Omni/Task/Core.hs | 37 |
2 files changed, 62 insertions, 0 deletions
diff --git a/Omni/Task.hs b/Omni/Task.hs index e3f89dc..656c972 100644 --- a/Omni/Task.hs +++ b/Omni/Task.hs @@ -41,6 +41,7 @@ Usage: task create <title> [--type=<type>] [--parent=<id>] [--priority=<p>] [--deps=<ids>] [--dep-type=<type>] [--discovered-from=<id>] [--namespace=<ns>] [--json] task list [--type=<type>] [--parent=<id>] [--status=<status>] [--namespace=<ns>] [--json] task ready [--json] + task show <id> [--json] task update <id> <status> [--json] task deps <id> [--json] task tree [<id>] [--json] @@ -55,6 +56,7 @@ Commands: create Create a new task or epic list List all tasks ready Show ready tasks (not blocked) + show Show detailed task information update Update task status deps Show dependency tree tree Show task tree (epics with children, or all epics if no ID given) @@ -186,6 +188,15 @@ move args else do putText "Ready tasks:" traverse_ printTask tasks + | args `Cli.has` Cli.command "show" = do + tid <- getArgText args "id" + tasks <- loadTasks + case filter (\t -> taskId t == tid) tasks of + [] -> putText "Task not found" + (task : _) -> + if isJsonMode args + then outputJson task + else showTaskDetailed task | args `Cli.has` Cli.command "update" = do tid <- getArgText args "id" statusStr <- getArgText args "status" @@ -424,6 +435,20 @@ cliTests = args `Cli.has` Cli.command "import" Test.@?= True -- Note: -i is a short option, not an argument Cli.getArg args (Cli.shortOption 'i') Test.@?= Just "tasks.jsonl", + Test.unit "show command" <| do + let result = Docopt.parseArgs help ["show", "t-abc123"] + case result of + Left err -> Test.assertFailure <| "Failed to parse 'show': " <> show err + Right args -> do + args `Cli.has` Cli.command "show" Test.@?= True + Cli.getArg args (Cli.argument "id") Test.@?= Just "t-abc123", + Test.unit "show with --json flag" <| do + let result = Docopt.parseArgs help ["show", "t-abc123", "--json"] + case result of + Left err -> Test.assertFailure <| "Failed to parse 'show --json': " <> show err + Right args -> do + args `Cli.has` Cli.command "show" Test.@?= True + args `Cli.has` Cli.longOption "json" Test.@?= True, Test.unit "sync command" <| do let result = Docopt.parseArgs help ["sync"] case result of diff --git a/Omni/Task/Core.hs b/Omni/Task/Core.hs index 6c472c5..1dc31a8 100644 --- a/Omni/Task/Core.hs +++ b/Omni/Task/Core.hs @@ -373,6 +373,43 @@ printTask t = Nothing -> "" Just ns -> " [" <> ns <> "]" +-- Show detailed task information (human-readable) +showTaskDetailed :: Task -> IO () +showTaskDetailed t = do + putText "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + putText <| "Task: " <> taskId t + putText "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + putText <| "Title: " <> taskTitle t + putText <| "Type: " <> T.pack (show (taskType t)) + putText <| "Status: " <> T.pack (show (taskStatus t)) + putText <| "Priority: " <> T.pack (show (taskPriority t)) <> priorityDesc + case taskParent t of + Nothing -> pure () + Just p -> putText <| "Parent: " <> p + case taskNamespace t of + Nothing -> pure () + Just ns -> putText <| "Namespace: " <> ns + putText <| "Created: " <> T.pack (show (taskCreatedAt t)) + putText <| "Updated: " <> T.pack (show (taskUpdatedAt t)) + + -- Show dependencies + unless (null (taskDependencies t)) <| do + putText "" + putText "Dependencies:" + traverse_ printDependency (taskDependencies t) + + putText "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + where + priorityDesc = case taskPriority t of + P0 -> " (Critical)" + P1 -> " (High)" + P2 -> " (Medium)" + P3 -> " (Low)" + P4 -> " (Backlog)" + + printDependency dep = + putText <| " - " <> depId dep <> " [" <> T.pack (show (depType dep)) <> "]" + -- Export tasks: Consolidate JSONL file (remove duplicates, keep latest version) exportTasks :: IO () exportTasks = do |
