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 /// Mark a task as done (shorthand for update REFPATH --status done)
101 Done {
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 /// Full-text search across all .mps files
110 Search {
111 /// Search query
112 query: String,
113 /// Filter by element type
114 #[arg(short = 't', long)]
115 r#type: Option<String>,
116 /// Filter by tag
117 #[arg(short = 'g', long)]
118 tag: Option<String>,
119 /// Search from this date onward
120 #[arg(short = 'S', long)]
121 since: Option<String>,
122 /// Filter character entries by person name
123 #[arg(short = 'n', long)]
124 name: Option<String>,
125 },
126
127 /// Show element counts and log durations
128 Stats {
129 /// Date (default: today)
130 datesign: Option<String>,
131 /// Stats from SINCE up to DATESIGN
132 #[arg(short = 'S', long)]
133 since: Option<String>,
134 /// Stats across all dates in the archive
135 #[arg(short = 'a', long)]
136 all: bool,
137 },
138
139 /// Show tag usage frequency bar chart
140 Tags {
141 /// Date (default: today)
142 datesign: Option<String>,
143 /// Filter by element type
144 #[arg(short = 't', long)]
145 r#type: Option<String>,
146 /// Filter tasks by status
147 #[arg(short = 's', long)]
148 status: Option<String>,
149 /// Tags from SINCE up to DATESIGN
150 #[arg(short = 'S', long)]
151 since: Option<String>,
152 /// Count tags across all dates
153 #[arg(short = 'a', long)]
154 all: bool,
155 /// Filter character entries by person name
156 #[arg(short = 'n', long)]
157 name: Option<String>,
158 },
159
160 /// Export elements to JSON or CSV on stdout
161 Export {
162 /// Date (default: today)
163 datesign: Option<String>,
164 /// Output format: json (default), csv
165 #[arg(short = 'f', long, default_value = "json")]
166 format: String,
167 /// Filter by element type
168 #[arg(short = 't', long)]
169 r#type: Option<String>,
170 /// Export from SINCE up to DATESIGN
171 #[arg(short = 'S', long)]
172 since: Option<String>,
173 },
174
175 /// View or edit MPS configuration
176 Config {
177 /// Subcommand: show (default) or edit
178 subcommand: Option<String>,
179 },
180
181 /// Run git commands inside the storage directory
182 Git {
183 /// Git subcommand and args (auto = full cycle, autocommit = stage+commit)
184 #[arg(trailing_var_arg = true)]
185 args: Vec<String>,
186 },
187
188 /// Stage, commit, pull, and push (equivalent to git auto)
189 Autogit,
190
191 /// Run any shell command inside the storage directory
192 Cmd {
193 /// Command and arguments
194 #[arg(trailing_var_arg = true)]
195 args: Vec<String>,
196 },
197
198 /// Print version
199 Version,
200}