diff --git a/Cargo.lock b/Cargo.lock index 2509000a2..f809a26ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,9 +181,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "clap" -version = "4.5.1" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" dependencies = [ "clap_builder", "clap_derive", @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" dependencies = [ "anstream", "anstyle", @@ -201,11 +201,20 @@ dependencies = [ "strsim 0.11.0", ] +[[package]] +name = "clap_complete" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d598e88f6874d4b888ed40c71efbcbf4076f1dfbae128a08a8c9e45f710605d" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck", "proc-macro2", @@ -665,9 +674,9 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex" @@ -2142,6 +2151,7 @@ name = "xtask" version = "0.1.0" dependencies = [ "clap", + "clap_complete", "clap_mangen", "devenv", "miette", diff --git a/package.nix b/package.nix index 76abee328..7605cbdc2 100644 --- a/package.nix +++ b/package.nix @@ -42,5 +42,16 @@ pkgs.rustPlatform.buildRustPackage { # Generate manpages cargo xtask generate-manpages --out-dir man installManPage man/* + + # Generate shell completions + compdir=./completions + for shell in bash fish zsh; do + cargo xtask generate-shell-completion $shell --out-dir $compdir + done + + installShellCompletion --cmd devenv \ + --bash $compdir/devenv.bash \ + --fish $compdir/devenv.fish \ + --zsh $compdir/_devenv ''; } diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index c964bf8f1..d295853a8 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -5,6 +5,7 @@ edition.workspace = true [dependencies] clap.workspace = true +clap_complete = "4.5.7" clap_mangen = "0.2.22" devenv = { path = "../devenv" } miette.workspace = true diff --git a/xtask/src/cli.rs b/xtask/src/cli.rs new file mode 100644 index 000000000..741f7c14e --- /dev/null +++ b/xtask/src/cli.rs @@ -0,0 +1 @@ +include!("../../devenv/src/cli.rs"); diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs new file mode 100644 index 000000000..4931e8a47 --- /dev/null +++ b/xtask/src/lib.rs @@ -0,0 +1,3 @@ +pub(crate) mod cli; +pub mod manpage; +pub mod shell_completion; diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 96025c0f0..f97622cbf 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,7 +1,6 @@ use clap::Parser; use miette::Result; - -mod manpage; +use xtask::{manpage, shell_completion}; #[derive(clap::Parser)] struct Cli { @@ -20,12 +19,27 @@ enum Command { )] out_dir: std::path::PathBuf, }, + GenerateShellCompletion { + #[clap(value_enum)] + shell: clap_complete::Shell, + + #[clap( + long, + value_parser, + value_hint = clap::ValueHint::DirPath, + default_value_os_t = shell_completion::default_out_dir() + )] + out_dir: std::path::PathBuf, + }, } fn main() -> Result<()> { let cli = Cli::parse(); match cli.command { - Command::GenerateManpages { out_dir } => manpage::generate_manpages(out_dir), + Command::GenerateManpages { out_dir } => manpage::generate(out_dir), + Command::GenerateShellCompletion { shell, out_dir } => { + shell_completion::generate(shell, out_dir) + } } } diff --git a/xtask/src/manpage.rs b/xtask/src/manpage.rs index 2cf9fef03..a2dd80ff8 100644 --- a/xtask/src/manpage.rs +++ b/xtask/src/manpage.rs @@ -1,16 +1,13 @@ +use super::cli::Cli; use clap::CommandFactory; use miette::{IntoDiagnostic, Result}; use std::fs; use std::path::{Path, PathBuf}; -mod cli { - include!("../../devenv/src/cli.rs"); -} - -pub fn generate_manpages(out_dir: impl AsRef) -> Result<()> { +pub fn generate(out_dir: impl AsRef) -> Result<()> { fs::create_dir_all(&out_dir).into_diagnostic()?; - clap_mangen::generate_to(cli::Cli::command(), &out_dir).into_diagnostic()?; - println!("Generated man pages to {}", out_dir.as_ref().display()); + clap_mangen::generate_to(Cli::command(), &out_dir).into_diagnostic()?; + eprintln!("Generated man pages to {}", out_dir.as_ref().display()); Ok(()) } diff --git a/xtask/src/shell_completion.rs b/xtask/src/shell_completion.rs new file mode 100644 index 000000000..70036561a --- /dev/null +++ b/xtask/src/shell_completion.rs @@ -0,0 +1,23 @@ +use crate::cli::Cli; +use clap::CommandFactory; +use miette::{IntoDiagnostic, Result}; +use std::fs; +use std::path::{Path, PathBuf}; + +pub fn generate(shell: clap_complete::Shell, out_dir: impl AsRef) -> Result<()> { + fs::create_dir_all(&out_dir).into_diagnostic()?; + let mut cmd = Cli::command(); + let bin_name = cmd.get_name().to_string(); + let completion_path = clap_complete::generate_to(shell, &mut cmd, bin_name, out_dir.as_ref()) + .into_diagnostic()?; + eprintln!( + "Generated {} completions to {}", + shell, + completion_path.display() + ); + Ok(()) +} + +pub fn default_out_dir() -> PathBuf { + std::env::current_dir().unwrap() +}