From 396b9baaa592b0fc0b8bcc9af6ce4b59c729ab58 Mon Sep 17 00:00:00 2001 From: Florian Hofmair Date: Wed, 4 Oct 2017 14:31:08 +0200 Subject: [PATCH] Use clap to generate shell completions --- Cargo.toml | 4 +++ build.rs | 19 +++++++++++++ src/app.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 80 ++--------------------------------------------------- 4 files changed, 104 insertions(+), 78 deletions(-) create mode 100644 build.rs create mode 100644 src/app.rs diff --git a/Cargo.toml b/Cargo.toml index 43a0af1..f7f76e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ keywords = ["search", "find", "file", "filesystem", "tool"] categories = ["command-line-utilities"] license = "MIT" exclude = ["benchmarks"] +build = "build.rs" [badges] appveyor = { repository = "sharkdp/fd" } @@ -26,3 +27,6 @@ atty = "0.2" regex = "0.2" ignore = "0.2" num_cpus = "1.6.2" + +[build-dependencies] +clap = "2.26.0" \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..c39c03c --- /dev/null +++ b/build.rs @@ -0,0 +1,19 @@ +#[macro_use] +extern crate clap; + +use clap::Shell; + +include!("src/app.rs"); + +fn main() { + let outdir = match std::env::var_os("OUT_DIR") { + None => return, + Some(outdir) => outdir, + }; + + let mut app = build_app(); + app.gen_completions("fd", Shell::Bash, &outdir); + app.gen_completions("fd", Shell::Fish, &outdir); + app.gen_completions("fd", Shell::Zsh, &outdir); + app.gen_completions("fd", Shell::PowerShell, &outdir); +} \ No newline at end of file diff --git a/src/app.rs b/src/app.rs new file mode 100644 index 0000000..02e7682 --- /dev/null +++ b/src/app.rs @@ -0,0 +1,79 @@ +use clap::{App, AppSettings, Arg}; + +pub fn build_app() -> App<'static, 'static> { + App::new("fd") + .version(crate_version!()) + .usage("fd [FLAGS/OPTIONS] [] []") + .setting(AppSettings::ColoredHelp) + .setting(AppSettings::DeriveDisplayOrder) + .arg(Arg::with_name("hidden") + .long("hidden") + .short("H") + .help("Search hidden files and directories")) + .arg(Arg::with_name("no-ignore") + .long("no-ignore") + .short("I") + .help("Do not respect .(git)ignore files")) + .arg(Arg::with_name("case-sensitive") + .long("case-sensitive") + .short("s") + .help("Case-sensitive search (default: smart case)")) + .arg(Arg::with_name("absolute-path") + .long("absolute-path") + .short("a") + .help("Show absolute instead of relative paths")) + .arg(Arg::with_name("follow") + .long("follow") + .short("L") + .alias("dereference") + .help("Follow symbolic links")) + .arg(Arg::with_name("full-path") + .long("full-path") + .short("p") + .help("Search full path (default: file-/dirname only)")) + .arg(Arg::with_name("null_separator") + .long("print0") + .short("0") + .help("Separate results by the null character")) + .arg(Arg::with_name("depth") + .long("max-depth") + .short("d") + .takes_value(true) + .help("Set maximum search depth (default: none)")) + .arg(Arg::with_name("file-type") + .long("type") + .short("t") + .takes_value(true) + .possible_values(&["f", "file", "d", "directory", "s", "symlink"]) + .hide_possible_values(true) + .help("Filter by type: f(ile), d(irectory), s(ymlink)")) + .arg(Arg::with_name("extension") + .long("extension") + .short("e") + .takes_value(true) + .value_name("ext") + .help("Filter by file extension")) + .arg(Arg::with_name("color") + .long("color") + .short("c") + .takes_value(true) + .possible_values(&["never", "auto", "always"]) + .hide_possible_values(true) + .help("When to use color in the output:\n\ + never, auto, always (default: auto)")) + .arg(Arg::with_name("threads") + .long("threads") + .short("j") + .takes_value(true) + .help("Set number of threads to use for searching\n\ + (default: number of available CPU cores)")) + .arg(Arg::with_name("max-buffer-time") + .long("max-buffer-time") + .takes_value(true) + .hidden(true) + .help("the time (in ms) to buffer, before streaming to the console")) + .arg(Arg::with_name("pattern") + .help("the search pattern, a regular expression (optional)")) + .arg(Arg::with_name("path") + .help("the root directory for the filesystem search (optional)")) +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 4b260bd..01aeaf1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ extern crate num_cpus; pub mod lscolors; pub mod fshelper; +mod app; use std::borrow::Cow; use std::env; @@ -23,7 +24,6 @@ use std::sync::mpsc::channel; use std::thread; use std::time; -use clap::{App, AppSettings, Arg}; use atty::Stream; use regex::{Regex, RegexBuilder}; use ignore::WalkBuilder; @@ -354,83 +354,7 @@ fn error(message: &str) -> ! { } fn main() { - let matches = - App::new("fd") - .version(crate_version!()) - .usage("fd [FLAGS/OPTIONS] [] []") - .setting(AppSettings::ColoredHelp) - .setting(AppSettings::DeriveDisplayOrder) - .arg(Arg::with_name("hidden") - .long("hidden") - .short("H") - .help("Search hidden files and directories")) - .arg(Arg::with_name("no-ignore") - .long("no-ignore") - .short("I") - .help("Do not respect .(git)ignore files")) - .arg(Arg::with_name("case-sensitive") - .long("case-sensitive") - .short("s") - .help("Case-sensitive search (default: smart case)")) - .arg(Arg::with_name("absolute-path") - .long("absolute-path") - .short("a") - .help("Show absolute instead of relative paths")) - .arg(Arg::with_name("follow") - .long("follow") - .short("L") - .alias("dereference") - .help("Follow symbolic links")) - .arg(Arg::with_name("full-path") - .long("full-path") - .short("p") - .help("Search full path (default: file-/dirname only)")) - .arg(Arg::with_name("null_separator") - .long("print0") - .short("0") - .help("Separate results by the null character")) - .arg(Arg::with_name("depth") - .long("max-depth") - .short("d") - .takes_value(true) - .help("Set maximum search depth (default: none)")) - .arg(Arg::with_name("file-type") - .long("type") - .short("t") - .takes_value(true) - .possible_values(&["f", "file", "d", "directory", "s", "symlink"]) - .hide_possible_values(true) - .help("Filter by type: f(ile), d(irectory), s(ymlink)")) - .arg(Arg::with_name("extension") - .long("extension") - .short("e") - .takes_value(true) - .value_name("ext") - .help("Filter by file extension")) - .arg(Arg::with_name("color") - .long("color") - .short("c") - .takes_value(true) - .possible_values(&["never", "auto", "always"]) - .hide_possible_values(true) - .help("When to use color in the output:\n\ - never, auto, always (default: auto)")) - .arg(Arg::with_name("threads") - .long("threads") - .short("j") - .takes_value(true) - .help("Set number of threads to use for searching\n\ - (default: number of available CPU cores)")) - .arg(Arg::with_name("max-buffer-time") - .long("max-buffer-time") - .takes_value(true) - .hidden(true) - .help("the time (in ms) to buffer, before streaming to the console")) - .arg(Arg::with_name("pattern") - .help("the search pattern, a regular expression (optional)")) - .arg(Arg::with_name("path") - .help("the root directory for the filesystem search (optional)")) - .get_matches(); + let matches = app::build_app().get_matches(); // Get the search pattern let empty_pattern = String::new();