From 07443e87ba3fa8b656fffb453f16bb610ff1b3dd Mon Sep 17 00:00:00 2001 From: Benjamin Sago Date: Wed, 27 Sep 2017 13:46:36 +0100 Subject: [PATCH] =?UTF-8?q?Add=20a=20--git-ignore=20option=20that=20doesn?= =?UTF-8?q?=E2=80=99t=20do=20anything?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit !! --- README.md | 1 + contrib/completions.fish | 1 + contrib/completions.zsh | 1 + contrib/man/exa.1 | 5 +++++ src/fs/filter.rs | 20 ++++++++++++++++++++ src/options/filter.rs | 20 ++++++++++++++++++-- src/options/flags.rs | 4 +++- src/options/help.rs | 1 + xtests/help | 1 + 9 files changed, 51 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9304011..9c10705 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ exa’s options are almost, but not quite, entirely unlike `ls`'s. - **-r**, **--reverse**: reverse the sort order - **-s**, **--sort=(field)**: which field to sort by - **--group-directories-first**: list directories before other files +- **--git-ignore**: ignore files mentioned in `.gitignore` - **-I**, **--ignore-glob=(globs)**: glob patterns (pipe-separated) of files to ignore Pass the `--all` option twice to also show the `.` and `..` directories. diff --git a/contrib/completions.fish b/contrib/completions.fish index 8cf43b0..b8bf2e4 100644 --- a/contrib/completions.fish +++ b/contrib/completions.fish @@ -17,6 +17,7 @@ complete -c exa -l 'colour-scale' -d "Highlight levels of file sizes dist # Filtering and sorting options complete -c exa -l 'group-directories-first' -d "Sort directories before other files" +complete -c exa -l 'git-ignore' -d "Ignore files mentioned in '.gitignore'" complete -c exa -s 'a' -l 'all' -d "Show and 'dot' files" complete -c exa -s 'd' -l 'list-dirs' -d "List directories like regular files" complete -c exa -s 'L' -l 'level' -d "Limit the depth of recursion" -a "1 2 3 4 5 6 7 8 9" diff --git a/contrib/completions.zsh b/contrib/completions.zsh index 6536e2c..8fe25e2 100644 --- a/contrib/completions.zsh +++ b/contrib/completions.zsh @@ -14,6 +14,7 @@ __exa() { {--color,--colour}"[When to use terminal colours]" \ {--color,--colour}-scale"[Highlight levels of file sizes distinctly]" \ --group-directories-first"[Sort directories before other files]" \ + --git-ignore"[Ignore files mentioned in '.gitignore']" \ {-a,--all}"[Show hidden and 'dot' files]" \ {-d,--list-dirs}"[List directories like regular files]" \ {-L,--level}"+[Limit the depth of recursion]" \ diff --git a/contrib/man/exa.1 b/contrib/man/exa.1 index dadb6c4..f14522e 100644 --- a/contrib/man/exa.1 +++ b/contrib/man/exa.1 @@ -88,6 +88,11 @@ Glob patterns, pipe-separated, of files to ignore .RS .RE .TP +.B \-\-git\-ignore +ignore files mentioned in '.gitignore' +.RS +.RE +.TP .B \-\-group\-directories\-first list directories before other files .RS diff --git a/src/fs/filter.rs b/src/fs/filter.rs index 12d54aa..e4092c5 100644 --- a/src/fs/filter.rs +++ b/src/fs/filter.rs @@ -305,6 +305,26 @@ impl IgnorePatterns { } +/// Whether to ignore or display files that are mentioned in `.gitignore` files. +#[derive(PartialEq, Debug, Copy, Clone)] +pub enum GitIgnore { + + /// Ignore files that Git would ignore. This means doing a check for a + /// `.gitignore` file, possibly recursively up the filesystem tree. + CheckAndIgnore, + + /// Display files, even if Git would ignore them. + Off, +} + +// This is not fully baked yet. The `ignore` crate lists a lot more files that +// we aren’t checking: +// +// > By default, all ignore files found are respected. This includes .ignore, +// > .gitignore, .git/info/exclude and even your global gitignore globs, +// > usually found in $XDG_CONFIG_HOME/git/ignore. + + #[cfg(test)] mod test_ignores { diff --git a/src/options/filter.rs b/src/options/filter.rs index 6ed2a4e..c3e961f 100644 --- a/src/options/filter.rs +++ b/src/options/filter.rs @@ -1,7 +1,7 @@ //! Parsing the options for `FileFilter`. use fs::DotFilter; -use fs::filter::{FileFilter, SortField, SortCase, IgnorePatterns}; +use fs::filter::{FileFilter, SortField, SortCase, IgnorePatterns, GitIgnore}; use options::{flags, Misfire}; use options::parser::MatchedFlags; @@ -180,6 +180,14 @@ impl IgnorePatterns { } +impl GitIgnore { + pub fn deduce(matches: &MatchedFlags) -> Result { + Ok(if matches.has(&flags::GIT_IGNORE)? { GitIgnore::CheckAndIgnore } + else { GitIgnore::Off }) + } +} + + #[cfg(test)] mod test { @@ -196,7 +204,7 @@ mod test { use options::test::parse_for_test; use options::test::Strictnesses::*; - static TEST_ARGS: &[&Arg] = &[ &flags::SORT, &flags::ALL, &flags::TREE, &flags::IGNORE_GLOB ]; + static TEST_ARGS: &[&Arg] = &[ &flags::SORT, &flags::ALL, &flags::TREE, &flags::IGNORE_GLOB, &flags::GIT_IGNORE ]; for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) { assert_eq!(result, $result); } @@ -275,4 +283,12 @@ mod test { test!(overridden_3: IgnorePatterns <- ["-I=*.ogg", "-I", "*.mp3"]; Complain => Err(Misfire::Duplicate(Flag::Short(b'I'), Flag::Short(b'I')))); test!(overridden_4: IgnorePatterns <- ["-I", "*.OGG", "-I*.MP3"]; Complain => Err(Misfire::Duplicate(Flag::Short(b'I'), Flag::Short(b'I')))); } + + + mod git_ignores { + use super::*; + + test!(off: GitIgnore <- []; Both => Ok(GitIgnore::Off)); + test!(on: GitIgnore <- ["--git-ignore"]; Both => Ok(GitIgnore::CheckAndIgnore)); + } } diff --git a/src/options/flags.rs b/src/options/flags.rs index 3f8eb20..46ecbfd 100644 --- a/src/options/flags.rs +++ b/src/options/flags.rs @@ -28,6 +28,7 @@ pub static LEVEL: Arg = Arg { short: Some(b'L'), long: "level", take pub static REVERSE: Arg = Arg { short: Some(b'r'), long: "reverse", takes_value: TakesValue::Forbidden }; pub static SORT: Arg = Arg { short: Some(b's'), long: "sort", takes_value: TakesValue::Necessary(Some(SORTS)) }; pub static IGNORE_GLOB: Arg = Arg { short: Some(b'I'), long: "ignore-glob", takes_value: TakesValue::Necessary(None) }; +pub static GIT_IGNORE: Arg = Arg { short: None, long: "git-ignore", takes_value: TakesValue::Forbidden }; pub static DIRS_FIRST: Arg = Arg { short: None, long: "group-directories-first", takes_value: TakesValue::Forbidden }; const SORTS: Values = &[ "name", "Name", "size", "extension", "Extension", "modified", "accessed", @@ -60,7 +61,8 @@ pub static ALL_ARGS: Args = Args(&[ &ONE_LINE, &LONG, &GRID, &ACROSS, &RECURSE, &TREE, &CLASSIFY, &COLOR, &COLOUR, &COLOR_SCALE, &COLOUR_SCALE, - &ALL, &LIST_DIRS, &LEVEL, &REVERSE, &SORT, &IGNORE_GLOB, &DIRS_FIRST, + &ALL, &LIST_DIRS, &LEVEL, &REVERSE, &SORT, &DIRS_FIRST, + &IGNORE_GLOB, &GIT_IGNORE, &BINARY, &BYTES, &GROUP, &HEADER, &INODE, &LINKS, &MODIFIED, &BLOCKS, &TIME, &ACCESSED, &CREATED, &TIME_STYLE, diff --git a/src/options/help.rs b/src/options/help.rs index e71492c..5428c4b 100644 --- a/src/options/help.rs +++ b/src/options/help.rs @@ -27,6 +27,7 @@ FILTERING AND SORTING OPTIONS -s, --sort SORT_FIELD which field to sort by --group-directories-first list directories before other files -I, --ignore-glob GLOBS glob patterns (pipe-separated) of files to ignore + --git-ignore Ignore files mentioned in '.gitignore' Valid sort fields: name, Name, extension, Extension, size, type, modified, accessed, created, inode, and none. date, time, old, and new all refer to modified. diff --git a/xtests/help b/xtests/help index 50eb989..2a29bd6 100644 --- a/xtests/help +++ b/xtests/help @@ -22,6 +22,7 @@ FILTERING AND SORTING OPTIONS -s, --sort SORT_FIELD which field to sort by --group-directories-first list directories before other files -I, --ignore-glob GLOBS glob patterns (pipe-separated) of files to ignore + --git-ignore Ignore files mentioned in '.gitignore' Valid sort fields: name, Name, extension, Extension, size, type, modified, accessed, created, inode, and none. date, time, old, and new all refer to modified.