use std::{
fs::OpenOptions,
io::{self, Write},
};
use anyhow::{ensure, Context, Result};
use camino::{Utf8Path, Utf8PathBuf};
use clap::{Args, CommandFactory, Parser, ValueHint};
use clap_complete::Shell;
#[derive(Parser)]
#[command(name = "cargo", bin_name = "cargo")]
enum Cli {
#[command(subcommand)]
Hatch(Command),
}
#[derive(Parser)]
#[command(about, author, version)]
pub enum Command {
Init {
name: Option<String>,
},
List,
New {
bookmark: String,
#[command(flatten)]
flags: CreationFlags,
},
Git {
#[arg(long)]
folder: Option<Utf8PathBuf>,
url: String,
#[command(flatten)]
flags: CreationFlags,
},
Local {
#[arg(value_hint = ValueHint::DirPath)]
path: Utf8PathBuf,
#[command(flatten)]
flags: CreationFlags,
},
Completions {
#[arg(value_enum)]
shell: Shell,
},
Manpages {
#[arg(value_hint = ValueHint::DirPath)]
dir: Utf8PathBuf,
},
}
#[derive(Args)]
pub struct CreationFlags {
pub name: Option<String>,
#[arg(short, long)]
pub update_deps: bool,
}
#[must_use]
pub fn parse() -> Command {
let Cli::Hatch(cmd) = Cli::parse();
cmd
}
pub fn completions(shell: Shell) {
clap_complete::generate(
shell,
&mut Cli::command(),
env!("CARGO_PKG_NAME"),
&mut io::stdout().lock(),
);
}
pub fn manpages(dir: &Utf8Path) -> Result<()> {
fn print(dir: &Utf8Path, app: &clap::Command) -> Result<()> {
let name = app.get_display_name().unwrap_or_else(|| app.get_name());
let out = dir.join(format!("{name}.1"));
let mut out = OpenOptions::new()
.write(true)
.create_new(true)
.open(&out)
.with_context(|| format!("the file `{out}` already exists"))?;
clap_mangen::Man::new(app.clone()).render(&mut out)?;
out.flush()?;
for sub in app.get_subcommands() {
print(dir, sub)?;
}
Ok(())
}
ensure!(dir.try_exists()?, "target directory doesn't exist");
let mut app = Command::command();
app.build();
print(dir, &app)
}
#[cfg(test)]
mod tests {
use super::Cli;
#[test]
fn verify_cli() {
use clap::CommandFactory;
Cli::command().debug_assert();
}
}