diff --git a/Cargo.toml b/Cargo.toml index af3c2ef..b826813 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cwdemangle" -version = "0.1.0" +version = "0.1.1" edition = "2018" authors = ["Luke Street "] license = "MIT OR Apache-2.0" diff --git a/src/argh_cargo.rs b/src/argh_cargo.rs new file mode 100644 index 0000000..496c2bc --- /dev/null +++ b/src/argh_cargo.rs @@ -0,0 +1,64 @@ +// From https://gist.github.com/suluke/e0c672492126be0a4f3b4f0e1115d77c +//! Extend `argh` to be better integrated with the `cargo` ecosystem +//! +//! For now, this only adds a --version/-V option which causes early-exit. +use argh::{FromArgs, TopLevelCommand}; + +struct ArgsOrVersion(T); +impl TopLevelCommand for ArgsOrVersion where T: FromArgs {} +impl FromArgs for ArgsOrVersion +where T: FromArgs +{ + fn from_args(command_name: &[&str], args: &[&str]) -> Result { + /// Also use argh for catching `--version`-only invocations + #[derive(FromArgs)] + struct Version { + /// print version information and exit + #[argh(switch, short = 'V')] + pub version: bool, + } + match Version::from_args(command_name, args) { + Ok(v) => { + if v.version { + Err(argh::EarlyExit { + output: format!( + "{} {}", + command_name.first().unwrap_or(&""), + env!("CARGO_PKG_VERSION") + ), + status: Ok(()), + }) + } else { + // seems args are empty + T::from_args(command_name, args).map(Self) + } + } + Err(exit) => match exit.status { + Ok(()) => { + // must have been --help + let help = match T::from_args(command_name, &["--help"]) { + Ok(_) => unreachable!(), + Err(exit) => exit.output, + }; + Err(argh::EarlyExit { + output: format!( + "{} -V, --version print version information and exit", + help + ), + status: Ok(()), + }) + } + Err(()) => T::from_args(command_name, args).map(Self), + }, + } + } +} + +/// Create a `FromArgs` type from the current process’s `env::args`. +/// +/// This function will exit early from the current process if argument parsing was unsuccessful or if information like `--help` was requested. +/// Error messages will be printed to stderr, and `--help` output to stdout. +pub fn from_env() -> T +where T: TopLevelCommand { + argh::from_env::>().0 +} diff --git a/src/main.rs b/src/main.rs index 9e7e687..d9cd8f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,12 @@ use argh::FromArgs; use cwdemangle::demangle; +use crate::argh_cargo::from_env; + +mod argh_cargo; + #[derive(FromArgs)] -/// CodeWarrior C++ demangler +/// A CodeWarrior C++ symbol demangler. struct Args { /// the symbol to demangle #[argh(positional)] @@ -10,7 +14,7 @@ struct Args { } fn main() -> Result<(), &'static str> { - let args: Args = argh::from_env(); + let args: Args = from_env(); return if let Some(symbol) = demangle(args.symbol.as_str()) { println!("{}", symbol); Ok(())