summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Gallant <jamslam@gmail.com>2018-09-04 21:39:05 -0400
committerAndrew Gallant <jamslam@gmail.com>2018-09-04 23:18:55 -0400
commitb6e30124e07fb3b3530bae2c0cf19e0893aa9831 (patch)
treef72ae866353a1817bbc4c78f374d599df87fe519
parent4846d63539690047fa58ec582d94bcba16da1c09 (diff)
ripgrep: add --line-buffered and --block-buffered
These flags provide granular control over ripgrep's buffering strategy. The --line-buffered flag can be genuinely useful in certain types of shell pipelines. The --block-buffered flag has a murkier use case, but we add it for completeness.
-rw-r--r--CHANGELOG.md2
-rw-r--r--complete/_rg6
-rw-r--r--src/app.rs63
-rw-r--r--src/args.rs9
4 files changed, 79 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 73406762..226ca6a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -44,6 +44,8 @@ Feature enhancements:
Add `--null-data` flag, which makes ripgrep use NUL as a line terminator.
* [FEATURE #997](https://github.com/BurntSushi/ripgrep/issues/997):
The `--passthru` flag now works with the `--replace` flag.
+* FEATURE:
+ Add `--line-buffered` and `--block-buffered` for forcing a buffer strategy.
Bug fixes:
diff --git a/complete/_rg b/complete/_rg
index e35b60df..2bbdf992 100644
--- a/complete/_rg
+++ b/complete/_rg
@@ -44,6 +44,12 @@ _rg() {
'(: * -)'{-h,--help}'[display help information]'
'(: * -)'{-V,--version}'[display version information]'
+ + '(buffered)' # buffering options
+ '--line-buffered[force line buffering]'
+ $no"--no-line-buffered[don't force line buffering]"
+ '--block-buffered[force block buffering]'
+ $no"--no-block-buffered[don't force block buffering]"
+
+ '(case)' # Case-sensitivity options
{-i,--ignore-case}'[search case-insensitively]'
{-s,--case-sensitive}'[search case-sensitively]'
diff --git a/src/app.rs b/src/app.rs
index 039b6980..e0e1eda7 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -544,6 +544,7 @@ pub fn all_args_and_flags() -> Vec<RGArg> {
// "positive" flag.
flag_after_context(&mut args);
flag_before_context(&mut args);
+ flag_block_buffered(&mut args);
flag_byte_offset(&mut args);
flag_case_sensitive(&mut args);
flag_color(&mut args);
@@ -571,6 +572,7 @@ pub fn all_args_and_flags() -> Vec<RGArg> {
flag_ignore_file(&mut args);
flag_invert_match(&mut args);
flag_json(&mut args);
+ flag_line_buffered(&mut args);
flag_line_number(&mut args);
flag_line_regexp(&mut args);
flag_max_columns(&mut args);
@@ -685,6 +687,36 @@ This overrides the --context flag.
args.push(arg);
}
+fn flag_block_buffered(args: &mut Vec<RGArg>) {
+ const SHORT: &str = "Force block buffering.";
+ const LONG: &str = long!("\
+When enabled, ripgrep will use block buffering. That is, whenever a matching
+line is found, it will be written to an in-memory buffer and will not be
+written to stdout until the buffer reaches a certain size. This is the default
+when ripgrep's stdout is redirected to a pipeline or a file. When ripgrep's
+stdout is connected to a terminal, line buffering will be used. Forcing block
+buffering can be useful when dumping a large amount of contents to a terminal.
+
+Forceful block buffering can be disabled with --no-block-buffered. Note that
+using --no-block-buffered causes ripgrep to revert to its default behavior of
+automatically detecting the buffering strategy. To force line buffering, use
+the --line-buffered flag.
+");
+ let arg = RGArg::switch("block-buffered")
+ .help(SHORT).long_help(LONG)
+ .overrides("no-block-buffered")
+ .overrides("line-buffered")
+ .overrides("no-line-buffered");
+ args.push(arg);
+
+ let arg = RGArg::switch("no-block-buffered")
+ .hidden()
+ .overrides("block-buffered")
+ .overrides("line-buffered")
+ .overrides("no-line-buffered");
+ args.push(arg);
+}
+
fn flag_byte_offset(args: &mut Vec<RGArg>) {
const SHORT: &str =
"Print the 0-based byte offset for each matching line.";
@@ -1245,6 +1277,37 @@ The JSON Lines format can be disabled with --no-json.
args.push(arg);
}
+fn flag_line_buffered(args: &mut Vec<RGArg>) {
+ const SHORT: &str = "Force line buffering.";
+ const LONG: &str = long!("\
+When enabled, ripgrep will use line buffering. That is, whenever a matching
+line is found, it will be flushed to stdout immediately. This is the default
+when ripgrep's stdout is connected to a terminal, but otherwise, ripgrep will
+use block buffering, which is typically faster. This flag forces ripgrep to
+use line buffering even if it would otherwise use block buffering. This is
+typically useful in shell pipelines, e.g.,
+'tail -f something.log | rg foo --line-buffered | rg bar'.
+
+Forceful line buffering can be disabled with --no-line-buffered. Note that
+using --no-line-buffered causes ripgrep to revert to its default behavior of
+automatically detecting the buffering strategy. To force block buffering, use
+the --block-buffered flag.
+");
+ let arg = RGArg::switch("line-buffered")
+ .help(SHORT).long_help(LONG)
+ .overrides("no-line-buffered")
+ .overrides("block-buffered")
+ .overrides("no-block-buffered");
+ args.push(arg);
+
+ let arg = RGArg::switch("no-line-buffered")
+ .hidden()
+ .overrides("line-buffered")
+ .overrides("block-buffered")
+ .overrides("no-block-buffered");
+ args.push(arg);
+}
+
fn flag_line_number(args: &mut Vec<RGArg>) {
const SHORT: &str = "Show line numbers.";
const LONG: &str = long!("\
diff --git a/src/args.rs b/src/args.rs
index 2decefe7..f8a29cae 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -314,7 +314,14 @@ impl Args {
/// Execute the given function with a writer to stdout that enables color
/// support based on the command line configuration.
pub fn stdout(&self) -> cli::StandardStream {
- cli::stdout(self.matches().color_choice())
+ let color = self.matches().color_choice();
+ if self.matches().is_present("line-buffered") {
+ cli::stdout_buffered_line(color)
+ } else if self.matches().is_present("block-buffered") {
+ cli::stdout_buffered_block(color)
+ } else {
+ cli::stdout(color)
+ }
}
/// Return the type definitions compiled into ripgrep.