Use clap to generate shell completions

This commit is contained in:
Florian Hofmair 2017-10-04 14:31:08 +02:00 committed by David Peter
parent 083b1cfd9b
commit 396b9baaa5
4 changed files with 104 additions and 78 deletions

View File

@ -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"

19
build.rs Normal file
View File

@ -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);
}

79
src/app.rs Normal file
View File

@ -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] [<pattern>] [<path>]")
.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)"))
}

View File

@ -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] [<pattern>] [<path>]")
.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();