Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option similar to -o, --only-matching #34 #422

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
4 changes: 4 additions & 0 deletions src/app.rs
Expand Up @@ -159,6 +159,7 @@ fn app<F>(next_line_help: bool, doc: F) -> 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 @@ -436,6 +437,9 @@ 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 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 @@ -66,6 +66,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 @@ -161,6 +162,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 @@ -365,6 +367,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