diff --git a/src/app.rs b/src/app.rs index 32164c0..b136592 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,110 +1,150 @@ +use std::collections::HashMap; + use clap::{App, AppSettings, Arg}; +struct Help { + short: &'static str, + long: &'static str, +} + +macro_rules! doc { + ($map:expr, $name:expr, $short:expr) => { + doc!($map, $name, $short, $short) + }; + ($map:expr, $name:expr, $short:expr, $long:expr) => { + $map.insert($name, Help { + short: $short, + long: concat!($long, "\n ") + }); + }; +} + pub fn build_app() -> App<'static, 'static> { + let helps = usage(); + let arg = |name| { + Arg::with_name(name).help(helps[name].short).long_help( + helps[name].long, + ) + }; + App::new("fd") .version(crate_version!()) .usage("fd [FLAGS/OPTIONS] [] []") .setting(AppSettings::ColoredHelp) .setting(AppSettings::DeriveDisplayOrder) + .arg(arg("hidden").long("hidden").short("H")) + .arg(arg("no-ignore").long("no-ignore").short("I")) + .arg(arg("case-sensitive").long("case-sensitive").short("s")) + .arg(arg("absolute-path").long("absolute-path").short("a")) + .arg(arg("follow").long("follow").short("L").alias("dereference")) + .arg(arg("full-path").long("full-path").short("p")) + .arg(arg("null_separator").long("print0").short("0")) + .arg(arg("depth").long("max-depth").short("d").takes_value(true)) .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") + arg("file-type") .long("type") .short("t") .takes_value(true) .value_name("filetype") .possible_values(&["f", "file", "d", "directory", "s", "symlink"]) - .hide_possible_values(true) - .help("Filter by type: f(ile), d(irectory), s(ymlink)"), + .hide_possible_values(true), ) .arg( - Arg::with_name("extension") + arg("extension") .long("extension") .short("e") .takes_value(true) - .value_name("ext") - .help("Filter by file extension"), + .value_name("ext"), ) .arg( - Arg::with_name("color") + arg("color") .long("color") .short("c") .takes_value(true) .value_name("when") .possible_values(&["never", "auto", "always"]) - .hide_possible_values(true) - .help( - "When to use color in the output:\n\ - never, auto, always (default: auto)", - ), + .hide_possible_values(true), ) .arg( - Arg::with_name("threads") + arg("threads") .long("threads") .short("j") .takes_value(true) - .value_name("num") - .help( - "Set number of threads to use for searching\n\ - (default: number of available CPU cores)", - ), + .value_name("num"), ) .arg( - Arg::with_name("max-buffer-time") + arg("max-buffer-time") .long("max-buffer-time") .takes_value(true) - .hidden(true) - .help("the time (in ms) to buffer, before streaming to the console"), + .hidden(true), ) - .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)")) + .arg(arg("pattern")) + .arg(arg("path")) +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn usage() -> HashMap<&'static str, Help> { + let mut h = HashMap::new(); + doc!(h, "hidden" + , "Search hidden files and directories" + , "Also include hidden directories and files in the search results (default: hidden files\ + and directories are skipped)."); + doc!(h, "no-ignore" + , "Do not respect .(git)ignore files" + , "Show search results from files and directories that would otherwise be ignored by\ + '.*ignore' files."); + doc!(h, "case-sensitive" + , "Case-sensitive search (default: smart case)" + , "Define your pattern as case sensitive. By default, fd uses 'smart case' for queries.\ + This option disables smart case."); + doc!(h, "absolute-path" + , "Show absolute instead of relative paths" + , "Shows the result of a pattern match as an absolute path instead of relative path."); + doc!(h, "follow" + , "Follow symbolic links" + , "By default, fd does not descent into symlinked directories. Using this flag, symbolic \ + links are also traversed."); + doc!(h, "full-path" + , "Search full path (default: file-/dirname only)" + , "Searches the full path of directory. By default, fd only searches the last part of \ + the path (the file name or the directory name)."); + doc!(h, "null_separator" + , "Separate results by the null character" + , "Separate search results by the null character (instead of newlines). This is useful \ + for piping results to 'xargs'."); + doc!(h, "depth" + , "Set maximum search depth (default: none)" + , "Set the limit of the maximum search depth in a pattern match query. By default, there\ + is no limit on the search depth."); + doc!(h, "file-type" + , "Filter by type: f(ile), d(irectory), s(ymlink)" + , "Filter the search by type:\n\ + f file for file\n\ + d directory for directory\n\ + s symlink for symbolic links"); + doc!(h, "extension" + , "Filter by file extension" + , "Only show search results with a specific file extension."); + doc!(h, "color" + , "When to use color in the output:\n\ + never, auto, always (default: auto)" + , "Declare when to use color for the pattern match output:\n\ + auto (default)\n\ + never\n\ + always"); + doc!(h, "threads" + , "Set number of threads to use for searching:\n\ + (default: number of available CPU cores)"); + doc!(h, "max-buffer-time" + , "the time (in ms) to buffer, before streaming to the console" + , "Amount of time in milliseconds to buffer, before streaming the search results to\ + the console."); + doc!(h, "pattern" + , "the search pattern, a regular expression (optional)"); + doc!(h, "path" + , "the root directory for the filesystem search (optional)" + , "The root directory where you want to do the filesystem search of the pattern.\ + When not present, the default is to use the current working directory."); + + h }