Skip to content

Commit

Permalink
Add -o/--only-matching flag.
Browse files Browse the repository at this point in the history
Currently, the `--only-matching` flag conflicts with the `--replace`
flag. In the future, this restriction may be relaxed.

Fixes #34
  • Loading branch information
kpp authored and BurntSushi committed Apr 9, 2017
1 parent 9456d95 commit 90a11de
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 2 deletions.
4 changes: 4 additions & 0 deletions doc/rg.1.md
Expand Up @@ -249,6 +249,10 @@ Project home page: https://github.com/BurntSushi/ripgrep
a list of matching files such as with --count, --files-with-matches
and --files.

-o, --only-matching
: Print only the matched (non-empty) parts of a matching line, with each such
part on a separate output line.

--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
Expand Down
5 changes: 5 additions & 0 deletions src/app.rs
Expand Up @@ -144,6 +144,7 @@ pub fn app() -> App<'static, 'static> {
.arg(flag("no-ignore-parent"))
.arg(flag("no-ignore-vcs"))
.arg(flag("null").short("0"))
.arg(flag("only-matching").short("o").conflicts_with("replace"))
.arg(flag("path-separator").value_name("SEPARATOR").takes_value(true))
.arg(flag("pretty").short("p"))
.arg(flag("replace").short("r").value_name("ARG").takes_value(true))
Expand Down Expand Up @@ -421,6 +422,10 @@ lazy_static! {
printing a list of matching files such as with --count, \
--files-with-matches and --files. This option is useful for use \
with xargs.");
doc!(h, "only-matching",
"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, "path-separator",
"Path separator to use when printing file paths.",
"The path separator to use when printing file paths. This \
Expand Down
3 changes: 3 additions & 0 deletions src/args.rs
Expand Up @@ -65,6 +65,7 @@ pub struct Args {
no_ignore_vcs: bool,
no_messages: bool,
null: bool,
only_matching: bool,
path_separator: Option<u8>,
quiet: bool,
quiet_matched: QuietMatched,
Expand Down Expand Up @@ -141,6 +142,7 @@ impl Args {
.heading(self.heading)
.line_per_match(self.line_per_match)
.null(self.null)
.only_matching(self.only_matching)
.path_separator(self.path_separator)
.with_filename(self.with_filename)
.max_columns(self.max_columns);
Expand Down Expand Up @@ -345,6 +347,7 @@ impl<'a> ArgMatches<'a> {
no_ignore_vcs: self.no_ignore_vcs(),
no_messages: self.is_present("no-messages"),
null: self.is_present("null"),
only_matching: self.is_present("only-matching"),
path_separator: try!(self.path_separator()),
quiet: quiet,
quiet_matched: QuietMatched::new(quiet),
Expand Down
19 changes: 17 additions & 2 deletions src/printer.rs
Expand Up @@ -58,6 +58,8 @@ pub struct Printer<W> {
/// Whether to print NUL bytes after a file path instead of new lines
/// or `:`.
null: bool,
/// Print only the matched (non-empty) parts of a matching line
only_matching: bool,
/// A string to use as a replacement of each match in a matching line.
replace: Option<Vec<u8>>,
/// Whether to prefix each match with the corresponding file name.
Expand All @@ -83,6 +85,7 @@ impl<W: WriteColor> Printer<W> {
heading: false,
line_per_match: false,
null: false,
only_matching: false,
replace: None,
with_filename: false,
colors: ColorSpecs::default(),
Expand Down Expand Up @@ -144,6 +147,12 @@ impl<W: WriteColor> Printer<W> {
self
}

/// Print only the matched (non-empty) parts of a matching line
pub fn only_matching(mut self, yes: bool) -> Printer<W> {
self.only_matching = yes;
self
}

/// A separator to use when printing file paths. When empty, use the
/// default separator for the current platform. (/ on Unix, \ on Windows.)
pub fn path_separator(mut self, sep: Option<u8>) -> Printer<W> {
Expand Down Expand Up @@ -232,7 +241,7 @@ impl<W: WriteColor> Printer<W> {
end: usize,
line_number: Option<u64>,
) {
if !self.line_per_match {
if !self.line_per_match && !self.only_matching {
let column =
if self.column {
Some(re.find(&buf[start..end])
Expand Down Expand Up @@ -298,7 +307,13 @@ impl<W: WriteColor> Printer<W> {
self.write_eol();
}
} else {
self.write_matched_line(re, &buf[start..end]);
let line_buf = if self.only_matching {
let m = re.find(&buf[start..end]).unwrap();
&buf[start + m.start()..start + m.end()]
} else {
&buf[start..end]
};
self.write_matched_line(re, line_buf);
// write_matched_line guarantees to write a newline.
}
}
Expand Down
26 changes: 26 additions & 0 deletions tests/tests.rs
Expand Up @@ -1166,6 +1166,32 @@ be, to a very large extent, the result of luck. Sherlock Holmes
assert_eq!(lines, expected);
});

// See: https://github.com/BurntSushi/ripgrep/issues/34
sherlock!(feature_34_only_matching, "Sherlock", ".",
|wd: WorkDir, mut cmd: Command| {
cmd.arg("--only-matching");

let lines: String = wd.stdout(&mut cmd);
let expected = "\
sherlock:Sherlock
sherlock:Sherlock
";
assert_eq!(lines, expected);
});

// See: https://github.com/BurntSushi/ripgrep/issues/34
sherlock!(feature_34_only_matching_line_column, "Sherlock", ".",
|wd: WorkDir, mut cmd: Command| {
cmd.arg("--only-matching").arg("--column").arg("--line-number");

let lines: String = wd.stdout(&mut cmd);
let expected = "\
sherlock:1:57:Sherlock
sherlock:3:49:Sherlock
";
assert_eq!(lines, expected);
});

// See: https://github.com/BurntSushi/ripgrep/issues/45
sherlock!(feature_45_relative_cwd, "test", ".",
|wd: WorkDir, mut cmd: Command| {
Expand Down

0 comments on commit 90a11de

Please sign in to comment.