origen/framework/
app_cmds.rs1use super::build_commands;
2use crate::commands::_prelude::*;
3use indexmap::IndexMap;
4use origen::core::application::Application;
5use origen::{Result, STATUS};
6use std::fs;
7use std::path::PathBuf;
8
9use super::{Command, CommandTOML, CommandsToml, Extensions};
10
11pub const APP_COMMANDS: [&'static str; 2] = [crate::commands::app::BASE_CMD, "commands"];
12
13pub struct AppCmds {
14 pub root: PathBuf,
15 pub top_commands: Vec<String>,
16 pub commands: IndexMap<String, Command>,
17}
18
19impl AppCmds {
20 fn _add_cmd(
21 slf: &mut Self,
22 current_path: String,
23 current_cmd: &mut CommandTOML,
24 parent_cmd: Option<&Command>,
25 ) -> Result<bool> {
26 if let Some(c) = Command::from_toml_cmd(
27 current_cmd,
28 CmdSrc::App(current_path.to_string()),
29 parent_cmd,
30 )? {
31 if let Some(ref mut sub_cmds) = current_cmd.subcommand {
32 for mut sub in sub_cmds {
33 Self::_add_cmd(
34 slf,
35 format!("{}.{}", current_path, &sub.name),
36 &mut sub,
37 Some(&c),
38 )?;
39 }
40 }
41 slf.commands.insert(current_path.clone(), c);
42 Ok(true)
43 } else {
44 Ok(false)
45 }
46 }
47
48 pub fn new(app: &Application, exts: &mut Extensions) -> Result<Self> {
49 let mut slf = Self {
50 root: app.root.to_owned(),
51 top_commands: vec![],
52 commands: IndexMap::new(),
53 };
54
55 for commands_toml in app.config().cmd_paths() {
56 let content = match fs::read_to_string(&commands_toml) {
57 Ok(x) => x,
58 Err(e) => {
59 bail!("{}", e);
60 }
61 };
62
63 let command_config: CommandsToml = match toml::from_str(&content) {
64 Ok(x) => x,
65 Err(e) => {
66 log_error!(
67 "Malformed Commands TOML '{}': {}",
68 &commands_toml.display(),
69 e
70 );
71 continue;
72 }
73 };
74 if let Some(commands) = command_config.command {
83 for mut cmd in commands {
84 if Self::_add_cmd(&mut slf, cmd.name.to_owned(), &mut cmd, None)? {
85 slf.top_commands.push(cmd.name.to_owned());
86 }
87 }
88 }
89
90 if let Some(extensions) = command_config.extension {
91 for ext in extensions {
92 match exts.add_from_app_toml(ext) {
93 Ok(_) => {}
94 Err(e) => log_error!(
95 "Failed to add extensions from application from '{}': {}",
96 &commands_toml.display(),
97 e
98 ),
99 }
100 }
101 }
102 }
103 Ok(slf)
104 }
105
106 pub fn cmds_root(&self) -> Result<PathBuf> {
107 let mut r = self.root.to_owned();
108 r.push(STATUS.app.as_ref().unwrap().name());
109 r.push("commands");
110 Ok(r)
111 }
112}
113
114pub(crate) fn add_helps(helps: &mut CmdHelps, app_cmds: &AppCmds) {
115 helps
116 .add_core_sub_cmd(&APP_COMMANDS)
117 .set_help_msg("Interface with commands added by the application")
118 .set_as_not_extendable();
119 for (n, c) in app_cmds.commands.iter() {
120 helps.add_app_cmd(n).set_help_msg(&c.help);
121 }
122}
123
124pub(crate) fn add_commands<'a>(
125 app: App,
126 helps: &'a CmdHelps,
127 app_commands: &'a AppCmds,
128 exts: &'a Extensions,
129) -> Result<App> {
130 let mut app_cmds_cmd = helps
131 .core_subc(&APP_COMMANDS)
132 .visible_alias("cmds")
133 .arg_required_else_help(true);
134
135 for top_cmd_name in app_commands.top_commands.iter() {
136 app_cmds_cmd = app_cmds_cmd.subcommand(build_commands(
137 &app_commands.commands.get(top_cmd_name).unwrap(),
138 &|cmd, app, opt_cache| exts.apply_to_app_cmd(cmd, app, opt_cache),
139 &|cmd| app_commands.commands.get(cmd).unwrap(),
140 &|cmd, app| helps.apply_helps(&CmdSrc::App(cmd.to_string()), app),
141 ));
142 }
143 Ok(app.subcommand(app_cmds_cmd))
144}