summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordana <dana@dana.is>2018-01-11 17:45:51 -0600
committerAndrew Gallant <jamslam@gmail.com>2018-01-11 18:45:51 -0500
commit58bdc366ec292653124699940190432ae30a6732 (patch)
treeb9f57e7d3502bf23452a0c0445edd593c628f402
parent34c0b1bc709f74678d7c1a24046c26571c25eaec (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/_rg8
-rw-r--r--doc/rg.18
-rw-r--r--doc/rg.1.md4
-rw-r--r--src/app.rs4
-rw-r--r--src/args.rs10
-rw-r--r--tests/tests.rs55
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]'
diff --git a/doc/rg.1 b/doc/rg.1
index c098410b..d8272e74 100644
--- a/doc/rg.1
+++ b/doc/rg.1
@@ -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
diff --git a/src/app.rs b/src/app.rs
index bcc91f8c..6bf2744e 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -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");