diff options
author | dana <dana@dana.is> | 2018-01-11 17:45:51 -0600 |
---|---|---|
committer | Andrew Gallant <jamslam@gmail.com> | 2018-01-11 18:45:51 -0500 |
commit | 58bdc366ec292653124699940190432ae30a6732 (patch) | |
tree | b9f57e7d3502bf23452a0c0445edd593c628f402 | |
parent | 34c0b1bc709f74678d7c1a24046c26571c25eaec (diff) |
printer: add --passthru flag
The --passthru flag causes ripgrep to print every line,
even if the line does not contain a match. This is a
response to the common pattern of `^|foo` to match every
line, while still highlighting things like `foo`.
Fixes #740
-rw-r--r-- | complete/_rg | 8 | ||||
-rw-r--r-- | doc/rg.1 | 8 | ||||
-rw-r--r-- | doc/rg.1.md | 4 | ||||
-rw-r--r-- | src/app.rs | 4 | ||||
-rw-r--r-- | src/args.rs | 10 | ||||
-rw-r--r-- | tests/tests.rs | 55 |
6 files changed, 84 insertions, 5 deletions
diff --git a/complete/_rg b/complete/_rg index 93ab4ae8..8455c804 100644 --- a/complete/_rg +++ b/complete/_rg @@ -26,7 +26,7 @@ _rg() { '--column[show column numbers]' '(-A -B -C --after-context --before-context --context)'{-C+,--context=}'[specify lines to show before and after each match]:number of lines' '--context-separator=[specify string used to separate non-continuous context lines in output]:separator' - '(-c --count)'{-c,--count}'[only show count of matches for each file]' + '(-c --count --passthrough --passthru)'{-c,--count}'[only show count of matches for each file]' '--debug[show debug messages]' '--dfa-size-limit=[specify upper size limit of generated DFA]:DFA size' '(-E --encoding)'{-E+,--encoding=}'[specify text encoding of files to search]: :_rg_encodings' @@ -61,13 +61,15 @@ _rg() { '--no-messages[suppress all error messages]' "(--mmap --no-mmap)--no-mmap[don't search using memory maps]" '(-0 --null)'{-0,--null}'[print NUL byte after file names]' - '(-o --only-matching -r --replace)'{-o,--only-matching}'[show only matching part of each line]' + '(-o -r --only-matching --passthrough --passthru --replace)'{-o,--only-matching}'[show only matching part of each line]' + '(-c -o -r --count --only-matching --passthrough --replace)--passthru[show both matching and non-matching lines]' + '!(-c -o -r --count --only-matching --passthru --replace)--passthrough' '--path-separator=[specify path separator to use when printing file names]:separator' '(-p --heading --no-heading --pretty --vimgrep)'{-p,--pretty}'[alias for --color=always --heading -n]' '(-q --quiet)'{-q,--quiet}'[suppress normal output]' '--regex-size-limit=[specify upper size limit of compiled regex]:regex size' '(1 -f --file)*'{-e+,--regexp=}'[specify pattern]:pattern' - '(-o --only-matching -r --replace)'{-r+,--replace=}'[specify string used to replace matches]:replace string' + '(-c -o -r --count --only-matching --passthrough --passthru --replace)'{-r+,--replace=}'[specify string used to replace matches]:replace string' '(-i -s -S --ignore-case --case-sensitive --smart-case)'{-S,--smart-case}'[search case-insensitively if the pattern is all lowercase]' '(-j --threads)--sort-files[sort results by file path (disables parallelism)]' '(-a --text)'{-a,--text}'[search binary files as if they were text]' @@ -435,6 +435,14 @@ such part on a separate output line. .RS .RE .TP +.B \-\-passthru, \-\-passthrough +Show both matching and non\-matching lines. +This is equivalent to adding ^ to the list of search patterns. +This option overrides \-\-count and cannot be used with +\-\-only\-matching or \-\-replace. +.RS +.RE +.TP .B \-\-path\-separator \f[I]SEPARATOR\f[] The path separator to use when printing file paths. This defaults to your platform\[aq]s path separator, which is / on Unix diff --git a/doc/rg.1.md b/doc/rg.1.md index 2cd7059e..93b401ab 100644 --- a/doc/rg.1.md +++ b/doc/rg.1.md @@ -288,6 +288,10 @@ Project home page: https://github.com/BurntSushi/ripgrep : Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line. +--passthru, --passthrough +: Show both matching and non-matching lines. This option cannot be used with + --only-matching or --replace. + --path-separator *SEPARATOR* : The path separator to use when printing file paths. This defaults to your platform's path separator, which is / on Unix and \\ on Windows. This flag is @@ -166,6 +166,8 @@ pub fn app() -> App<'static, 'static> { .arg(flag("no-ignore-vcs")) .arg(flag("null").short("0")) .arg(flag("only-matching").short("o")) + .arg(flag("passthru").alias("passthrough") + .conflicts_with_all(&["only-matching", "replace"])) .arg(flag("path-separator").value_name("SEPARATOR").takes_value(true)) .arg(flag("pretty").short("p")) .arg(flag("replace").short("r") @@ -499,6 +501,8 @@ lazy_static! { "Print only matched parts of a line.", "Print only the matched (non-empty) parts of a matching line, \ with each such part on a separate output line."); + doc!(h, "passthru", + "Show both matching and non-matching lines."); doc!(h, "path-separator", "Path separator to use when printing file paths.", "The path separator to use when printing file paths. This \ diff --git a/src/args.rs b/src/args.rs index 6affa2dd..d2d0232b 100644 --- a/src/args.rs +++ b/src/args.rs @@ -433,7 +433,9 @@ impl<'a> ArgMatches<'a> { /// Note that if -F/--fixed-strings is set, then all patterns will be /// escaped. Similarly, if -w/--word-regexp is set, then all patterns /// are surrounded by `\b`, and if -x/--line-regexp is set, then all - /// patterns are surrounded by `^...$`. + /// patterns are surrounded by `^...$`. Finally, if --passthru is set, + /// the pattern `^` is added to the end (to ensure that it works as + /// expected with multiple -e/-f patterns). /// /// If any pattern is invalid UTF-8, then an error is returned. fn patterns(&self) -> Result<Vec<String>> { @@ -470,7 +472,11 @@ impl<'a> ArgMatches<'a> { } } } - if pats.is_empty() { + // It's important that this be at the end; otherwise it would always + // match first, and we wouldn't get colours in the output + if self.is_present("passthru") && !self.is_present("count") { + pats.push("^".to_string()) + } else if pats.is_empty() { pats.push(self.empty_pattern()) } Ok(pats) diff --git a/tests/tests.rs b/tests/tests.rs index 4bd852cd..646b02fa 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1610,6 +1610,61 @@ clean!(suggest_fixed_strings_for_invalid_regex, "foo(", ".", }); #[test] +fn feature_740_passthru() { + let wd = WorkDir::new("feature_740"); + wd.create("file", "\nfoo\nbar\nfoobar\n\nbaz\n"); + wd.create("patterns", "foo\n\nbar\n"); + + // We can't assume that the way colour specs are translated to ANSI + // sequences will remain stable, and --replace doesn't currently work with + // pass-through, so for now we don't actually test the match sub-strings + let common_args = &["-n", "--passthru"]; + let expected = "\ +1: +2:foo +3:bar +4:foobar +5: +6:baz +"; + + // With single pattern + let mut cmd = wd.command(); + cmd.args(common_args).arg("foo").arg("file"); + let lines: String = wd.stdout(&mut cmd); + assert_eq!(lines, expected); + + // With multiple -e patterns + let mut cmd = wd.command(); + cmd.args(common_args) + .arg("-e").arg("foo").arg("-e").arg("bar").arg("file"); + let lines: String = wd.stdout(&mut cmd); + assert_eq!(lines, expected); + + // With multiple -f patterns + let mut cmd = wd.command(); + cmd.args(common_args).arg("-f").arg("patterns").arg("file"); + let lines: String = wd.stdout(&mut cmd); + assert_eq!(lines, expected); + + // -c should override + let mut cmd = wd.command(); + cmd.args(common_args).arg("-c").arg("foo").arg("file"); + let lines: String = wd.stdout(&mut cmd); + assert_eq!(lines, "2\n"); + + // -o should conflict + let mut cmd = wd.command(); + cmd.args(common_args).arg("-o").arg("foo").arg("file"); + wd.assert_err(&mut cmd); + + // -r should conflict + let mut cmd = wd.command(); + cmd.args(common_args).arg("-r").arg("$0").arg("foo").arg("file"); + wd.assert_err(&mut cmd); +} + +#[test] fn binary_nosearch() { let wd = WorkDir::new("binary_nosearch"); wd.create("file", "foo\x00bar\nfoo\x00baz\n"); |