summaryrefslogtreecommitdiff
path: root/Omni
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2025-11-20 13:59:39 -0500
committerBen Sima <ben@bsima.me>2025-11-20 13:59:39 -0500
commit9b3151d3eee1dd534f990e5fb0e3151d383fd393 (patch)
tree5d3a76bb795a0387f3f7cc6d0937333693dc856c /Omni
parent0a0ea5a3fec6eae0a4b300918a9a8fc06fcc786f (diff)
task: prettier tree visualization and flag ordering fixes
- Implement box-drawing characters (├──, └──, │) for task tree visualization - Fix 'task create' flag ordering by using [options] in docopt (same as 'task list') - Document TASK_TEST_MODE environment variable in AGENTS.md Testing section - Add test case for multi-flag ordering on 'task create' - Clean up test tasks polluted in production database All 29 tests passing. Amp-Thread-ID: https://ampcode.com/threads/T-4e6225cf-3e78-4538-963c-5377bbbccee8 Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'Omni')
-rw-r--r--Omni/Task.hs13
-rw-r--r--Omni/Task/Core.hs28
2 files changed, 34 insertions, 7 deletions
diff --git a/Omni/Task.hs b/Omni/Task.hs
index eeca4c6..6d2da71 100644
--- a/Omni/Task.hs
+++ b/Omni/Task.hs
@@ -38,7 +38,7 @@ task
Usage:
task init [--quiet]
- task create <title> [--type=<type>] [--parent=<id>] [--priority=<p>] [--deps=<ids>] [--dep-type=<type>] [--discovered-from=<id>] [--namespace=<ns>] [--json]
+ task create <title> [options]
task list [options]
task ready [--json]
task show <id> [--json]
@@ -453,5 +453,14 @@ cliTests =
let result = Docopt.parseArgs help ["sync"]
case result of
Left err -> Test.assertFailure <| "Failed to parse 'sync': " <> show err
- Right args -> args `Cli.has` Cli.command "sync" Test.@?= True
+ Right args -> args `Cli.has` Cli.command "sync" Test.@?= True,
+ Test.unit "create with flags in different order" <| do
+ let result = Docopt.parseArgs help ["create", "Test", "--json", "--priority=1", "--namespace=Omni/Task"]
+ case result of
+ Left err -> Test.assertFailure <| "Failed to parse 'create' with reordered flags: " <> show err
+ Right args -> do
+ args `Cli.has` Cli.command "create" Test.@?= True
+ args `Cli.has` Cli.longOption "json" Test.@?= True
+ Cli.getArg args (Cli.longOption "priority") Test.@?= Just "1"
+ Cli.getArg args (Cli.longOption "namespace") Test.@?= Just "Omni/Task"
]
diff --git a/Omni/Task/Core.hs b/Omni/Task/Core.hs
index 1dc31a8..f463040 100644
--- a/Omni/Task/Core.hs
+++ b/Omni/Task/Core.hs
@@ -10,6 +10,7 @@ import qualified Data.Aeson as Aeson
import qualified Data.Aeson.KeyMap as KM
import Data.Aeson.Types (parseMaybe)
import qualified Data.ByteString.Lazy.Char8 as BLC
+import qualified Data.List as List
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Data.Time (UTCTime, diffTimeToPicoseconds, getCurrentTime, utctDayTime)
@@ -324,9 +325,19 @@ showTaskTree maybeId = do
printEpicTree allTasks task = printTreeNode allTasks task 0
printTreeNode :: [Task] -> Task -> Int -> IO ()
- printTreeNode allTasks task indent = do
- let prefix = T.pack (replicate (indent * 2) ' ')
- children = filter (\t -> taskParent t == Just (taskId task)) allTasks
+ printTreeNode allTasks task indent = printTreeNode' allTasks task indent []
+
+ printTreeNode' :: [Task] -> Task -> Int -> [Bool] -> IO ()
+ printTreeNode' allTasks task indent ancestry = do
+ let children = filter (\t -> taskParent t == Just (taskId task)) allTasks
+ -- Build tree prefix using box-drawing characters
+ prefix =
+ if indent == 0
+ then ""
+ else
+ let ancestorPrefixes = map (\hasMore -> if hasMore then "│ " else " ") (List.init ancestry)
+ myPrefix = if List.last ancestry then "├── " else "└── "
+ in T.pack <| concat ancestorPrefixes ++ myPrefix
-- For epics, show progress count [completed/total]; for tasks, show status checkbox
statusStr = case taskType task of
Epic ->
@@ -349,8 +360,15 @@ showTaskTree maybeId = do
else taskTitle task
putText <| prefix <> taskId task <> " " <> statusStr <> " " <> nsStr <> truncatedTitle
- -- Print children
- traverse_ (\child -> printTreeNode allTasks child (indent + 1)) children
+ -- Print children with updated ancestry
+ let indexedChildren = zip [1 ..] children
+ totalChildren = length children
+ traverse_
+ ( \(idx, child) ->
+ let hasMoreSiblings = idx < totalChildren
+ in printTreeNode' allTasks child (indent + 1) (ancestry ++ [hasMoreSiblings])
+ )
+ indexedChildren
-- Helper to print a task
printTask :: Task -> IO ()