1pub mod app;
2pub mod env;
3pub mod exec;
4pub mod interactive;
6pub mod new;
8pub mod rc;
10pub mod save_ref;
11pub mod target;
12pub mod web;
13pub mod _prelude;
15pub mod aux_cmds;
16pub mod credentials;
17pub mod develop_origen;
18pub mod eval;
19pub mod generate;
20pub mod plugin;
21pub mod plugins;
22
23use crate::python;
24use crate::strs_to_cli_arr;
25
26use _prelude::{CountArgs, SetArgTrue};
27use indexmap::map::IndexMap;
28use origen::{LOGGER, STATUS}; use std::process::exit;
30
31use crate::framework::extensions::{Extension, ExtensionSource};
32use crate::Plugins;
33use clap::{ArgMatches, Command as App};
34use std::collections::HashMap;
35
36#[macro_export]
37macro_rules! unreachable_invalid_subc {
38 ($subcmd:expr) => {{
39 unreachable!(
40 "Uncaught Invalid Subcommand {} From {}",
41 $subcmd,
42 module_path!()
43 )
44 }};
45}
46
47#[macro_export]
48macro_rules! print_subcmds_available_msg {
49 () => {{
50 println!("Run with 'help' or '-h' to see available subcommands");
51 }};
52}
53
54#[macro_export]
55macro_rules! gen_simple_run_func {
56 ($base_cmd: expr) => {
57 pub(crate) fn run(
58 mut invocation: &clap::ArgMatches,
59 mut cmd_def: &clap::Command,
60 exts: &crate::Extensions,
61 plugins: Option<&crate::Plugins>,
62 ) -> origen::Result<()> {
63 let mut path_pieces: Vec<String> = vec![];
64 cmd_def = cmd_def.find_subcommand($base_cmd).unwrap();
65 if invocation.subcommand_name().is_some() {
66 while invocation.subcommand_name().is_some() {
67 let n = invocation.subcommand_name().unwrap();
68 invocation = invocation.subcommand_matches(&n).unwrap();
69 cmd_def = cmd_def.find_subcommand(n).unwrap();
70 path_pieces.push(n.to_string());
71 }
72 crate::commands::launch(
73 Some($base_cmd),
74 Some(&path_pieces),
75 invocation,
76 cmd_def,
77 exts.get_core_ext(&format!("{}.{}", $base_cmd, path_pieces.join("."))),
78 plugins,
79 None,
80 );
81 } else {
82 crate::commands::launch_from_invocation(
83 invocation,
84 cmd_def,
85 exts.get_core_ext($base_cmd),
86 plugins,
87 );
88 }
89 Ok(())
90 }
91 };
92 () => {
93 crate::gen_simple_run_func!(BASE_CMD);
94 };
95}
96
97pub fn launch_as(
98 cmd: &str,
99 subcmds: Option<&Vec<String>>,
100 invocation: &ArgMatches,
101 cmd_def: &App,
102 cmd_exts: Option<&Vec<Extension>>,
103 plugins: Option<&Plugins>,
104 overrides: Option<IndexMap<String, Option<String>>>,
105) -> () {
106 launch(
107 Some(cmd),
108 subcmds,
109 invocation,
110 cmd_def,
111 cmd_exts,
112 plugins,
113 overrides,
114 )
115}
116pub fn launch_from_invocation(
117 invocation: &ArgMatches,
118 cmd_def: &App,
119 cmd_exts: Option<&Vec<Extension>>,
120 plugins: Option<&Plugins>,
121) {
122 launch(None, None, invocation, cmd_def, cmd_exts, plugins, None)
123}
124
125pub fn launch(
126 base_cmd: Option<&str>,
127 subcmds: Option<&Vec<String>>,
128 invocation: &ArgMatches,
129 cmd_def: &App,
130 cmd_exts: Option<&Vec<Extension>>,
131 plugins: Option<&Plugins>,
132 overrides: Option<IndexMap<String, Option<String>>>,
133) {
134 macro_rules! as_name {
135 ($arg_name:expr) => {{
136 if $arg_name.starts_with(crate::framework::extensions::EXT_BASE_NAME) {
137 $arg_name.splitn(4, ".").last().unwrap()
138 } else {
139 $arg_name
140 }
141 }};
142 }
143
144 let mut args: Vec<String> = vec![];
145 let mut arg_indices: Vec<String> = vec![];
146
147 let mut opt_names = HashMap::new();
148 let mut ext_args: HashMap<&ExtensionSource, Vec<String>> = HashMap::new();
149 let mut ext_arg_indices: HashMap<&ExtensionSource, Vec<String>> = HashMap::new();
150 if let Some(exts) = cmd_exts {
151 for ext in exts {
152 if let Some(opts) = ext.opts.as_ref() {
153 for opt in opts {
154 opt_names.insert(opt.full_name.as_ref().unwrap().as_str(), &ext.source);
155 if !ext_args.contains_key(&ext.source) {
156 ext_args.insert(&ext.source, vec![]);
157 ext_arg_indices.insert(&ext.source, vec![]);
158 }
159 }
160 }
161 }
162 }
163
164 let mut targets = None;
165
166 for arg in cmd_def.get_arguments() {
167 let arg_n = arg.get_id().as_str();
168 if arg_n == "verbose" || arg_n == "verbosity_keywords" {
169 continue;
170 }
171
172 if invocation.contains_id(arg_n) {
173 if arg_n == "targets" {
174 targets = Some(invocation.get_many::<String>(arg_n).unwrap());
175 continue;
176 } else if arg_n == "no_targets" {
177 if *invocation.get_one::<bool>(arg_n).unwrap() {
178 targets = Some(clap::parser::ValuesRef::default());
179 }
180 continue;
181 } else if arg_n == "mode" {
182 todo!("Mode argument is not currently supported!");
184 }
185
186 let arg_str: String;
187 if arg.get_action().takes_values() {
188 let multiple_values = matches!(arg.get_action(), clap::ArgAction::Append)
189 || arg
190 .get_num_args()
191 .map(|range| range.max_values() > 1)
192 .unwrap_or(false);
193 if multiple_values {
194 let r = invocation
196 .get_many::<String>(arg_n)
197 .unwrap()
198 .map(|x| format!("\"{}\"", x).replace("\\", "/"))
199 .collect::<Vec<String>>();
200 arg_str = format!("r'{}': [{}]", as_name!(arg_n), r.join(", "));
201 } else {
202 arg_str = format!(
204 "r'{}': r'{}'",
205 as_name!(arg_n),
206 invocation.get_one::<String>(arg_n).unwrap()
207 );
208 }
209 } else {
210 match arg.get_action() {
211 SetArgTrue => {
212 if *(invocation.get_one::<bool>(arg_n).unwrap()) {
213 arg_str = format!("r'{}': True", as_name!(arg_n));
214 } else {
215 continue;
216 }
217 }
218 CountArgs => {
219 let count = *(invocation.get_one::<u8>(arg_n).unwrap());
220 if count > 0 {
221 arg_str = format!("r'{}': {}", as_name!(arg_n), count);
222 } else {
223 continue;
224 }
225 }
226 _ => {
227 log_error!(
228 "Unsupported action '{:#?}' for arg '{}'",
229 arg.get_action(),
230 as_name!(arg_n)
231 ); exit(1);
233 }
234 }
235 }
236 let indices_str = format!(
237 "r'{}': [{}]",
238 as_name!(arg_n),
239 invocation
240 .indices_of(arg_n)
241 .unwrap()
242 .map(|i| i.to_string())
243 .collect::<Vec<String>>()
244 .join(", ")
245 );
246 if let Some(ext_src) = opt_names.get(arg_n) {
247 ext_args.get_mut(ext_src).unwrap().push(arg_str);
248 ext_arg_indices.get_mut(ext_src).unwrap().push(indices_str);
249 } else {
250 args.push(arg_str);
251 arg_indices.push(indices_str);
252 }
253 }
254 }
255
256 let mut cmd = format!(
257 "from origen.boot import run_cmd; run_cmd('{}'",
258 base_cmd.unwrap_or_else(|| cmd_def.get_name())
259 );
260 if let Some(subs) = subcmds.as_ref() {
261 cmd += &format!(
262 ", subcmds=[{}]",
263 subs.iter()
264 .map(|s| format!("r'{}'", s))
265 .collect::<Vec<String>>()
266 .join(", ")
267 );
268 }
269 cmd += &format!(
270 ", args={{{}}}, arg_indices={{{}}}",
271 args.join(", "),
272 arg_indices.join(", ")
273 );
274
275 let mut app_ext_str = "".to_string();
276 let mut pl_ext_str = "".to_string();
277 let mut aux_ext_str = "".to_string();
278 let mut app_ext_indices_str = "".to_string();
279 let mut pl_ext_indices_str = "".to_string();
280 let mut aux_ext_indices_str = "".to_string();
281 if !ext_args.is_empty() {
282 for ext in ext_args {
283 match ext.0 {
284 ExtensionSource::App => {
285 app_ext_str = ext.1.join(", ");
286 app_ext_indices_str = ext_arg_indices[ext.0].join(", ");
287 }
288 ExtensionSource::Plugin(ref pl_name) => {
289 pl_ext_str += &format!(", '{}': {{{}}}", pl_name, ext.1.join(", "));
290 pl_ext_indices_str +=
291 &format!(", '{}': {{{}}}", pl_name, ext_arg_indices[ext.0].join(", "));
292 }
293 ExtensionSource::Aux(ref ns, _) => {
294 aux_ext_str += &format!(", '{}': {{{}}}", ns, ext.1.join(", "));
295 aux_ext_indices_str +=
296 &format!(", '{}': {{{}}}", ns, ext_arg_indices[ext.0].join(", "));
297 }
298 }
299 }
300 if !pl_ext_str.is_empty() {
301 pl_ext_str = pl_ext_str[2..].to_string();
302 pl_ext_indices_str = pl_ext_indices_str[2..].to_string();
303 }
304 if !aux_ext_str.is_empty() {
305 aux_ext_str = aux_ext_str[2..].to_string();
306 aux_ext_indices_str = aux_ext_indices_str[2..].to_string();
307 }
308 }
309 cmd += &format!(
310 concat!(
311 ", ext_args={{'app': {{{}}}, 'plugin': {{{}}}, 'aux': {{{}}}}}",
312 ", ext_arg_indices={{'app': {{{}}}, 'plugin': {{{}}}, 'aux': {{{}}}}}"
313 ),
314 app_ext_str,
315 pl_ext_str,
316 aux_ext_str,
317 app_ext_indices_str,
318 pl_ext_indices_str,
319 aux_ext_indices_str,
320 );
321
322 if let Some(exts) = cmd_exts {
323 let mut ext_setups: Vec<String> = vec![];
324 for ext in exts {
325 let mut ext_setup = "{".to_string();
326 match ext.source {
327 ExtensionSource::App => {
328 ext_setup += &format!(
329 "'source': 'app', 'root': r'{}', 'name': None",
330 origen::app()
331 .unwrap()
332 .root
333 .join(format!(
334 "{}/commands/extensions/",
335 STATUS.app.as_ref().unwrap().name()
336 ))
337 .display()
338 );
339 }
340 ExtensionSource::Plugin(ref pl_name) => {
341 ext_setup += &format!(
342 "'root': r'{}', 'name': r'{}', 'source': 'plugin'",
343 plugins
344 .unwrap()
345 .plugins
346 .get(pl_name)
347 .unwrap()
348 .root
349 .as_path()
350 .join("commands/extensions/")
351 .display(),
352 pl_name,
353 );
354 }
355 ExtensionSource::Aux(ref ns, ref path) => {
356 ext_setup += &format!(
357 "'root': r'{}', 'name': r'{}', 'source': 'aux'",
358 path.display(),
359 ns,
360 );
361 }
362 }
363 ext_setup += "}";
364 ext_setups.push(ext_setup);
365 }
366 cmd += &format!(", extensions=[{}]", ext_setups.join(", "));
367 }
368
369 if let Some(pls) = plugins {
370 cmd += &format!(
371 ", plugins={{{}}}",
372 pls.plugins
373 .iter()
374 .map(|(n, pl)| format!("'{}': {{'root': r'{}'}}", n, pl.root.display()))
375 .collect::<Vec<String>>()
376 .join(", ")
377 );
378 }
379
380 if let Some(top_overrides) = overrides {
381 for (name, val) in top_overrides.iter() {
382 if let Some(v) = val {
383 cmd += &format!(", {}={}", name, v);
384 }
385 }
386 }
387
388 if let Some(targs) = targets {
389 if targs.clone().count() == 0 {
390 cmd += ", targets=False"
391 } else {
392 cmd += &format!(", {}", strs_to_cli_arr!("targets", targs));
393 }
394 }
395 cmd += &format!(", verbosity={}", LOGGER.verbosity());
396 cmd += &format!(
397 ", {}",
398 strs_to_cli_arr!("verbosity_keywords", origen::LOGGER.data().keywords.iter())
399 );
400 cmd += ");";
401
402 log_debug!("Launching Python: '{}'", &cmd);
403
404 match python::run(&cmd) {
405 Err(e) => {
406 log_error!("{}", &e);
407 exit(1);
408 }
409 Ok(exit_status) => {
410 if exit_status.success() {
411 exit(0);
412 } else {
413 exit(exit_status.code().unwrap_or(1));
414 }
415 }
416 }
417}