mps/cli.rs
1use clap::{Parser, Subcommand};
2
3#[derive(Parser)]
4#[command(name = "mps", version, about = "Plain-text personal productivity CLI")]
5pub struct Cli {
6 /// Path to config file (default: ~/.mps_config.yaml)
7 #[arg(long, global = true)]
8 pub config_path: Option<String>,
9
10 /// Recreate config even if it exists
11 #[arg(long, global = true, default_value_t = false)]
12 pub force: bool,
13
14 #[command(subcommand)]
15 pub command: Option<Commands>,
16}
17
18#[derive(Subcommand)]
19pub enum Commands {
20 /// Open a date's .mps file in $EDITOR (default: today)
21 Open {
22 /// Date to open (today, yesterday, YYYYMMDD, last friday, …)
23 datesign: Option<String>,
24 },
25
26 /// List elements for a date as an indented tree
27 List {
28 /// Date (default: today)
29 datesign: Option<String>,
30 /// Filter by element type: task, note, log, reminder
31 #[arg(short = 't', long)]
32 r#type: Option<String>,
33 /// Filter by tag name
34 #[arg(short = 'g', long)]
35 tag: Option<String>,
36 /// Filter tasks by status: open, done
37 #[arg(short = 's', long)]
38 status: Option<String>,
39 /// Show elements from SINCE up to DATESIGN
40 #[arg(short = 'S', long)]
41 since: Option<String>,
42 /// Show human-readable ref column (task-1, mps-1.2, …)
43 #[arg(short = 'r', long)]
44 refs: bool,
45 /// List elements across all dates in the archive
46 #[arg(short = 'a', long)]
47 all: bool,
48 /// Filter character entries by person name
49 #[arg(short = 'n', long)]
50 name: Option<String>,
51 },
52
53 /// Append an element to today's file without opening an editor
54 Append {
55 /// Element type: task, note, log, reminder (aliases from config are resolved)
56 kind: String,
57 /// Element body text
58 body: Vec<String>,
59 /// Comma-separated tags (e.g. work,backend)
60 #[arg(long)]
61 tags: Option<String>,
62 /// Task status: open (default) or done
63 #[arg(long)]
64 status: Option<String>,
65 /// Time for reminders (e.g. 5pm, 10:30)
66 #[arg(long)]
67 at: Option<String>,
68 /// Start time for logs (HH:MM)
69 #[arg(long)]
70 start_time: Option<String>,
71 /// End time for logs (HH:MM)
72 #[arg(long)]
73 end_time: Option<String>,
74 /// Person name for character entries
75 #[arg(short = 'n', long)]
76 name: Option<String>,
77 },
78
79 /// Update an element's attributes in-place
80 Update {
81 /// Element ref: human (task-1) or epoch (20260428.1)
82 ref_path: String,
83 /// Set task status: open or done
84 #[arg(long)]
85 status: Option<String>,
86 /// Set log start time (HH:MM)
87 #[arg(long = "start-time")]
88 start_time: Option<String>,
89 /// Set log end time (HH:MM)
90 #[arg(long = "end-time")]
91 end_time: Option<String>,
92 /// Set reminder time
93 #[arg(long)]
94 at: Option<String>,
95 /// Date context for human refs (default: today)
96 #[arg(short = 'd', long)]
97 date: Option<String>,
98 },
99
100 /// Edit an element's body text in $EDITOR
101 Edit {
102 /// Element ref: human (task-1) or epoch (20260428.1)
103 ref_path: String,
104 /// Date context for human refs (default: today)
105 #[arg(short = 'd', long)]
106 date: Option<String>,
107 },
108
109 /// Delete an element from its file
110 Delete {
111 /// Element ref: human (task-1) or epoch (20260428.1)
112 ref_path: String,
113 /// Date context for human refs (default: today)
114 #[arg(short = 'd', long)]
115 date: Option<String>,
116 /// Skip confirmation prompt
117 #[arg(short = 'y', long)]
118 yes: bool,
119 },
120
121 /// Mark a task as done (shorthand for update REFPATH --status done)
122 Done {
123 /// Element ref: human (task-1) or epoch (20260428.1)
124 ref_path: String,
125 /// Date context for human refs (default: today)
126 #[arg(short = 'd', long)]
127 date: Option<String>,
128 },
129
130 /// Full-text search across all .mps files
131 Search {
132 /// Search query
133 query: String,
134 /// Filter by element type
135 #[arg(short = 't', long)]
136 r#type: Option<String>,
137 /// Filter by tag
138 #[arg(short = 'g', long)]
139 tag: Option<String>,
140 /// Search from this date onward
141 #[arg(short = 'S', long)]
142 since: Option<String>,
143 /// Filter character entries by person name
144 #[arg(short = 'n', long)]
145 name: Option<String>,
146 },
147
148 /// Show element counts and log durations
149 Stats {
150 /// Date (default: today)
151 datesign: Option<String>,
152 /// Stats from SINCE up to DATESIGN
153 #[arg(short = 'S', long)]
154 since: Option<String>,
155 /// Stats across all dates in the archive
156 #[arg(short = 'a', long)]
157 all: bool,
158 },
159
160 /// Show tag usage frequency bar chart
161 Tags {
162 /// Date (default: today)
163 datesign: Option<String>,
164 /// Filter by element type
165 #[arg(short = 't', long)]
166 r#type: Option<String>,
167 /// Filter tasks by status
168 #[arg(short = 's', long)]
169 status: Option<String>,
170 /// Tags from SINCE up to DATESIGN
171 #[arg(short = 'S', long)]
172 since: Option<String>,
173 /// Count tags across all dates
174 #[arg(short = 'a', long)]
175 all: bool,
176 /// Filter character entries by person name
177 #[arg(short = 'n', long)]
178 name: Option<String>,
179 },
180
181 /// Export elements to JSON or CSV on stdout
182 Export {
183 /// Date (default: today)
184 datesign: Option<String>,
185 /// Output format: json (default), csv
186 #[arg(short = 'f', long, default_value = "json")]
187 format: String,
188 /// Filter by element type
189 #[arg(short = 't', long)]
190 r#type: Option<String>,
191 /// Export from SINCE up to DATESIGN
192 #[arg(short = 'S', long)]
193 since: Option<String>,
194 },
195
196 /// View or edit MPS configuration
197 Config {
198 /// Subcommand: show (default) or edit
199 subcommand: Option<String>,
200 },
201
202 /// Run git commands inside the storage directory
203 Git {
204 /// Git subcommand and args (auto = full cycle, autocommit = stage+commit)
205 #[arg(trailing_var_arg = true)]
206 args: Vec<String>,
207 },
208
209 /// Stage, commit, pull, and push (equivalent to git auto)
210 Autogit,
211
212 /// Run any shell command inside the storage directory
213 Cmd {
214 /// Command and arguments
215 #[arg(trailing_var_arg = true)]
216 args: Vec<String>,
217 },
218
219 /// Check for due reminders and open tasks; send desktop notifications
220 Notify {
221 /// Show what would be sent without actually sending
222 #[arg(long)]
223 dry_run: bool,
224 /// Override the time window in minutes (default: from config)
225 #[arg(long)]
226 window: Option<u64>,
227 /// Fire even if already notified within the window
228 #[arg(long)]
229 force: bool,
230 },
231
232 /// Manage the background notification daemon (systemd user timer)
233 Daemon {
234 /// Subcommand: install, remove, status, run
235 subcommand: String,
236 },
237
238 /// Inspect or edit the .mps.meta sidecar config file
239 Meta {
240 /// Subcommand: show (default), clear, edit
241 subcommand: Option<String>,
242 },
243
244 /// Print version
245 Version,
246}