use clap::CommandFactory;
use clap_complete::{Shell, generate_to};
use clap_mangen::Man;
use std::env;
use std::fs;
use std::io::Result;
use std::path::PathBuf;
use std::process::Command;
#[path = "src/cli.rs"]
mod cli;
use cli::Cli;
fn generate_completions(outdir: &std::ffi::OsString) -> Result<()> {
let mut cmd = Cli::command();
for shell in [
Shell::Bash,
Shell::Fish,
Shell::Zsh,
Shell::PowerShell,
Shell::Elvish,
] {
generate_to(shell, &mut cmd, "panache", outdir)?;
}
let completions_dir = PathBuf::from("target/completions");
fs::create_dir_all(&completions_dir)?;
let outdir_path = PathBuf::from(outdir);
let bash_src = outdir_path.join("panache.bash");
let fish_src = outdir_path.join("panache.fish");
let zsh_src = outdir_path.join("_panache");
if bash_src.exists() {
fs::copy(&bash_src, completions_dir.join("panache.bash"))?;
}
if fish_src.exists() {
fs::copy(&fish_src, completions_dir.join("panache.fish"))?;
}
if zsh_src.exists() {
fs::copy(&zsh_src, completions_dir.join("_panache"))?;
}
Ok(())
}
fn generate_cli_markdown() -> Result<()> {
let is_packaging = std::env::current_dir()
.ok()
.and_then(|p| p.to_str().map(|s| s.contains("/target/package/")))
.unwrap_or(false);
if is_packaging {
return Ok(());
}
let cmd = Cli::command();
let docs_dir = PathBuf::from("docs");
if !docs_dir.exists() {
return Ok(());
}
let opts = clap_markdown::MarkdownOptions::default()
.show_footer(false)
.title(String::from(""))
.show_table_of_contents(false);
let markdown = clap_markdown::help_markdown_command_custom(&cmd, &opts);
let mut document = String::new();
document.push_str("---\n");
document.push_str("title: CLI Reference\n");
document.push_str("---\n\n");
document.push_str(&markdown);
let output_path = docs_dir.join("cli.qmd");
fs::write(&output_path, &document)?;
let panache_bin = PathBuf::from("target/release/panache");
if panache_bin.exists() {
let status = Command::new(&panache_bin)
.arg("format")
.arg("--write")
.arg(&output_path)
.status();
match status {
Ok(exit_status) if exit_status.success() => {
println!("Generated and formatted CLI markdown: {:?}", output_path);
}
_ => {
println!(
"Generated CLI markdown (formatting skipped): {:?}",
output_path
);
}
}
} else {
println!(
"Generated CLI markdown (panache binary not found, skipping format): {:?}",
output_path
);
}
Ok(())
}
fn generate_man_pages() -> Result<()> {
let out_dir = PathBuf::from("target/man");
fs::create_dir_all(&out_dir)?;
let cmd = Cli::command();
let man = Man::new(cmd.clone());
let mut buffer = Vec::new();
man.render(&mut buffer)?;
fs::write(out_dir.join("panache.1"), buffer)?;
for subcommand in cmd.get_subcommands() {
let subcommand_name = subcommand.get_name();
if subcommand_name == "help" {
continue; }
let name = format!("panache-{}", subcommand_name);
let man = Man::new(subcommand.clone()).title(&name);
let mut buffer = Vec::new();
man.render(&mut buffer)?;
let content = String::from_utf8_lossy(&buffer);
let fixed_content = content.replace(
&format!("{}\\-", subcommand_name),
&format!("panache\\-{}\\-", subcommand_name),
);
fs::write(
out_dir.join(format!("{}.1", name)),
fixed_content.as_bytes(),
)?;
for nested in subcommand.get_subcommands() {
let nested_name = nested.get_name();
if nested_name == "help" {
continue;
}
let full_name = format!("panache-{}-{}", subcommand_name, nested_name);
let man = Man::new(nested.clone()).title(&full_name);
let mut buffer = Vec::new();
man.render(&mut buffer)?;
let content = String::from_utf8_lossy(&buffer);
let fixed_content = content
.replace(
&format!("{} \\-", nested_name),
&format!("{} \\-", full_name),
)
.replace(
&format!("\\fB{}\\fR", nested_name),
&format!("\\fBpanache {} {}\\fR", subcommand_name, nested_name),
);
fs::write(
out_dir.join(format!("{}.1", full_name)),
fixed_content.as_bytes(),
)?;
}
}
Ok(())
}
fn main() -> Result<()> {
if let Some(outdir) = env::var_os("OUT_DIR") {
generate_completions(&outdir)?;
}
generate_man_pages()?;
generate_cli_markdown()?;
println!("cargo:rerun-if-changed=src/cli.rs");
println!("cargo:rerun-if-changed=build.rs");
Ok(())
}