diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e77ffc3..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "docs/wiki/themes/hugo-book"] - path = docs/wiki/themes/hugo-book - url = https://github.com/alex-shpak/hugo-book diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index a717844..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "lldb", - "request": "launch", - "name": "Debug executable 'complate'", - "cargo": { - "args": [ - "build", - "--bin=complate", - "--package=complate" - ], - "filter": { - "name": "complate", - "kind": "bin" - } - }, - "args": [ - "render", - "--shell-trust", "prompt", - ], - "cwd": "${workspaceFolder}" - }, - { - "type": "lldb", - "request": "launch", - "name": "Debug unit tests in executable 'complate'", - "cargo": { - "args": [ - "test", - "--no-run", - "--bin=complate", - "--package=complate" - ], - "filter": { - "name": "complate", - "kind": "bin" - } - }, - "args": [], - "cwd": "${workspaceFolder}" - } - ] -} \ No newline at end of file diff --git a/src/args/mod.rs b/src/args/mod.rs index 70e519c..3fd76ab 100644 --- a/src/args/mod.rs +++ b/src/args/mod.rs @@ -13,15 +13,6 @@ pub struct CallArgs { impl CallArgs { #[allow(clippy::single_match)] pub async fn validate(&self) -> Result<(), Box> { - match &self.command { - | Command::Render(args) => { - if args.helpers && args.shell_trust != ShellTrust::Ultimate { - return Err(Box::new(Error::NoTrust)); - } - }, - | _ => {}, - } - match self.privileges { | Privilege::Normal => match &self.command { | Command::Render(args) => { @@ -34,9 +25,6 @@ impl CallArgs { if args.value_overrides.len() > 0 { return Err(Box::new(Error::ExperimentalCommand)); } - if args.helpers { - return Err(Box::new(Error::ExperimentalCommand)); - } #[allow(unreachable_code)] Ok(()) }, @@ -61,8 +49,8 @@ pub enum ManualFormat { #[derive(Debug)] pub enum Command { - Manual(String, ManualFormat), - Autocomplete(String, clap_complete::Shell), + Manual { path: String, format: ManualFormat }, + Autocomplete { path: String, shell: clap_complete::Shell }, Init, Render(RenderArguments), } @@ -72,7 +60,6 @@ pub struct RenderArguments { pub configuration: String, pub template: Option, pub value_overrides: std::collections::HashMap, - pub helpers: bool, pub shell_trust: ShellTrust, pub loose: bool, pub backend: Backend, @@ -161,10 +148,6 @@ impl ClapArgumentLoader { .long("loose") .action(ArgAction::SetTrue) .help("Defines that the templating is done in non-strict mode (allow missing value for variable).")) - .arg(clap::Arg::new("helpers") - .long("helpers") - .action(ArgAction::SetTrue) - .help("Enables handlebar helpers.")) .arg(clap::Arg::new("backend") .short('b') .long("backend") @@ -189,22 +172,22 @@ impl ClapArgumentLoader { if let Some(subc) = command_matches.subcommand_matches("man") { Ok(CallArgs { - command: Command::Manual( - subc.get_one::("out").unwrap().into(), - match subc.get_one::("format").unwrap().as_str() { + command: Command::Manual { + path: subc.get_one::("out").unwrap().into(), + format: match subc.get_one::("format").unwrap().as_str() { | "manpages" => ManualFormat::Manpages, | "markdown" => ManualFormat::Markdown, | _ => return Err(Box::new(Error::Argument("unknown format".into()))), }, - ), + }, privileges, }) } else if let Some(subc) = command_matches.subcommand_matches("autocomplete") { Ok(CallArgs { - command: Command::Autocomplete( - subc.get_one::("out").unwrap().into(), - clap_complete::Shell::from_str(subc.get_one::("shell").unwrap().as_str()).unwrap(), - ), + command: Command::Autocomplete { + path: subc.get_one::("out").unwrap().into(), + shell: clap_complete::Shell::from_str(subc.get_one::("shell").unwrap().as_str()).unwrap(), + }, privileges, }) } else if let Some(..) = command_matches.subcommand_matches("init") { @@ -236,7 +219,6 @@ impl ClapArgumentLoader { | "ui" => Backend::UI, | _ => return Err(Box::new(Error::Argument("no backend specified".into()))), }; - let helpers = subc.get_flag("helpers"); Ok(CallArgs { privileges, @@ -247,7 +229,6 @@ impl ClapArgumentLoader { shell_trust, loose, backend, - helpers, }), }) } else { diff --git a/src/error.rs b/src/error.rs index 39333ff..ffd2bae 100644 --- a/src/error.rs +++ b/src/error.rs @@ -15,7 +15,7 @@ pub(crate) enum Error { #[error("unknown command")] UnknownCommand, #[error("no trust")] - NoTrust, + NoTrust(String), #[error("shell command")] ShellCommand(String), #[error("user interact abort")] diff --git a/src/main.rs b/src/main.rs index 714f6d8..67f8151 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,7 @@ async fn main() -> Result<(), Box> { cmd.validate().await?; match cmd.command { - | crate::args::Command::Manual(path, format) => { + | crate::args::Command::Manual { path, format } => { let out_path = PathBuf::from(path); std::fs::create_dir_all(&out_path)?; match format { @@ -31,7 +31,7 @@ async fn main() -> Result<(), Box> { } Ok(()) }, - | crate::args::Command::Autocomplete(path, shell) => { + | crate::args::Command::Autocomplete { path, shell } => { let out_path = PathBuf::from(path); std::fs::create_dir_all(&out_path)?; reference::build_shell_completion(&out_path, &shell)?; diff --git a/src/render/mod.rs b/src/render/mod.rs index 89237ac..6cc7c29 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -49,42 +49,45 @@ pub async fn render( hb.register_escape_fn(|s| s.to_owned()); hb.set_strict_mode(!args.loose); - if args.helpers { - for helper in helpers { - let h_func = move |h: &handlebars::Helper, - _: &handlebars::Handlebars, - _: &handlebars::Context, - _: &mut handlebars::RenderContext, - out: &mut dyn handlebars::Output| - -> handlebars::HelperResult { - let param = h - .param(0) - .ok_or_else(|| Error::Helper("no parameter to helper function found".into())) - .unwrap(); - // dbg!(param); - let cmd = helper.1.shell.to_owned(); - - let output = std::process::Command::new("sh") - .arg("-c") - .arg(cmd) - .env( - "VALUE", - param - .value() - .as_str() - .ok_or_else(|| Error::Helper("parameter is not a string".into())) - .unwrap(), - ) - .output()?; - if output.status.code().unwrap() != 0 { - return Err(handlebars::RenderError::new("failed to get command status")); - } - - out.write(String::from_utf8(output.stdout).unwrap().as_str())?; - Ok(()) - }; - hb.register_helper(helper.0, Box::new(h_func)) - } + if helpers.len() > 0 && args.shell_trust != ShellTrust::Ultimate { + return Err(Box::new(Error::NoTrust( + "need trust for executing helper functions".into(), + ))); + } + for helper in helpers { + let h_func = move |h: &handlebars::Helper, + _: &handlebars::Handlebars, + _: &handlebars::Context, + _: &mut handlebars::RenderContext, + out: &mut dyn handlebars::Output| + -> handlebars::HelperResult { + let param = h + .param(0) + .ok_or_else(|| Error::Helper("no parameter to helper function found".into())) + .unwrap(); + // dbg!(param); + let cmd = helper.1.shell.to_owned(); + + let output = std::process::Command::new("sh") + .arg("-c") + .arg(cmd) + .env( + "VALUE", + param + .value() + .as_str() + .ok_or_else(|| Error::Helper("parameter is not a string".into())) + .unwrap(), + ) + .output()?; + if output.status.code().unwrap() != 0 { + return Err(handlebars::RenderError::new("failed to get command status")); + } + + out.write(String::from_utf8(output.stdout).unwrap().as_str())?; + Ok(()) + }; + hb.register_helper(helper.0, Box::new(h_func)) } Ok(hb.render_template(template, &values_json)?) @@ -221,7 +224,11 @@ async fn shell( shell_trust: &ShellTrust, ) -> Result> { match shell_trust { - | ShellTrust::None => return Err(Box::new(Error::NoTrust)), + | ShellTrust::None => { + return Err(Box::new(Error::NoTrust( + "need trust for executing shell commands".into(), + ))) + }, | ShellTrust::Ultimate => {}, }