mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-05-19 09:40:22 -07:00
Add --path-separator flag.
This flag permits setting the path separator used for all file paths printed by ripgrep in normal operation. Fixes #275
This commit is contained in:
parent
2143bcf9cb
commit
8751e55706
12
doc/rg.1
12
doc/rg.1
@ -186,7 +186,7 @@ One byte is equal to one column.
|
|||||||
.RS
|
.RS
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.B \-\-context\-separator \f[I]ARG\f[]
|
.B \-\-context\-separator \f[I]SEPARATOR\f[]
|
||||||
The string to use when separating non\-continuous context lines.
|
The string to use when separating non\-continuous context lines.
|
||||||
Escape sequences may be used.
|
Escape sequences may be used.
|
||||||
[default: \-\-]
|
[default: \-\-]
|
||||||
@ -328,6 +328,16 @@ and \-\-files.
|
|||||||
.RS
|
.RS
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-path\-separator \f[I]SEPARATOR\f[]
|
||||||
|
The path separator to use when printing file paths.
|
||||||
|
This defaults to your platform\[aq]s path separator, which is / on Unix
|
||||||
|
and \\ on Windows.
|
||||||
|
This flag is intended for overriding the default when the environment
|
||||||
|
demands it (e.g., cygwin).
|
||||||
|
A path separator is limited to a single byte.
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
.B \-p, \-\-pretty
|
.B \-p, \-\-pretty
|
||||||
Alias for \-\-color=always \-\-heading \-n.
|
Alias for \-\-color=always \-\-heading \-n.
|
||||||
.RS
|
.RS
|
||||||
|
@ -128,7 +128,7 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
|||||||
numbers for the first match on each line. Note that this doesn't try
|
numbers for the first match on each line. Note that this doesn't try
|
||||||
to account for Unicode. One byte is equal to one column.
|
to account for Unicode. One byte is equal to one column.
|
||||||
|
|
||||||
--context-separator *ARG*
|
--context-separator *SEPARATOR*
|
||||||
: The string to use when separating non-continuous context lines. Escape
|
: The string to use when separating non-continuous context lines. Escape
|
||||||
sequences may be used. [default: --]
|
sequences may be used. [default: --]
|
||||||
|
|
||||||
@ -221,6 +221,12 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
|||||||
a list of matching files such as with --count, --files-with-matches
|
a list of matching files such as with --count, --files-with-matches
|
||||||
and --files.
|
and --files.
|
||||||
|
|
||||||
|
--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
|
||||||
|
intended for overriding the default when the environment demands it (e.g.,
|
||||||
|
cygwin). A path separator is limited to a single byte.
|
||||||
|
|
||||||
-p, --pretty
|
-p, --pretty
|
||||||
: Alias for --color=always --heading -n.
|
: Alias for --color=always --heading -n.
|
||||||
|
|
||||||
|
11
src/app.rs
11
src/app.rs
@ -125,7 +125,8 @@ fn app<F>(next_line_help: bool, doc: F) -> App<'static, 'static>
|
|||||||
.value_name("NUM").takes_value(true)
|
.value_name("NUM").takes_value(true)
|
||||||
.validator(validate_number))
|
.validator(validate_number))
|
||||||
.arg(flag("column"))
|
.arg(flag("column"))
|
||||||
.arg(flag("context-separator").value_name("ARG").takes_value(true))
|
.arg(flag("context-separator")
|
||||||
|
.value_name("SEPARATOR").takes_value(true))
|
||||||
.arg(flag("debug"))
|
.arg(flag("debug"))
|
||||||
.arg(flag("file").short("f")
|
.arg(flag("file").short("f")
|
||||||
.value_name("FILE").takes_value(true)
|
.value_name("FILE").takes_value(true)
|
||||||
@ -154,6 +155,7 @@ fn app<F>(next_line_help: bool, doc: F) -> App<'static, 'static>
|
|||||||
.arg(flag("no-ignore-parent"))
|
.arg(flag("no-ignore-parent"))
|
||||||
.arg(flag("no-ignore-vcs"))
|
.arg(flag("no-ignore-vcs"))
|
||||||
.arg(flag("null"))
|
.arg(flag("null"))
|
||||||
|
.arg(flag("path-separator").value_name("SEPARATOR").takes_value(true))
|
||||||
.arg(flag("pretty").short("p"))
|
.arg(flag("pretty").short("p"))
|
||||||
.arg(flag("replace").short("r").value_name("ARG").takes_value(true))
|
.arg(flag("replace").short("r").value_name("ARG").takes_value(true))
|
||||||
.arg(flag("case-sensitive").short("s"))
|
.arg(flag("case-sensitive").short("s"))
|
||||||
@ -410,6 +412,13 @@ lazy_static! {
|
|||||||
printing a list of matching files such as with --count, \
|
printing a list of matching files such as with --count, \
|
||||||
--files-with-matches and --files. This option is useful for use \
|
--files-with-matches and --files. This option is useful for use \
|
||||||
with xargs.");
|
with xargs.");
|
||||||
|
doc!(h, "path-separator",
|
||||||
|
"Path separator to use when printing file paths.",
|
||||||
|
"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 intended for overriding the \
|
||||||
|
default when the environment demands it (e.g., cygwin). A path \
|
||||||
|
separator is limited to a single byte.");
|
||||||
doc!(h, "pretty",
|
doc!(h, "pretty",
|
||||||
"Alias for --color always --heading -n.");
|
"Alias for --color always --heading -n.");
|
||||||
doc!(h, "replace",
|
doc!(h, "replace",
|
||||||
|
22
src/args.rs
22
src/args.rs
@ -62,6 +62,7 @@ pub struct Args {
|
|||||||
no_ignore_vcs: bool,
|
no_ignore_vcs: bool,
|
||||||
no_messages: bool,
|
no_messages: bool,
|
||||||
null: bool,
|
null: bool,
|
||||||
|
path_separator: Option<u8>,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
quiet_matched: QuietMatched,
|
quiet_matched: QuietMatched,
|
||||||
replace: Option<Vec<u8>>,
|
replace: Option<Vec<u8>>,
|
||||||
@ -151,6 +152,7 @@ impl Args {
|
|||||||
.heading(self.heading)
|
.heading(self.heading)
|
||||||
.line_per_match(self.line_per_match)
|
.line_per_match(self.line_per_match)
|
||||||
.null(self.null)
|
.null(self.null)
|
||||||
|
.path_separator(self.path_separator)
|
||||||
.with_filename(self.with_filename);
|
.with_filename(self.with_filename);
|
||||||
if let Some(ref rep) = self.replace {
|
if let Some(ref rep) = self.replace {
|
||||||
p = p.replace(rep.clone());
|
p = p.replace(rep.clone());
|
||||||
@ -347,6 +349,7 @@ impl<'a> ArgMatches<'a> {
|
|||||||
no_ignore_vcs: self.no_ignore_vcs(),
|
no_ignore_vcs: self.no_ignore_vcs(),
|
||||||
no_messages: self.is_present("no-messages"),
|
no_messages: self.is_present("no-messages"),
|
||||||
null: self.is_present("null"),
|
null: self.is_present("null"),
|
||||||
|
path_separator: try!(self.path_separator()),
|
||||||
quiet: quiet,
|
quiet: quiet,
|
||||||
quiet_matched: QuietMatched::new(quiet),
|
quiet_matched: QuietMatched::new(quiet),
|
||||||
replace: self.replace(),
|
replace: self.replace(),
|
||||||
@ -616,6 +619,25 @@ impl<'a> ArgMatches<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the unescaped path separator in UTF-8 bytes.
|
||||||
|
fn path_separator(&self) -> Result<Option<u8>> {
|
||||||
|
match self.value_of_lossy("path-separator") {
|
||||||
|
None => Ok(None),
|
||||||
|
Some(sep) => {
|
||||||
|
let sep = unescape(&sep);
|
||||||
|
if sep.is_empty() {
|
||||||
|
Ok(None)
|
||||||
|
} else if sep.len() > 1 {
|
||||||
|
Err(From::from(format!(
|
||||||
|
"A path separator must be exactly one byte, but \
|
||||||
|
the given separator is {} bytes.", sep.len())))
|
||||||
|
} else {
|
||||||
|
Ok(Some(sep[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the before and after contexts from the command line.
|
/// Returns the before and after contexts from the command line.
|
||||||
///
|
///
|
||||||
/// If a context setting was absent, then `0` is returned.
|
/// If a context setting was absent, then `0` is returned.
|
||||||
|
@ -44,6 +44,8 @@ pub struct Printer<W> {
|
|||||||
with_filename: bool,
|
with_filename: bool,
|
||||||
/// The color specifications.
|
/// The color specifications.
|
||||||
colors: ColorSpecs,
|
colors: ColorSpecs,
|
||||||
|
/// The separator to use for file paths. If empty, this is ignored.
|
||||||
|
path_separator: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: WriteColor> Printer<W> {
|
impl<W: WriteColor> Printer<W> {
|
||||||
@ -62,6 +64,7 @@ impl<W: WriteColor> Printer<W> {
|
|||||||
replace: None,
|
replace: None,
|
||||||
with_filename: false,
|
with_filename: false,
|
||||||
colors: ColorSpecs::default(),
|
colors: ColorSpecs::default(),
|
||||||
|
path_separator: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +121,13 @@ impl<W: WriteColor> Printer<W> {
|
|||||||
self
|
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> {
|
||||||
|
self.path_separator = sep;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Replace every match in each matching line with the replacement string
|
/// Replace every match in each matching line with the replacement string
|
||||||
/// given.
|
/// given.
|
||||||
///
|
///
|
||||||
@ -342,12 +352,29 @@ impl<W: WriteColor> Printer<W> {
|
|||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
let path = path.as_ref().as_os_str().as_bytes();
|
let path = path.as_ref().as_os_str().as_bytes();
|
||||||
self.write(path);
|
match self.path_separator {
|
||||||
|
None => self.write(path),
|
||||||
|
Some(sep) => self.write_path_with_sep(path, sep),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
fn write_path<P: AsRef<Path>>(&mut self, path: P) {
|
fn write_path<P: AsRef<Path>>(&mut self, path: P) {
|
||||||
self.write(path.as_ref().to_string_lossy().as_bytes());
|
let path = path.as_ref().to_string_lossy();
|
||||||
|
match self.path_separator {
|
||||||
|
None => self.write(path.as_bytes()),
|
||||||
|
Some(sep) => self.write_path_with_sep(path.as_bytes(), sep),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_path_with_sep(&mut self, path: &[u8], sep: u8) {
|
||||||
|
let mut path = path.to_vec();
|
||||||
|
for b in &mut path {
|
||||||
|
if *b == b'/' || (cfg!(windows) && *b == b'\\') {
|
||||||
|
*b = sep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.write(&path);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&mut self, buf: &[u8]) {
|
fn write(&mut self, buf: &[u8]) {
|
||||||
|
@ -1226,6 +1226,16 @@ clean!(feature_263_sort_files, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
|||||||
assert_eq!(lines, "abc:test\nbar:test\nfoo:test\nzoo:test\n");
|
assert_eq!(lines, "abc:test\nbar:test\nfoo:test\nzoo:test\n");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// See: https://github.com/BurntSushi/ripgrep/issues/275
|
||||||
|
clean!(feature_275_pathsep, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
||||||
|
wd.create_dir("foo");
|
||||||
|
wd.create("foo/bar", "test");
|
||||||
|
cmd.arg("--path-separator").arg("Z");
|
||||||
|
|
||||||
|
let lines: String = wd.stdout(&mut cmd);
|
||||||
|
assert_eq!(lines, "fooZbar:test\n");
|
||||||
|
});
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn binary_nosearch() {
|
fn binary_nosearch() {
|
||||||
let wd = WorkDir::new("binary_nosearch");
|
let wd = WorkDir::new("binary_nosearch");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user