feat: add CLI asset generation for shell completions and man page

This commit is contained in:
2026-02-28 01:01:33 -06:00
parent ce5fefa833
commit b8a2cfa9be
9 changed files with 177 additions and 2 deletions
+7
View File
@@ -112,6 +112,13 @@ pub enum Commands {
},
/// Show current configuration
Config,
/// Generate shell completion scripts and a man page into an output directory.
#[command(hide = true)]
GenerateArtifacts {
/// Output directory for generated files
#[arg(long, value_name = "DIR")]
out_dir: PathBuf,
},
/// Create a new package specification interactively
MakeSpec {
/// Output file path (defaults to <name>.toml)
+74
View File
@@ -0,0 +1,74 @@
//! Generation helpers for CLI man pages and shell completions.
use crate::cli::Cli;
use anyhow::{Context, Result};
use clap::CommandFactory;
use clap_complete::Shell;
use std::fs;
use std::path::Path;
const BIN_NAME: &str = "depot";
/// Generate all supported shell completion scripts and a man page into `out_dir`.
pub fn generate_cli_assets(out_dir: &Path) -> Result<()> {
fs::create_dir_all(out_dir)
.with_context(|| format!("Failed to create output directory {}", out_dir.display()))?;
generate_completion(out_dir, Shell::Bash, "depot.bash")?;
generate_completion(out_dir, Shell::Zsh, "_depot")?;
generate_completion(out_dir, Shell::Fish, "depot.fish")?;
generate_man_page(out_dir, "depot.1")?;
Ok(())
}
fn command_for_generation() -> clap::Command {
Cli::command().name(BIN_NAME)
}
fn generate_completion(out_dir: &Path, shell: Shell, filename: &str) -> Result<()> {
let mut command = command_for_generation();
let output_path = out_dir.join(filename);
let mut buffer = Vec::new();
clap_complete::generate(shell, &mut command, BIN_NAME, &mut buffer);
fs::write(&output_path, buffer).with_context(|| {
format!(
"Failed to write {} completion to {}",
shell,
output_path.display()
)
})?;
Ok(())
}
fn generate_man_page(out_dir: &Path, filename: &str) -> Result<()> {
let output_path = out_dir.join(filename);
let mut buffer = Vec::new();
clap_mangen::Man::new(command_for_generation())
.render(&mut buffer)
.context("Failed to render clap man page")?;
fs::write(&output_path, buffer)
.with_context(|| format!("Failed to write man page {}", output_path.display()))?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn generate_cli_assets_writes_expected_files() {
let temp = tempfile::tempdir().unwrap();
generate_cli_assets(temp.path()).unwrap();
let bash = temp.path().join("depot.bash");
let zsh = temp.path().join("_depot");
let fish = temp.path().join("depot.fish");
let man = temp.path().join("depot.1");
assert!(bash.exists());
assert!(zsh.exists());
assert!(fish.exists());
assert!(man.exists());
assert!(!std::fs::read_to_string(&man).unwrap().is_empty());
}
}
+6 -2
View File
@@ -1,7 +1,7 @@
use crate::cli::{Cli, Commands, RepoCommands, RepoKindArg};
use crate::{
builder, config, cross, db, deps, index, install, locking, package, planner, signing, source,
staging, ui,
builder, cli_assets, config, cross, db, deps, index, install, locking, package, planner,
signing, source, staging, ui,
};
use anyhow::{Context, Result};
use std::fs;
@@ -1949,6 +1949,10 @@ pub fn run(cli: Cli) -> Result<()> {
}
}
},
Commands::GenerateArtifacts { out_dir } => {
cli_assets::generate_cli_assets(&out_dir)?;
ui::success(format!("Generated CLI assets in {}", out_dir.display()));
}
Commands::Config => {
let config = config::Config::for_rootfs(&cli.rootfs);
let config_lock = locking::open_lock(&config)?;
+1
View File
@@ -3,6 +3,7 @@
mod builder;
mod cli;
mod cli_assets;
mod commands;
mod config;
mod cross;