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

[WIP] Implement -o, --only-matching. #125

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
10 changes: 9 additions & 1 deletion src/args.rs
Expand Up @@ -165,6 +165,10 @@ Less common options:
a list of matching files such as with --count, --files-with-matches
and --files.

-o, --only-matching
Only print the text that matches the regex, with each match on a
separate line.

-p, --pretty
Alias for --color=always --heading -n.

Expand Down Expand Up @@ -236,6 +240,7 @@ pub struct RawArgs {
flag_no_mmap: bool,
flag_no_filename: bool,
flag_null: bool,
flag_only_matching: bool,
flag_pretty: bool,
flag_quiet: bool,
flag_regexp: Vec<String>,
Expand Down Expand Up @@ -283,6 +288,7 @@ pub struct Args {
no_ignore_parent: bool,
no_ignore_vcs: bool,
null: bool,
only_matching: bool,
quiet: bool,
replace: Option<Vec<u8>>,
text: bool,
Expand Down Expand Up @@ -415,6 +421,7 @@ impl RawArgs {
// --no-ignore implies --no-ignore-vcs
self.flag_no_ignore_vcs || no_ignore,
null: self.flag_null,
only_matching: self.flag_only_matching,
quiet: self.flag_quiet,
replace: self.flag_replace.clone().map(|s| s.into_bytes()),
text: text,
Expand Down Expand Up @@ -570,7 +577,8 @@ impl Args {
.line_per_match(self.line_per_match)
.quiet(self.quiet)
.null(self.null)
.with_filename(self.with_filename);
.with_filename(self.with_filename)
.only_matching(self.only_matching);
if let Some(ref rep) = self.replace {
p = p.replace(rep.clone());
}
Expand Down
17 changes: 17 additions & 0 deletions src/printer.rs
Expand Up @@ -42,6 +42,8 @@ pub struct Printer<W> {
replace: Option<Vec<u8>>,
/// Whether to prefix each match with the corresponding file name.
with_filename: bool,
/// Whether to only print matching text.
only_matching: bool,

/// The choice of Colours
color_choice: ColorChoice
Expand Down Expand Up @@ -90,6 +92,7 @@ impl<W: Terminal + Send> Printer<W> {
null: false,
replace: None,
with_filename: false,
only_matching: false,
color_choice: ColorChoice::new()
}
}
Expand Down Expand Up @@ -163,6 +166,13 @@ impl<W: Terminal + Send> Printer<W> {
self
}

/// When set, only the text that matches the regex is printed, with each match on a
/// separate line.
pub fn only_matching(mut self, yes: bool) -> Printer<W> {
self.only_matching = yes;
self
}

/// Returns true if and only if something has been printed.
pub fn has_printed(&self) -> bool {
self.has_printed
Expand Down Expand Up @@ -242,6 +252,13 @@ impl<W: Terminal + Send> Printer<W> {
end: usize,
line_number: Option<u64>,
) {
if self.only_matching {
for (match_start, match_end) in re.find_iter(&buf[start..end]) {
self.write(&buf[start + match_start..start + match_end]);
self.write_eol();
}
return;
}
if !self.line_per_match {
let column =
if self.column {
Expand Down
14 changes: 14 additions & 0 deletions tests/tests.rs
Expand Up @@ -925,3 +925,17 @@ fn type_list() {
// This can change over time, so just make sure we print something.
assert!(!lines.is_empty());
}

// See: https://github.com/BurntSushi/ripgrep/issues/34
sherlock!(only_matching, r"of \w+", |wd: WorkDir, mut cmd: Command| {
cmd.arg("--only-matching");
let lines: String = wd.stdout(&mut cmd);
let expected = "\
of this
of detective
of luck
of straw
of cigar
";
assert_eq!(lines, expected);
});