summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/args.rs8
-rw-r--r--src/main.rs47
-rw-r--r--src/printer.rs27
-rw-r--r--src/search_buffer.rs9
-rw-r--r--src/search_stream.rs24
5 files changed, 82 insertions, 33 deletions
diff --git a/src/args.rs b/src/args.rs
index 5cfb14ad..73675ff4 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -571,6 +571,11 @@ impl Args {
self.mmap
}
+ /// Whether ripgrep should be quiet or not.
+ pub fn quiet(&self) -> bool {
+ self.quiet
+ }
+
/// Create a new printer of individual search results that writes to the
/// writer given.
pub fn printer<W: Terminal + Send>(&self, wtr: W) -> Printer<W> {
@@ -580,7 +585,6 @@ impl Args {
.eol(self.eol)
.heading(self.heading)
.line_per_match(self.line_per_match)
- .quiet(self.quiet)
.null(self.null)
.with_filename(self.with_filename);
if let Some(ref rep) = self.replace {
@@ -660,6 +664,7 @@ impl Args {
.eol(self.eol)
.line_number(self.line_number)
.invert_match(self.invert_match)
+ .quiet(self.quiet)
.text(self.text)
}
@@ -679,6 +684,7 @@ impl Args {
.eol(self.eol)
.line_number(self.line_number)
.invert_match(self.invert_match)
+ .quiet(self.quiet)
.text(self.text)
}
diff --git a/src/main.rs b/src/main.rs
index b095f009..5f8b3dfe 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -27,6 +27,7 @@ use std::path::Path;
use std::process;
use std::result;
use std::sync::{Arc, Mutex};
+use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::cmp;
@@ -102,6 +103,7 @@ fn run(args: Args) -> Result<u64> {
}
let out = Arc::new(Mutex::new(args.out()));
+ let quiet_matched = QuietMatched::new(args.quiet());
let mut workers = vec![];
let workq = {
@@ -109,6 +111,7 @@ fn run(args: Args) -> Result<u64> {
for _ in 0..threads {
let worker = MultiWorker {
chan_work: stealer.clone(),
+ quiet_matched: quiet_matched.clone(),
out: out.clone(),
outbuf: Some(args.outbuf()),
worker: Worker {
@@ -124,11 +127,17 @@ fn run(args: Args) -> Result<u64> {
};
let mut paths_searched: u64 = 0;
for p in paths {
+ if quiet_matched.has_match() {
+ break;
+ }
if p == Path::new("-") {
paths_searched += 1;
workq.push(Work::Stdin);
} else {
for ent in try!(args.walker(p)) {
+ if quiet_matched.has_match() {
+ break;
+ }
paths_searched += 1;
workq.push(Work::File(ent));
}
@@ -161,6 +170,9 @@ fn run_one_thread(args: Arc<Args>) -> Result<u64> {
let mut paths_searched: u64 = 0;
for p in paths {
+ if args.quiet() && worker.match_count > 0 {
+ break;
+ }
if p == Path::new("-") {
paths_searched += 1;
let mut printer = args.printer(&mut term);
@@ -175,6 +187,9 @@ fn run_one_thread(args: Arc<Args>) -> Result<u64> {
paths_searched += 1;
let mut printer = args.printer(&mut term);
if worker.match_count > 0 {
+ if args.quiet() {
+ break;
+ }
if let Some(sep) = args.file_separator() {
printer = printer.file_separator(sep);
}
@@ -240,6 +255,7 @@ enum WorkReady {
struct MultiWorker {
chan_work: Stealer<Work>,
+ quiet_matched: QuietMatched,
out: Arc<Mutex<Out>>,
#[cfg(not(windows))]
outbuf: Option<ColoredTerminal<term::TerminfoTerminal<Vec<u8>>>>,
@@ -258,6 +274,9 @@ struct Worker {
impl MultiWorker {
fn run(mut self) -> u64 {
loop {
+ if self.quiet_matched.has_match() {
+ break;
+ }
let work = match self.chan_work.steal() {
Stolen::Empty | Stolen::Abort => continue,
Stolen::Data(Work::Quit) => break,
@@ -276,6 +295,9 @@ impl MultiWorker {
outbuf.clear();
let mut printer = self.worker.args.printer(outbuf);
self.worker.do_work(&mut printer, work);
+ if self.quiet_matched.set_match(self.worker.match_count > 0) {
+ break;
+ }
let outbuf = printer.into_inner();
if !outbuf.get_ref().is_empty() {
let mut out = self.out.lock().unwrap();
@@ -359,3 +381,28 @@ impl Worker {
).run())
}
}
+
+#[derive(Clone, Debug)]
+struct QuietMatched(Arc<Option<AtomicBool>>);
+
+impl QuietMatched {
+ fn new(quiet: bool) -> QuietMatched {
+ let atomic = if quiet { Some(AtomicBool::new(false)) } else { None };
+ QuietMatched(Arc::new(atomic))
+ }
+
+ fn has_match(&self) -> bool {
+ match *self.0 {
+ None => false,
+ Some(ref matched) => matched.load(Ordering::SeqCst),
+ }
+ }
+
+ fn set_match(&self, yes: bool) -> bool {
+ match *self.0 {
+ None => false,
+ Some(_) if !yes => false,
+ Some(ref m) => { m.store(true, Ordering::SeqCst); true }
+ }
+ }
+}
diff --git a/src/printer.rs b/src/printer.rs
index 11848830..9a5c649d 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -33,8 +33,6 @@ pub struct Printer<W> {
heading: bool,
/// Whether to show every match on its own line.
line_per_match: bool,
- /// Whether to suppress all output.
- quiet: bool,
/// Whether to print NUL bytes after a file path instead of new lines
/// or `:`.
null: bool,
@@ -42,8 +40,7 @@ pub struct Printer<W> {
replace: Option<Vec<u8>>,
/// Whether to prefix each match with the corresponding file name.
with_filename: bool,
-
- /// The choice of Colours
+ /// The choice of colors.
color_choice: ColorChoice
}
@@ -54,7 +51,6 @@ struct ColorChoice {
}
impl ColorChoice {
-
#[cfg(unix)]
pub fn new() -> ColorChoice {
ColorChoice {
@@ -86,7 +82,6 @@ impl<W: Terminal + Send> Printer<W> {
file_separator: None,
heading: false,
line_per_match: false,
- quiet: false,
null: false,
replace: None,
with_filename: false,
@@ -141,12 +136,6 @@ impl<W: Terminal + Send> Printer<W> {
self
}
- /// When set, all output is suppressed.
- pub fn quiet(mut self, yes: bool) -> Printer<W> {
- self.quiet = yes;
- self
- }
-
/// Replace every match in each matching line with the replacement string
/// given.
///
@@ -168,11 +157,6 @@ impl<W: Terminal + Send> Printer<W> {
self.has_printed
}
- /// Returns true if the printer has been configured to be quiet.
- pub fn is_quiet(&self) -> bool {
- self.quiet
- }
-
/// Flushes the underlying writer and returns it.
pub fn into_inner(mut self) -> W {
let _ = self.wtr.flush();
@@ -222,9 +206,6 @@ impl<W: Terminal + Send> Printer<W> {
/// Prints the context separator.
pub fn context_separate(&mut self) {
// N.B. We can't use `write` here because of borrowing restrictions.
- if self.quiet {
- return;
- }
if self.context_separator.is_empty() {
return;
}
@@ -398,9 +379,6 @@ impl<W: Terminal + Send> Printer<W> {
}
fn write(&mut self, buf: &[u8]) {
- if self.quiet {
- return;
- }
self.has_printed = true;
let _ = self.wtr.write_all(buf);
}
@@ -411,9 +389,6 @@ impl<W: Terminal + Send> Printer<W> {
}
fn write_file_sep(&mut self) {
- if self.quiet {
- return;
- }
if let Some(ref sep) = self.file_separator {
self.has_printed = true;
let _ = self.wtr.write_all(sep);
diff --git a/src/search_buffer.rs b/src/search_buffer.rs
index efc66cd7..6a32a631 100644
--- a/src/search_buffer.rs
+++ b/src/search_buffer.rs
@@ -81,6 +81,13 @@ impl<'a, W: Send + Terminal> BufferSearcher<'a, W> {
self
}
+ /// If enabled, don't show any output and quit searching after the first
+ /// match is found.
+ pub fn quiet(mut self, yes: bool) -> Self {
+ self.opts.quiet = yes;
+ self
+ }
+
/// If enabled, search binary files as if they were text.
pub fn text(mut self, yes: bool) -> Self {
self.opts.text = yes;
@@ -104,7 +111,7 @@ impl<'a, W: Send + Terminal> BufferSearcher<'a, W> {
self.print_match(m.start(), m.end());
}
last_end = m.end();
- if self.printer.is_quiet() || self.opts.files_with_matches {
+ if self.opts.stop_after_first_match() {
break;
}
}
diff --git a/src/search_stream.rs b/src/search_stream.rs
index 3407366e..8f458ca5 100644
--- a/src/search_stream.rs
+++ b/src/search_stream.rs
@@ -84,6 +84,7 @@ pub struct Options {
pub eol: u8,
pub invert_match: bool,
pub line_number: bool,
+ pub quiet: bool,
pub text: bool,
}
@@ -97,6 +98,7 @@ impl Default for Options {
eol: b'\n',
invert_match: false,
line_number: false,
+ quiet: false,
text: false,
}
}
@@ -104,10 +106,16 @@ impl Default for Options {
}
impl Options {
- /// Both --count and --files-with-matches options imply that we should not
- /// display matches at all.
+ /// Several options (--quiet, --count, --files-with-matches) imply that
+ /// we shouldn't ever display matches.
pub fn skip_matches(&self) -> bool {
- return self.count || self.files_with_matches;
+ self.count || self.files_with_matches || self.quiet
+ }
+
+ /// Some options (--quiet, --files-with-matches) imply that we can stop
+ /// searching after the first match.
+ pub fn stop_after_first_match(&self) -> bool {
+ self.files_with_matches || self.quiet
}
}
@@ -197,6 +205,13 @@ impl<'a, R: io::Read, W: Terminal + Send> Searcher<'a, R, W> {
self
}
+ /// If enabled, don't show any output and quit searching after the first
+ /// match is found.
+ pub fn quiet(mut self, yes: bool) -> Self {
+ self.opts.quiet = yes;
+ self
+ }
+
/// If enabled, search binary files as if they were text.
pub fn text(mut self, yes: bool) -> Self {
self.opts.text = yes;
@@ -265,8 +280,7 @@ impl<'a, R: io::Read, W: Terminal + Send> Searcher<'a, R, W> {
#[inline(always)]
fn terminate(&self) -> bool {
- self.match_count > 0
- && (self.printer.is_quiet() || self.opts.files_with_matches)
+ self.match_count > 0 && self.opts.stop_after_first_match()
}
#[inline(always)]