use argh::{FromArgs, TopLevelCommand};
struct ArgsOrVersion<T: FromArgs>(T);
impl<T> argh::TopLevelCommand for ArgsOrVersion<T> where T: FromArgs {}
impl<T> FromArgs for ArgsOrVersion<T>
where
T: FromArgs,
{
fn from_args(command_name: &[&str], args: &[&str]) -> Result<Self, argh::EarlyExit> {
#[derive(FromArgs)]
struct Version {
#[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 {
T::from_args(command_name, args).map(Self)
}
}
Err(exit) => match exit.status {
Ok(()) => {
let help = match T::from_args(command_name, &["--help"]) {
Ok(_) => unreachable!(),
Err(exit) => exit.output,
};
Err(argh::EarlyExit {
output: format!(
"{help} -V, --version print version information and exit"
),
status: Ok(()),
})
}
Err(()) => T::from_args(command_name, args).map(Self),
},
}
}
}
pub fn from_env<T>() -> T
where
T: TopLevelCommand,
{
argh::from_env::<ArgsOrVersion<T>>().0
}