diff --git a/Cargo.lock b/Cargo.lock index 669c6c0..82a0c67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,9 +70,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" @@ -249,9 +249,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.4" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", "clap_derive", @@ -259,9 +259,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", @@ -269,11 +269,20 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_complete" +version = "4.5.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aad5b1b4de04fead402672b48897030eec1f3bfe1550776322f59f6d6e6a5677" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck", "proc-macro2", @@ -283,9 +292,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "colorchoice" @@ -1050,6 +1059,7 @@ dependencies = [ "bincode", "byteorder", "clap", + "clap_complete", "error-chain", "futures", "grep", diff --git a/Cargo.toml b/Cargo.toml index 46e3718..0e6220c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ xdg = "2.5.2" xml-rs = "0.8.20" xz2 = "0.1.7" zstd = { version = "0.12.4", features = [ "zstdmt" ] } +clap_complete = "4.5.54" [dependencies.hyper] features = ["client", "http1", "http2", "runtime", "stream"] diff --git a/src/bin/nix-channel-index.rs b/src/bin/nix-channel-index.rs index 75de785..e847e23 100644 --- a/src/bin/nix-channel-index.rs +++ b/src/bin/nix-channel-index.rs @@ -5,7 +5,8 @@ use std::os::unix::ffi::OsStringExt; use std::path::PathBuf; use std::process; -use clap::Parser; +use clap::{CommandFactory, Parser}; +use clap_complete::{generate, Shell}; use error_chain::ChainedError; use futures::{future, StreamExt}; use nix_index::files::FileNode; @@ -179,12 +180,26 @@ struct Args { /// Show a stack trace in the case of a Nix evaluation error #[clap(long)] show_trace: bool, + + /// Generate shell completions to stdout. + #[clap(long)] + completions: Option, } #[tokio::main] async fn main() { let args = Args::parse(); + if let Some(shell) = args.completions { + generate( + shell, + &mut Args::command(), + "nix-channel-index", + &mut io::stdout(), + ); + return; + } + if let Err(e) = update_index(&args).await { eprintln!("error: {}", e); diff --git a/src/bin/nix-index.rs b/src/bin/nix-index.rs index 004e0e0..627b14e 100644 --- a/src/bin/nix-index.rs +++ b/src/bin/nix-index.rs @@ -5,7 +5,8 @@ use std::io::{self, Write}; use std::path::PathBuf; use std::process; -use clap::Parser; +use clap::{CommandFactory, Parser}; +use clap_complete::{generate, Shell}; use error_chain::ChainedError; use futures::future::Either; use futures::{future, StreamExt}; @@ -153,12 +154,21 @@ struct Args { /// Note: does not check if the cached data is up to date! Use only for development. #[clap(long)] path_cache: bool, + + /// Generate shell completions to stdout. + #[clap(long)] + completions: Option, } #[tokio::main] async fn main() { let args = Args::parse(); + if let Some(shell) = args.completions { + generate(shell, &mut Args::command(), "nix-index", &mut io::stdout()); + return; + } + if let Err(e) = update_index(&args).await { eprintln!("error: {}", e); diff --git a/src/bin/nix-locate.rs b/src/bin/nix-locate.rs index 2c18747..5986041 100644 --- a/src/bin/nix-locate.rs +++ b/src/bin/nix-locate.rs @@ -1,13 +1,17 @@ //! Tool for searching for files in nixpkgs packages use std::collections::HashSet; use std::ffi::OsStr; +use std::io; use std::path::PathBuf; use std::process; use std::result; use std::str; use std::str::FromStr; +use clap::CommandFactory; use clap::{value_parser, Parser}; +use clap_complete::generate; +use clap_complete::Shell; use error_chain::error_chain; use nix_index::database; use nix_index::files::{self, FileTreeEntry, FileType}; @@ -153,7 +157,10 @@ fn locate(args: &Args) -> Result<()> { /// /// Handles parsing the values of more complex arguments. fn process_args(matches: Opts) -> result::Result { - let pattern_arg = matches.pattern; + let pattern_arg = matches.pattern.ok_or(Opts::command().error( + clap::error::ErrorKind::MissingRequiredArgument, + "The argument is missing", + ))?; let package_arg = matches.package; let start_anchor = if matches.at_root { "^" } else { "" }; @@ -237,7 +244,7 @@ fn cache_dir() -> &'static OsStr { struct Opts { /// Pattern for which to search // #[clap(name = "PATTERN")] - pattern: String, + pattern: Option, /// Directory where the index is stored #[clap(short, long = "db", default_value_os = cache_dir(), env = "NIX_INDEX_DATABASE")] @@ -293,6 +300,10 @@ struct Opts { /// store path are omitted. This is useful for scripts that use the output of nix-locate. #[clap(long)] minimal: bool, + + /// Generate shell completions to stdout. + #[clap(long)] + completions: Option, } #[derive(clap::ValueEnum, Clone, Copy, Debug)] @@ -318,6 +329,11 @@ impl FromStr for Color { fn main() { let args = Opts::parse(); + if let Some(shell) = args.completions { + generate(shell, &mut Opts::command(), "nix-locate", &mut io::stdout()); + return; + } + let args = process_args(args).unwrap_or_else(|e| e.exit()); if let Err(e) = locate(&args) {