j_cli/interactive/
parser.rs1use crate::cli::SubCmd;
2use crate::command;
3use crate::config::YamlConfig;
4use crate::constants::cmd;
5
6pub enum ParseResult {
8 Matched(SubCmd),
10 Handled,
12 NotFound,
14}
15
16pub fn execute_interactive_command(args: &[String], config: &mut YamlConfig) {
18 if args.is_empty() {
19 return;
20 }
21
22 let cmd_str = &args[0];
23
24 if cmd::EXIT.contains(&cmd_str.as_str()) {
25 command::system::handle_exit();
26 return;
27 }
28
29 match parse_interactive_command(args) {
30 ParseResult::Matched(subcmd) => {
31 command::dispatch(subcmd, config);
32 }
33 ParseResult::Handled => {}
34 ParseResult::NotFound => {
35 command::open::handle_open(args, config);
36 }
37 }
38}
39
40pub fn parse_interactive_command(args: &[String]) -> ParseResult {
42 if args.is_empty() {
43 return ParseResult::NotFound;
44 }
45
46 let cmd = args[0].as_str();
47 let rest = &args[1..];
48
49 let is = |names: &[&str]| names.contains(&cmd);
50
51 if is(cmd::SET) {
52 if rest.is_empty() {
53 crate::usage!("set <alias> <path>");
54 return ParseResult::Handled;
55 }
56 ParseResult::Matched(SubCmd::Set {
57 alias: rest[0].clone(),
58 path: rest[1..].to_vec(),
59 })
60 } else if is(cmd::REMOVE) {
61 match rest.first() {
62 Some(alias) => ParseResult::Matched(SubCmd::Remove {
63 alias: alias.clone(),
64 }),
65 None => {
66 crate::usage!("rm <alias>");
67 ParseResult::Handled
68 }
69 }
70 } else if is(cmd::RENAME) {
71 if rest.len() < 2 {
72 crate::usage!("rename <alias> <new_alias>");
73 return ParseResult::Handled;
74 }
75 ParseResult::Matched(SubCmd::Rename {
76 alias: rest[0].clone(),
77 new_alias: rest[1].clone(),
78 })
79 } else if is(cmd::MODIFY) {
80 if rest.is_empty() {
81 crate::usage!("mf <alias> <new_path>");
82 return ParseResult::Handled;
83 }
84 ParseResult::Matched(SubCmd::Modify {
85 alias: rest[0].clone(),
86 path: rest[1..].to_vec(),
87 })
88 } else if is(cmd::NOTE) {
89 if rest.len() < 2 {
90 crate::usage!("note <alias> <category>");
91 return ParseResult::Handled;
92 }
93 ParseResult::Matched(SubCmd::Note {
94 alias: rest[0].clone(),
95 category: rest[1].clone(),
96 })
97 } else if is(cmd::DENOTE) {
98 if rest.len() < 2 {
99 crate::usage!("denote <alias> <category>");
100 return ParseResult::Handled;
101 }
102 ParseResult::Matched(SubCmd::Denote {
103 alias: rest[0].clone(),
104 category: rest[1].clone(),
105 })
106 } else if is(cmd::LIST) {
107 ParseResult::Matched(SubCmd::List {
108 part: rest.first().cloned(),
109 })
110 } else if is(cmd::CONTAIN) {
111 if rest.is_empty() {
112 crate::usage!("contain <alias> [sections]");
113 return ParseResult::Handled;
114 }
115 ParseResult::Matched(SubCmd::Contain {
116 alias: rest[0].clone(),
117 containers: rest.get(1).cloned(),
118 })
119 } else if is(cmd::LOG) {
120 if rest.len() < 2 {
121 crate::usage!("log mode <verbose|concise>");
122 return ParseResult::Handled;
123 }
124 ParseResult::Matched(SubCmd::Log {
125 key: rest[0].clone(),
126 value: rest[1].clone(),
127 })
128 } else if is(cmd::CHANGE) {
129 if rest.len() < 3 {
130 crate::usage!("change <part> <field> <value>");
131 return ParseResult::Handled;
132 }
133 ParseResult::Matched(SubCmd::Change {
134 part: rest[0].clone(),
135 field: rest[1].clone(),
136 value: rest[2].clone(),
137 })
138 } else if is(cmd::CLEAR) {
139 ParseResult::Matched(SubCmd::Clear)
140 } else if is(cmd::REPORT) {
141 ParseResult::Matched(SubCmd::Report {
142 content: rest.to_vec(),
143 })
144 } else if is(cmd::REPORTCTL) {
145 if rest.is_empty() {
146 crate::usage!("reportctl <new|sync|push|pull|set-url> [date|message|url]");
147 return ParseResult::Handled;
148 }
149 ParseResult::Matched(SubCmd::Reportctl {
150 action: rest[0].clone(),
151 arg: rest.get(1).cloned(),
152 })
153 } else if is(cmd::CHECK) {
154 ParseResult::Matched(SubCmd::Check {
155 line_count: rest.first().cloned(),
156 })
157 } else if is(cmd::SEARCH) {
158 if rest.len() < 2 {
159 crate::usage!("search <line_count|all> <target> [-f|-fuzzy]");
160 return ParseResult::Handled;
161 }
162 ParseResult::Matched(SubCmd::Search {
163 line_count: rest[0].clone(),
164 target: rest[1].clone(),
165 fuzzy: rest.get(2).cloned(),
166 })
167 } else if is(cmd::TODO) {
168 ParseResult::Matched(SubCmd::Todo {
169 content: rest.to_vec(),
170 })
171 } else if is(cmd::CHAT) {
172 ParseResult::Matched(SubCmd::Chat {
173 content: rest.to_vec(),
174 })
175 } else if is(cmd::CONCAT) {
176 if rest.is_empty() {
177 crate::usage!("concat <script_name> [\"<script_content>\"]");
178 return ParseResult::Handled;
179 }
180 ParseResult::Matched(SubCmd::Concat {
181 name: rest[0].clone(),
182 content: if rest.len() > 1 {
183 rest[1..].to_vec()
184 } else {
185 vec![]
186 },
187 })
188 } else if is(cmd::TIME) {
189 if rest.len() < 2 {
190 crate::usage!("time countdown <duration>");
191 return ParseResult::Handled;
192 }
193 ParseResult::Matched(SubCmd::Time {
194 function: rest[0].clone(),
195 arg: rest[1].clone(),
196 })
197 } else if is(cmd::VERSION) {
198 ParseResult::Matched(SubCmd::Version)
199 } else if is(cmd::HELP) {
200 ParseResult::Matched(SubCmd::Help)
201 } else if is(cmd::COMPLETION) {
202 ParseResult::Matched(SubCmd::Completion {
203 shell: rest.first().cloned(),
204 })
205 } else if is(cmd::VOICE) {
206 ParseResult::Matched(SubCmd::Voice {
207 action: rest.first().cloned().unwrap_or_default(),
208 copy: rest.contains(&"-c".to_string()),
209 model: rest
210 .iter()
211 .position(|a| a == "-m" || a == "--model")
212 .and_then(|i| rest.get(i + 1).cloned()),
213 })
214 } else {
215 ParseResult::NotFound
216 }
217}