summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/rg.112
-rw-r--r--doc/rg.1.md8
-rw-r--r--src/app.rs11
-rw-r--r--src/args.rs22
-rw-r--r--src/printer.rs31
-rw-r--r--tests/tests.rs10
6 files changed, 89 insertions, 5 deletions
diff --git a/doc/rg.1 b/doc/rg.1
index 95539939..bed7ac65 100644
--- a/doc/rg.1
+++ b/doc/rg.1
@@ -186,7 +186,7 @@ One byte is equal to one column.
.RS
.RE
.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.
Escape sequences may be used.
[default: \-\-]
@@ -328,6 +328,16 @@ and \-\-files.
.RS
.RE
.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
Alias for \-\-color=always \-\-heading \-n.
.RS
diff --git a/doc/rg.1.md b/doc/rg.1.md
index 7f19cecf..5e0f7031 100644
--- a/doc/rg.1.md
+++ b/doc/rg.1.md
@@ -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
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
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
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
: Alias for --color=always --heading -n.
diff --git a/src/app.rs b/src/app.rs
index a9dd06a6..a353fdb9 100644
--- a/src/app.rs
+++ b/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)
.validator(validate_number))
.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("file").short("f")
.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-vcs"))
.arg(flag("null"))
+ .arg(flag("path-separator").value_name("SEPARATOR").takes_value(true))
.arg(flag("pretty").short("p"))
.arg(flag("replace").short("r").value_name("ARG").takes_value(true))
.arg(flag("case-sensitive").short("s"))
@@ -410,6 +412,13 @@ lazy_static! {
printing a list of matching files such as with --count, \
--files-with-matches and --files. This option is useful for use \
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",
"Alias for --color always --heading -n.");
doc!(h, "replace",
diff --git a/src/args.rs b/src/args.rs
index 29a7fa81..594ece09 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -62,6 +62,7 @@ pub struct Args {
no_ignore_vcs: bool,
no_messages: bool,
null: bool,
+ path_separator: Option<u8>,
quiet: bool,
quiet_matched: QuietMatched,
replace: Option<Vec<u8>>,
@@ -151,6 +152,7 @@ impl Args {
.heading(self.heading)
.line_per_match(self.line_per_match)
.null(self.null)
+ .path_separator(self.path_separator)
.with_filename(self.with_filename);
if let Some(ref rep) = self.replace {
p = p.replace(rep.clone());
@@ -347,6 +349,7 @@ impl<'a> ArgMatches<'a> {
no_ignore_vcs: self.no_ignore_vcs(),
no_messages: self.is_present("no-messages"),
null: self.is_present("null"),
+ path_separator: try!(self.path_separator()),
quiet: quiet,
quiet_matched: QuietMatched::new(quiet),
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.
///
/// If a context setting was absent, then `0` is returned.
diff --git a/src/printer.rs b/src/printer.rs
index c57e1611..8c04dd1a 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -44,6 +44,8 @@ pub struct Printer<W> {
with_filename: bool,
/// The color specifications.
colors: ColorSpecs,
+ /// The separator to use for file paths. If empty, this is ignored.
+ path_separator: Option<u8>,
}
impl<W: WriteColor> Printer<W> {
@@ -62,6 +64,7 @@ impl<W: WriteColor> Printer<W> {
replace: None,
with_filename: false,
colors: ColorSpecs::default(),
+ path_separator: None,
}
}
@@ -118,6 +121,13 @@ impl<W: WriteColor> Printer<W> {
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
/// given.
///
@@ -342,12 +352,29 @@ impl<W: WriteColor> Printer<W> {
use std::os::unix::ffi::OsStrExt;
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))]
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]) {
diff --git a/tests/tests.rs b/tests/tests.rs
index 11a76044..92d8e8ca 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -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");
});
+// 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]
fn binary_nosearch() {
let wd = WorkDir::new("binary_nosearch");