use {
anyhow::Result,
clap::Arg,
path_clean::PathClean,
std::{path::PathBuf, str::FromStr},
};
#[derive(Debug, Eq, PartialEq)]
pub(crate) enum Privilege {
Normal,
Experimental,
}
#[derive(Debug)]
pub(crate) enum ManualFormat {
Manpages,
Markdown,
}
#[derive(Debug)]
pub(crate) struct CallArgs {
pub privileges: Privilege,
pub command: Command,
}
impl CallArgs {
pub(crate) fn validate(&self) -> Result<()> {
if self.privileges == Privilege::Experimental {
return Ok(());
}
match &self.command {
| _ => (),
}
Ok(())
}
}
#[derive(Debug)]
pub(crate) enum Command {
Manual {
path: PathBuf,
format: ManualFormat,
},
Autocomplete {
path: PathBuf,
shell: clap_complete::Shell,
},
}
pub(crate) struct ClapArgumentLoader {}
impl ClapArgumentLoader {
fn get_absolute_path(matches: &clap::ArgMatches, name: &str) -> Result<PathBuf> {
let path_str: &String = matches.get_one(name).unwrap();
let path = std::path::Path::new(path_str);
if path.is_absolute() {
Ok(path.to_path_buf().clean())
} else {
Ok(std::env::current_dir()?.join(path).clean())
}
}
pub(crate) fn root_command() -> clap::Command {
let root = clap::Command::new(env!("CARGO_PKG_NAME"))
.version(env!("CARGO_PKG_VERSION"))
.about(env!("CARGO_PKG_DESCRIPTION"))
.author("cchexcode <alexanderh.weber@outlook.com>")
.propagate_version(true)
.subcommand_required(false)
.args([Arg::new("experimental").short('e').long("experimental").help("Enables experimental features.").num_args(0)])
.subcommand(
clap::Command::new("man").about("Renders the manual.")
.arg(clap::Arg::new("out").short('o').long("out").required(true))
.arg(clap::Arg::new("format").short('f').long("format").value_parser(["manpages", "markdown"]).required(true)),
)
.subcommand(
clap::Command::new("autocomplete").about("Renders shell completion scripts.")
.arg(clap::Arg::new("out").short('o').long("out").required(true))
.arg(clap::Arg::new("shell").short('s').long("shell").value_parser(["bash", "zsh", "fish", "elvish", "powershell"]).required(true)),
);
root
}
pub(crate) fn load() -> Result<CallArgs> {
let command = Self::root_command().get_matches();
let privileges = if command.get_flag("experimental") {
Privilege::Experimental
} else {
Privilege::Normal
};
let cmd = if let Some(subc) = command.subcommand_matches("man") {
Command::Manual {
path: Self::get_absolute_path(subc, "out")?,
format: match subc.get_one::<String>("format").unwrap().as_str() {
| "manpages" => ManualFormat::Manpages,
| "markdown" => ManualFormat::Markdown,
| _ => return Err(anyhow::anyhow!("argument \"format\": unknown format")),
},
}
} else if let Some(subc) = command.subcommand_matches("autocomplete") {
Command::Autocomplete {
path: Self::get_absolute_path(subc, "out")?,
shell: clap_complete::Shell::from_str(subc.get_one::<String>("shell").unwrap().as_str()).unwrap(),
}
} else {
anyhow::bail!("unknown command")
};
let callargs = CallArgs { privileges, command: cmd };
callargs.validate()?;
Ok(callargs)
}
}