mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-01-03 05:10:12 +02:00
cli: add --field-{context,match}-separator flags
These flags permit configuring the bytes used to delimit fields in match or context lines, where "fields" are things like the file path, line number, column number and the match/context itself. Fixes #1842, Closes #1871
This commit is contained in:
parent
46d0130597
commit
578e1992fa
@ -43,6 +43,8 @@ Feature enhancements:
|
||||
Cargo will now produce static executables on Windows when using MSVC.
|
||||
* [FEATURE #1680](https://github.com/BurntSushi/ripgrep/pull/1680):
|
||||
Add `-.` as a short flag alias for `--hidden`.
|
||||
* [FEATURE #1842](https://github.com/BurntSushi/ripgrep/issues/1842):
|
||||
Add `--field-{context,match}-separator` for customizing field delimiters.
|
||||
* [FEATURE #1856](https://github.com/BurntSushi/ripgrep/pull/1856):
|
||||
The README now links to a
|
||||
[Spanish translation](https://github.com/UltiRequiem/traducciones/tree/master/ripgrep).
|
||||
|
@ -303,6 +303,8 @@ _rg() {
|
||||
'--context-separator=[specify string used to separate non-continuous context lines in output]:separator'
|
||||
$no"--no-context-separator[don't print context separators]"
|
||||
'--debug[show debug messages]'
|
||||
'--field-context-separator[set string to delimit fields in context lines]'
|
||||
'--field-match-separator[set string to delimit fields in matching lines]'
|
||||
'--trace[show more verbose debug messages]'
|
||||
'--dfa-size-limit=[specify upper size limit of generated DFA]:DFA size (bytes)'
|
||||
"(1 stats)--files[show each file that would be searched (but don't search)]"
|
||||
|
@ -568,6 +568,8 @@ pub fn all_args_and_flags() -> Vec<RGArg> {
|
||||
flag_dfa_size_limit(&mut args);
|
||||
flag_encoding(&mut args);
|
||||
flag_engine(&mut args);
|
||||
flag_field_context_separator(&mut args);
|
||||
flag_field_match_separator(&mut args);
|
||||
flag_file(&mut args);
|
||||
flag_files(&mut args);
|
||||
flag_files_with_matches(&mut args);
|
||||
@ -1231,6 +1233,38 @@ This overrides previous uses of --pcre2 and --auto-hybrid-regex flags.
|
||||
args.push(arg);
|
||||
}
|
||||
|
||||
fn flag_field_context_separator(args: &mut Vec<RGArg>) {
|
||||
const SHORT: &str = "Set the field context separator.";
|
||||
const LONG: &str = long!(
|
||||
"\
|
||||
Set the field context separator, which is used to delimit file paths, line
|
||||
numbers, columns and the context itself, when printing contextual lines. The
|
||||
separator may be any number of bytes, including zero. Escape sequences like
|
||||
\\x7F or \\t may be used. The default value is -.
|
||||
"
|
||||
);
|
||||
let arg = RGArg::flag("field-context-separator", "SEPARATOR")
|
||||
.help(SHORT)
|
||||
.long_help(LONG);
|
||||
args.push(arg);
|
||||
}
|
||||
|
||||
fn flag_field_match_separator(args: &mut Vec<RGArg>) {
|
||||
const SHORT: &str = "Set the match separator.";
|
||||
const LONG: &str = long!(
|
||||
"\
|
||||
Set the field match separator, which is used to delimit file paths, line
|
||||
numbers, columns and the match itself. The separator may be any number of
|
||||
bytes, including zero. Escape sequences like \\x7F or \\t may be used. The
|
||||
default value is -.
|
||||
"
|
||||
);
|
||||
let arg = RGArg::flag("field-match-separator", "SEPARATOR")
|
||||
.help(SHORT)
|
||||
.long_help(LONG);
|
||||
args.push(arg);
|
||||
}
|
||||
|
||||
fn flag_file(args: &mut Vec<RGArg>) {
|
||||
const SHORT: &str = "Search for patterns from the given file.";
|
||||
const LONG: &str = long!(
|
||||
|
@ -786,8 +786,8 @@ impl ArgMatches {
|
||||
.trim_ascii(self.is_present("trim"))
|
||||
.separator_search(None)
|
||||
.separator_context(self.context_separator())
|
||||
.separator_field_match(b":".to_vec())
|
||||
.separator_field_context(b"-".to_vec())
|
||||
.separator_field_match(self.field_match_separator())
|
||||
.separator_field_context(self.field_context_separator())
|
||||
.separator_path(self.path_separator()?)
|
||||
.path_terminator(self.path_terminator());
|
||||
if separator_search {
|
||||
@ -1377,6 +1377,24 @@ impl ArgMatches {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the unescaped field context separator. If one wasn't specified,
|
||||
/// then '-' is used as the default.
|
||||
fn field_context_separator(&self) -> Vec<u8> {
|
||||
match self.value_of_os("field-context-separator") {
|
||||
None => b"-".to_vec(),
|
||||
Some(sep) => cli::unescape_os(&sep),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the unescaped field match separator. If one wasn't specified,
|
||||
/// then ':' is used as the default.
|
||||
fn field_match_separator(&self) -> Vec<u8> {
|
||||
match self.value_of_os("field-match-separator") {
|
||||
None => b":".to_vec(),
|
||||
Some(sep) => cli::unescape_os(&sep),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a sequence of all available patterns from the command line.
|
||||
/// This includes reading the -e/--regexp and -f/--file flags.
|
||||
///
|
||||
|
@ -828,6 +828,99 @@ rgtest!(f1404_nothing_searched_ignored, |dir: Dir, mut cmd: TestCommand| {
|
||||
eqnice!(expected, stderr);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/1842
|
||||
rgtest!(f1842_field_context_separator, |dir: Dir, _: TestCommand| {
|
||||
dir.create("sherlock", SHERLOCK);
|
||||
|
||||
// Test the default.
|
||||
let base = &["-n", "-A1", "Doctor Watsons", "sherlock"];
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
2-Holmeses, success in the province of detective work must always
|
||||
";
|
||||
eqnice!(expected, dir.command().args(base).stdout());
|
||||
|
||||
// Test that it can be overridden.
|
||||
let mut args = vec!["--field-context-separator", "!"];
|
||||
args.extend(base);
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
2!Holmeses, success in the province of detective work must always
|
||||
";
|
||||
eqnice!(expected, dir.command().args(&args).stdout());
|
||||
|
||||
// Test that it can use multiple bytes.
|
||||
let mut args = vec!["--field-context-separator", "!!"];
|
||||
args.extend(base);
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
2!!Holmeses, success in the province of detective work must always
|
||||
";
|
||||
eqnice!(expected, dir.command().args(&args).stdout());
|
||||
|
||||
// Test that unescaping works.
|
||||
let mut args = vec!["--field-context-separator", r"\x7F"];
|
||||
args.extend(base);
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
2\x7FHolmeses, success in the province of detective work must always
|
||||
";
|
||||
eqnice!(expected, dir.command().args(&args).stdout());
|
||||
|
||||
// Test that an empty separator is OK.
|
||||
let mut args = vec!["--field-context-separator", r""];
|
||||
args.extend(base);
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
2Holmeses, success in the province of detective work must always
|
||||
";
|
||||
eqnice!(expected, dir.command().args(&args).stdout());
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/1842
|
||||
rgtest!(f1842_field_match_separator, |dir: Dir, _: TestCommand| {
|
||||
dir.create("sherlock", SHERLOCK);
|
||||
|
||||
// Test the default.
|
||||
let base = &["-n", "Doctor Watsons", "sherlock"];
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
";
|
||||
eqnice!(expected, dir.command().args(base).stdout());
|
||||
|
||||
// Test that it can be overridden.
|
||||
let mut args = vec!["--field-match-separator", "!"];
|
||||
args.extend(base);
|
||||
let expected = "\
|
||||
1!For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
";
|
||||
eqnice!(expected, dir.command().args(&args).stdout());
|
||||
|
||||
// Test that it can use multiple bytes.
|
||||
let mut args = vec!["--field-match-separator", "!!"];
|
||||
args.extend(base);
|
||||
let expected = "\
|
||||
1!!For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
";
|
||||
eqnice!(expected, dir.command().args(&args).stdout());
|
||||
|
||||
// Test that unescaping works.
|
||||
let mut args = vec!["--field-match-separator", r"\x7F"];
|
||||
args.extend(base);
|
||||
let expected = "\
|
||||
1\x7FFor the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
";
|
||||
eqnice!(expected, dir.command().args(&args).stdout());
|
||||
|
||||
// Test that an empty separator is OK.
|
||||
let mut args = vec!["--field-match-separator", r""];
|
||||
args.extend(base);
|
||||
let expected = "\
|
||||
1For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
";
|
||||
eqnice!(expected, dir.command().args(&args).stdout());
|
||||
});
|
||||
|
||||
rgtest!(no_context_sep, |dir: Dir, mut cmd: TestCommand| {
|
||||
dir.create("test", "foo\nctx\nbar\nctx\nfoo\nctx");
|
||||
cmd.args(&["-A1", "--no-context-separator", "foo", "test"]);
|
||||
|
Loading…
Reference in New Issue
Block a user