diff --git a/Cargo.toml b/Cargo.toml index 7ac461a..14dec26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ humantime = "2.0" lscolors = "0.7" globset = "0.4" anyhow = "1.0" +dirs = "2.0" [dependencies.clap] version = "2.31.2" diff --git a/README.md b/README.md index b984529..ad7c7bf 100644 --- a/README.md +++ b/README.md @@ -458,6 +458,10 @@ To make exclude-patterns like these permanent, you can create a `.fdignore` file ``` Note: `fd` also supports `.ignore` files that are used by other programs such as `rg` or `ag`. +If you want `fd` to ignore these patterns globally, you can put them in `fd`'s global ignore file. +This is usually located in `~/.config/fd/ignore` in macOS or Linux, and `%APPDATA%\fd\ignore` in +Windows. + ### Using fd with `xargs` or `parallel` If we want to run a command on all search results, we can pipe the output to `xargs`: diff --git a/doc/fd.1 b/doc/fd.1 index 923e5d7..9bc0352 100644 --- a/doc/fd.1 +++ b/doc/fd.1 @@ -33,10 +33,9 @@ Include hidden files and directories in the search results .B \-I, \-\-no\-ignore Show search results from files and directories that would otherwise be ignored by .IR .gitignore , -.I .ignore -or -.I .fdignore -files. +.IR .ignore , +.IR .fdignore , +or the global ignore file. .TP .B \-u, \-\-unrestricted Alias for '--no-ignore'. Can be repeated; '-uu' is an alias for '--no-ignore --hidden'. @@ -282,6 +281,14 @@ The glob syntax is documented here: .B LS_COLORS Determines how to colorize search results, see .BR dircolors (1) . +.TP +.B XDG_CONFIG_HOME, HOME +Used to locate the global ignore file. If +.B XDG_CONFIG_HOME +is set, use +.IR $XDG_CONFIG_HOME/fd/ignore . +Otherwise, use +.IR $HOME/.config/fd/ignore . .SH EXAMPLES .TP .RI "Find files and directories that match the pattern '" needle "':" diff --git a/src/app.rs b/src/app.rs index 6faa2dd..bad5a79 100644 --- a/src/app.rs +++ b/src/app.rs @@ -30,7 +30,7 @@ pub fn build_app() -> App<'static, 'static> { .help("Do not respect .(git|fd)ignore files") .long_help( "Show search results from files and directories that would otherwise be \ - ignored by '.gitignore', '.ignore' or '.fdignore' files.", + ignored by '.gitignore', '.ignore', '.fdignore', or the global ignore file.", ), ) .arg( @@ -43,6 +43,12 @@ pub fn build_app() -> App<'static, 'static> { ignored by '.gitignore' files.", ), ) + .arg( + Arg::with_name("no-global-ignore-file") + .long("no-global-ignore-file") + .hidden(true) + .long_help("Do not respect the global ignore file."), + ) .arg( Arg::with_name("rg-alias-hidden-ignore") .short("u") diff --git a/src/main.rs b/src/main.rs index 96c887f..fa0e462 100644 --- a/src/main.rs +++ b/src/main.rs @@ -294,6 +294,9 @@ fn run() -> Result { read_vcsignore: !(matches.is_present("no-ignore") || matches.is_present("rg-alias-hidden-ignore") || matches.is_present("no-ignore-vcs")), + read_global_ignore: !(matches.is_present("no-ignore") + || matches.is_present("rg-alias-hidden-ignore") + || matches.is_present("no-global-ignore-file")), follow_links: matches.is_present("follow"), one_file_system: matches.is_present("one-file-system"), null_separator: matches.is_present("null_separator"), diff --git a/src/options.rs b/src/options.rs index 19906db..dd11506 100644 --- a/src/options.rs +++ b/src/options.rs @@ -27,6 +27,9 @@ pub struct Options { /// Whether to respect VCS ignore files (`.gitignore`, ..) or not. pub read_vcsignore: bool, + /// Whether to respect the global ignore file or not. + pub read_global_ignore: bool, + /// Whether to follow symlinks or not. pub follow_links: bool, diff --git a/src/walk.rs b/src/walk.rs index 56c0bc0..1082e1c 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::env; use std::ffi::OsStr; use std::fs::{FileType, Metadata}; use std::io; @@ -82,6 +83,34 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc, config: Arc) -> walker.add_custom_ignore_filename(".fdignore"); } + if config.read_global_ignore { + #[cfg(target_os = "macos")] + let config_dir_op = env::var_os("XDG_CONFIG_HOME") + .map(PathBuf::from) + .filter(|p| p.is_absolute()) + .or_else(|| dirs::home_dir().map(|d| d.join(".config"))); + + #[cfg(not(target_os = "macos"))] + let config_dir_op = dirs::config_dir(); + + if let Some(global_ignore_file) = config_dir_op + .map(|p| p.join("fd").join("ignore")) + .filter(|p| p.is_file()) + { + let result = walker.add_ignore(global_ignore_file); + match result { + Some(ignore::Error::Partial(_)) => (), + Some(err) => { + print_error(format!( + "Malformed pattern in global ignore file. {}.", + err.to_string() + )); + } + None => (), + } + } + } + for ignore_file in &config.ignore_files { let result = walker.add_ignore(ignore_file); match result { diff --git a/tests/testenv/mod.rs b/tests/testenv/mod.rs index a4414a8..ae3e08e 100644 --- a/tests/testenv/mod.rs +++ b/tests/testenv/mod.rs @@ -190,7 +190,7 @@ impl TestEnv { // Setup *fd* command. let mut cmd = process::Command::new(&self.fd_exe); cmd.current_dir(self.temp_dir.path().join(path)); - cmd.args(args); + cmd.arg("--no-global-ignore-file").args(args); // Run *fd*. let output = cmd.output().expect("fd output"); @@ -251,7 +251,7 @@ impl TestEnv { // Setup *fd* command. let mut cmd = process::Command::new(&self.fd_exe); cmd.current_dir(self.temp_dir.path().join(path)); - cmd.args(args); + cmd.arg("--no-global-ignore-file").args(args); // Run *fd*. let output = cmd.output().expect("fd output");