1mod create;
2mod dep;
3mod doctor;
4mod done;
5mod export;
6mod import;
7mod label;
8mod list;
9mod log;
10mod next;
11mod project;
12mod ready;
13mod reopen;
14mod rm;
15mod search;
16mod show;
17mod skill;
18mod stats;
19pub mod sync;
20mod tidy;
21mod update;
22mod webui;
23
24use crate::cli::{Cli, Command};
25use crate::db;
26use anyhow::Result;
27
28fn require_root() -> Result<std::path::PathBuf> {
29 std::env::current_dir().map_err(Into::into)
30}
31
32pub fn dispatch(cli: &Cli) -> Result<()> {
33 if let Some(project) = &cli.project {
34 std::env::set_var(db::PROJECT_ENV, project);
35 }
36
37 match &cli.command {
38 Command::Project { action } => project::run(action, cli.json),
39 Command::Create {
40 title,
41 priority,
42 effort,
43 task_type,
44 desc,
45 parent,
46 labels,
47 } => {
48 let root = require_root()?;
49 create::run(
50 &root,
51 create::Opts {
52 title: title.as_deref(),
53 priority: db::parse_priority(priority)?,
54 effort: db::parse_effort(effort)?,
55 task_type,
56 desc: desc.as_deref(),
57 parent: parent.as_deref(),
58 labels: labels.as_deref(),
59 json: cli.json,
60 },
61 )
62 }
63 Command::List {
64 status,
65 priority,
66 effort,
67 label,
68 } => {
69 let root = require_root()?;
70 let pri = priority.as_deref().map(db::parse_priority).transpose()?;
71 let eff = effort.as_deref().map(db::parse_effort).transpose()?;
72 list::run(
73 &root,
74 status.as_deref(),
75 pri,
76 eff,
77 label.as_deref(),
78 cli.json,
79 )
80 }
81 Command::Show { id } => {
82 let root = require_root()?;
83 show::run(&root, id, cli.json)
84 }
85 Command::Log { id, message } => {
86 let root = require_root()?;
87 log::run(&root, id, message, cli.json)
88 }
89 Command::Update {
90 id,
91 status,
92 priority,
93 effort,
94 title,
95 desc,
96 } => {
97 let root = require_root()?;
98 let pri = priority.as_deref().map(db::parse_priority).transpose()?;
99 let eff = effort.as_deref().map(db::parse_effort).transpose()?;
100 update::run(
101 &root,
102 id,
103 update::Opts {
104 status: status.as_deref(),
105 priority: pri,
106 effort: eff,
107 title: title.as_deref(),
108 desc: desc.as_deref(),
109 json: cli.json,
110 },
111 )
112 }
113 Command::Done { ids } => {
114 let root = require_root()?;
115 done::run(&root, ids, cli.json)
116 }
117 Command::Rm {
118 force,
119 recursive,
120 ids,
121 } => {
122 let root = require_root()?;
123 rm::run(&root, ids, *recursive, *force, cli.json)
124 }
125 Command::Reopen { ids } => {
126 let root = require_root()?;
127 reopen::run(&root, ids, cli.json)
128 }
129 Command::Dep { action } => {
130 let root = require_root()?;
131 dep::run(&root, action, cli.json)
132 }
133 Command::Label { action } => {
134 let root = require_root()?;
135 label::run(&root, action, cli.json)
136 }
137 Command::Search { query } => {
138 let root = require_root()?;
139 search::run(&root, query, cli.json)
140 }
141 Command::Ready => {
142 let root = require_root()?;
143 ready::run(&root, cli.json)
144 }
145 Command::Next {
146 mode,
147 verbose,
148 limit,
149 } => {
150 let root = require_root()?;
151 next::run(&root, mode, *verbose, *limit, cli.json)
152 }
153 Command::Stats => {
154 let root = require_root()?;
155 stats::run(&root)
156 }
157 Command::Doctor { fix } => {
158 let root = require_root()?;
159 doctor::run(&root, *fix, cli.json)
160 }
161 Command::Tidy => {
162 let root = require_root()?;
163 tidy::run(&root)
164 }
165 Command::Export => {
166 let root = require_root()?;
167 export::run(&root)
168 }
169 Command::Import { file } => {
170 let root = require_root()?;
171 import::run(&root, file)
172 }
173 Command::Sync { code } => {
174 let root = require_root()?;
175 sync::run(&root, code.as_deref(), cli.json)
176 }
177 Command::WebUi { host, port } => {
178 let root = require_root()?;
179 webui::run(&root, host, *port, cli.project.as_deref())
180 }
181 Command::Skill { dir } => skill::run(dir.as_deref()),
182 }
183}