Improves Printer, fixes some bugs

This commit is contained in:
Roman Proskuryakov 2017-03-31 00:13:07 +03:00 committed by Andrew Gallant
parent 33c95d2919
commit aed3ccb9c7
2 changed files with 89 additions and 73 deletions

View File

@ -204,22 +204,14 @@ impl<W: WriteColor> Printer<W> {
pub fn path<P: AsRef<Path>>(&mut self, path: P) { pub fn path<P: AsRef<Path>>(&mut self, path: P) {
let path = strip_prefix("./", path.as_ref()).unwrap_or(path.as_ref()); let path = strip_prefix("./", path.as_ref()).unwrap_or(path.as_ref());
self.write_path(path); self.write_path(path);
if self.null { self.write_path_eol();
self.write(b"\x00");
} else {
self.write_eol();
}
} }
/// Prints the given path and a count of the number of matches found. /// Prints the given path and a count of the number of matches found.
pub fn path_count<P: AsRef<Path>>(&mut self, path: P, count: u64) { pub fn path_count<P: AsRef<Path>>(&mut self, path: P, count: u64) {
if self.with_filename { if self.with_filename {
self.write_path(path); self.write_path(path);
if self.null { self.write_path_sep(b':');
self.write(b"\x00");
} else {
self.write(b":");
}
} }
self.write(count.to_string().as_bytes()); self.write(count.to_string().as_bytes());
self.write_eol(); self.write_eol();
@ -227,13 +219,11 @@ impl<W: WriteColor> Printer<W> {
/// Prints the context separator. /// Prints the context separator.
pub fn context_separate(&mut self) { pub fn context_separate(&mut self) {
// N.B. We can't use `write` here because of borrowing restrictions.
if self.context_separator.is_empty() { if self.context_separator.is_empty() {
return; return;
} }
self.has_printed = true;
let _ = self.wtr.write_all(&self.context_separator); let _ = self.wtr.write_all(&self.context_separator);
let _ = self.wtr.write_all(&[self.eol]); self.write_eol();
} }
pub fn matched<P: AsRef<Path>>( pub fn matched<P: AsRef<Path>>(
@ -280,16 +270,17 @@ impl<W: WriteColor> Printer<W> {
) { ) {
if self.heading && self.with_filename && !self.has_printed { if self.heading && self.with_filename && !self.has_printed {
self.write_file_sep(); self.write_file_sep();
self.write_heading(path.as_ref()); self.write_path(path);
self.write_path_eol();
} else if !self.heading && self.with_filename { } else if !self.heading && self.with_filename {
self.write_non_heading_path(path.as_ref()); self.write_path(path);
self.write_path_sep(b':');
} }
if let Some(line_number) = line_number { if let Some(line_number) = line_number {
self.line_number(line_number, b':'); self.line_number(line_number, b':');
} }
if let Some(c) = column { if let Some(c) = column {
self.write((c + 1).to_string().as_bytes()); self.column_number(c + 1, b':');
self.write(b":");
} }
if self.replace.is_some() { if self.replace.is_some() {
let mut count = 0; let mut count = 0;
@ -299,11 +290,8 @@ impl<W: WriteColor> Printer<W> {
re.replace_all(&buf[start..end], replacer) re.replace_all(&buf[start..end], replacer)
}; };
if self.max_columns.map_or(false, |m| line.len() > m) { if self.max_columns.map_or(false, |m| line.len() > m) {
let _ = self.wtr.set_color(self.colors.matched()); let msg = format!("[Omitted long line with {} replacements]", count);
let msg = format!( self.write_colored(msg.as_bytes(), |colors| colors.matched());
"[Omitted long line with {} replacements]", count);
self.write(msg.as_bytes());
let _ = self.wtr.reset();
self.write_eol(); self.write_eol();
return; return;
} }
@ -320,10 +308,8 @@ impl<W: WriteColor> Printer<W> {
fn write_matched_line(&mut self, re: &Regex, buf: &[u8]) { fn write_matched_line(&mut self, re: &Regex, buf: &[u8]) {
if self.max_columns.map_or(false, |m| buf.len() > m) { if self.max_columns.map_or(false, |m| buf.len() > m) {
let count = re.find_iter(buf).count(); let count = re.find_iter(buf).count();
let _ = self.wtr.set_color(self.colors.matched());
let msg = format!("[Omitted long line with {} matches]", count); let msg = format!("[Omitted long line with {} matches]", count);
self.write(msg.as_bytes()); self.write_colored(msg.as_bytes(), |colors| colors.matched());
let _ = self.wtr.reset();
self.write_eol(); self.write_eol();
return; return;
} }
@ -333,9 +319,7 @@ impl<W: WriteColor> Printer<W> {
let mut last_written = 0; let mut last_written = 0;
for m in re.find_iter(buf) { for m in re.find_iter(buf) {
self.write(&buf[last_written..m.start()]); self.write(&buf[last_written..m.start()]);
let _ = self.wtr.set_color(self.colors.matched()); self.write_colored(&buf[m.start()..m.end()], |colors| colors.matched());
self.write(&buf[m.start()..m.end()]);
let _ = self.wtr.reset();
last_written = m.end(); last_written = m.end();
} }
self.write(&buf[last_written..]); self.write(&buf[last_written..]);
@ -355,14 +339,11 @@ impl<W: WriteColor> Printer<W> {
) { ) {
if self.heading && self.with_filename && !self.has_printed { if self.heading && self.with_filename && !self.has_printed {
self.write_file_sep(); self.write_file_sep();
self.write_heading(path.as_ref()); self.write_path(path);
self.write_path_eol();
} else if !self.heading && self.with_filename { } else if !self.heading && self.with_filename {
self.write_path(path.as_ref()); self.write_path(path);
if self.null { self.write_path_sep(b'-');
self.write(b"\x00");
} else {
self.write(b"-");
}
} }
if let Some(line_number) = line_number { if let Some(line_number) = line_number {
self.line_number(line_number, b'-'); self.line_number(line_number, b'-');
@ -378,10 +359,19 @@ impl<W: WriteColor> Printer<W> {
} }
} }
fn write_heading<P: AsRef<Path>>(&mut self, path: P) { fn separator(&mut self, sep: &[u8]) {
let _ = self.wtr.set_color(self.colors.path()); self.write(&sep);
self.write_path(path.as_ref()); }
let _ = self.wtr.reset();
fn write_path_sep(&mut self, sep: u8) {
if self.null {
self.write(b"\x00");
} else {
self.separator(&[sep]);
}
}
fn write_path_eol(&mut self) {
if self.null { if self.null {
self.write(b"\x00"); self.write(b"\x00");
} else { } else {
@ -389,52 +379,43 @@ impl<W: WriteColor> Printer<W> {
} }
} }
fn write_non_heading_path<P: AsRef<Path>>(&mut self, path: P) {
let _ = self.wtr.set_color(self.colors.path());
self.write_path(path.as_ref());
let _ = self.wtr.reset();
if self.null {
self.write(b"\x00");
} else {
self.write(b":");
}
}
fn line_number(&mut self, n: u64, sep: u8) {
let _ = self.wtr.set_color(self.colors.line());
self.write(n.to_string().as_bytes());
let _ = self.wtr.reset();
self.write(&[sep]);
}
#[cfg(unix)] #[cfg(unix)]
fn write_path<P: AsRef<Path>>(&mut self, path: P) { fn write_path<P: AsRef<Path>>(&mut self, path: P) {
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();
match self.path_separator { self.write_path_replace_separator(path);
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) {
let path = path.as_ref().to_string_lossy(); let path = path.as_ref().to_string_lossy();
self.write_path_replace_separator(path.as_bytes());
}
fn write_path_replace_separator(&mut self, path: &[u8]) {
match self.path_separator { match self.path_separator {
None => self.write(path.as_bytes()), None => self.write_colored(path, |colors| colors.path()),
Some(sep) => self.write_path_with_sep(path.as_bytes(), sep), Some(sep) => {
let transformed_path: Vec<_> = path.iter().map(|&b| {
if b == b'/' || (cfg!(windows) && b == b'\\') {
sep
} else {
b
}
}).collect();
self.write_colored(&transformed_path, |colors| colors.path());
}
} }
} }
fn write_path_with_sep(&mut self, path: &[u8], sep: u8) { fn line_number(&mut self, n: u64, sep: u8) {
let mut path = path.to_vec(); self.write_colored(n.to_string().as_bytes(), |colors| colors.line());
for b in &mut path { self.separator(&[sep]);
if *b == b'/' || (cfg!(windows) && *b == b'\\') { }
*b = sep;
} fn column_number(&mut self, n: u64, sep: u8) {
} self.write(n.to_string().as_bytes());
self.write(&path); self.separator(&[sep]);
} }
fn write(&mut self, buf: &[u8]) { fn write(&mut self, buf: &[u8]) {
@ -447,6 +428,14 @@ impl<W: WriteColor> Printer<W> {
self.write(&[eol]); self.write(&[eol]);
} }
fn write_colored<F>(&mut self, buf: &[u8], get_color: F)
where F: Fn(&ColorSpecs) -> &ColorSpec
{
let _ = self.wtr.set_color( get_color(&self.colors) );
self.write(buf);
let _ = self.wtr.reset();
}
fn write_file_sep(&mut self) { fn write_file_sep(&mut self) {
if let Some(ref sep) = self.file_separator { if let Some(ref sep) = self.file_separator {
self.has_printed = true; self.has_printed = true;
@ -503,7 +492,7 @@ impl fmt::Display for Error {
} }
Error::UnrecognizedStyle(ref name) => { Error::UnrecognizedStyle(ref name) => {
write!(f, "Unrecognized style attribute '{}'. Choose from: \ write!(f, "Unrecognized style attribute '{}'. Choose from: \
nobold, bold.", name) nobold, bold, nointense, intense.", name)
} }
Error::InvalidFormat(ref original) => { Error::InvalidFormat(ref original) => {
write!(f, "Invalid color speci format: '{}'. Valid format \ write!(f, "Invalid color speci format: '{}'. Valid format \

View File

@ -1057,6 +1057,33 @@ clean!(regression_405, "test", ".", |wd: WorkDir, mut cmd: Command| {
assert_eq!(lines, format!("{}:test\n", path("bar/foo/file2.txt"))); assert_eq!(lines, format!("{}:test\n", path("bar/foo/file2.txt")));
}); });
// See: https://github.com/BurntSushi/ripgrep/issues/428
clean!(regression_428_color_context_path, "foo", ".", |wd: WorkDir, mut cmd: Command| {
wd.create("sherlock", "foo\nbar");
cmd.arg("-A1").arg("-H").arg("--no-heading").arg("-N")
.arg("--colors=match:none").arg("--color=always");
let lines: String = wd.stdout(&mut cmd);
let expected = format!("\
{colored_path}:foo
{colored_path}-bar
", colored_path=format!("\x1b\x5b\x6d\x1b\x5b\x33\x35\x6d{path}\x1b\x5b\x6d", path=path("sherlock")));
assert_eq!(lines, expected);
});
// See: https://github.com/BurntSushi/ripgrep/issues/428
clean!(regression_428_unrecognized_style, "Sherlok", ".", |wd: WorkDir, mut cmd: Command| {
cmd.arg("--colors=match:style:");
wd.assert_err(&mut cmd);
let output = cmd.output().unwrap();
let err = String::from_utf8_lossy(&output.stderr);
let expected = "\
Unrecognized style attribute ''. Choose from: nobold, bold, nointense, intense.
";
assert_eq!(err, expected);
});
// See: https://github.com/BurntSushi/ripgrep/issues/1 // See: https://github.com/BurntSushi/ripgrep/issues/1
clean!(feature_1_sjis, "Шерлок Холмс", ".", |wd: WorkDir, mut cmd: Command| { clean!(feature_1_sjis, "Шерлок Холмс", ".", |wd: WorkDir, mut cmd: Command| {
let sherlock = let sherlock =