diff options
author | Andrew Gallant <jamslam@gmail.com> | 2017-01-10 18:16:15 -0500 |
---|---|---|
committer | Andrew Gallant <jamslam@gmail.com> | 2017-01-10 18:16:15 -0500 |
commit | 8751e5570697e6b2b913b2ab06e0dabf9f28b436 (patch) | |
tree | 51a57c6e292aaa8dc74ec30635faf2ad9c509726 /src | |
parent | 2143bcf9cb259c2230aa79a7cbc23cb1ec1fdae7 (diff) |
Add --path-separator flag.
This flag permits setting the path separator used for all file paths
printed by ripgrep in normal operation.
Fixes #275
Diffstat (limited to 'src')
-rw-r--r-- | src/app.rs | 11 | ||||
-rw-r--r-- | src/args.rs | 22 | ||||
-rw-r--r-- | src/printer.rs | 31 |
3 files changed, 61 insertions, 3 deletions
@@ -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]) { |