mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-06-04 05:57:39 +02:00
parent
214f2bef66
commit
67b835fe2a
@ -3,29 +3,58 @@ use std::fmt;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use regex::bytes::{Captures, Regex, Replacer};
|
use regex::bytes::{Captures, Match, Regex, Replacer};
|
||||||
use termcolor::{Color, ColorSpec, ParseColorError, WriteColor};
|
use termcolor::{Color, ColorSpec, ParseColorError, WriteColor};
|
||||||
|
|
||||||
use pathutil::strip_prefix;
|
use pathutil::strip_prefix;
|
||||||
use ignore::types::FileTypeDef;
|
use ignore::types::FileTypeDef;
|
||||||
|
|
||||||
|
/// Track the start and end of replacements to allow coloring them on output.
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Offset {
|
||||||
|
start: usize,
|
||||||
|
end: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Offset {
|
||||||
|
fn new(start: usize, end: usize) -> Offset {
|
||||||
|
Offset { start: start, end: end }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'m, 'r> From<&'m Match<'r>> for Offset {
|
||||||
|
fn from(m: &'m Match<'r>) -> Self {
|
||||||
|
Offset{ start: m.start(), end: m.end() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// CountingReplacer implements the Replacer interface for Regex,
|
/// CountingReplacer implements the Replacer interface for Regex,
|
||||||
/// and counts how often replacement is being performed.
|
/// and counts how often replacement is being performed.
|
||||||
struct CountingReplacer<'r> {
|
struct CountingReplacer<'r> {
|
||||||
replace: &'r [u8],
|
replace: &'r [u8],
|
||||||
count: &'r mut usize,
|
count: &'r mut usize,
|
||||||
|
offsets: &'r mut Vec<Offset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> CountingReplacer<'r> {
|
impl<'r> CountingReplacer<'r> {
|
||||||
fn new(replace: &'r [u8], count: &'r mut usize) -> CountingReplacer<'r> {
|
fn new(
|
||||||
CountingReplacer { replace: replace, count: count }
|
replace: &'r [u8],
|
||||||
|
count: &'r mut usize,
|
||||||
|
offsets: &'r mut Vec<Offset>,
|
||||||
|
) -> CountingReplacer<'r> {
|
||||||
|
CountingReplacer { replace: replace, count: count, offsets: offsets, }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> Replacer for CountingReplacer<'r> {
|
impl<'r> Replacer for CountingReplacer<'r> {
|
||||||
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
|
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
|
||||||
*self.count += 1;
|
*self.count += 1;
|
||||||
|
let start = dst.len();
|
||||||
caps.expand(self.replace, dst);
|
caps.expand(self.replace, dst);
|
||||||
|
let end = dst.len();
|
||||||
|
if start != end {
|
||||||
|
self.offsets.push(Offset::new(start, end));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,9 +312,10 @@ impl<W: WriteColor> Printer<W> {
|
|||||||
}
|
}
|
||||||
if self.replace.is_some() {
|
if self.replace.is_some() {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
let mut offsets = Vec::new();
|
||||||
let line = {
|
let line = {
|
||||||
let replacer = CountingReplacer::new(
|
let replacer = CountingReplacer::new(
|
||||||
self.replace.as_ref().unwrap(), &mut count);
|
self.replace.as_ref().unwrap(), &mut count, &mut offsets);
|
||||||
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) {
|
||||||
@ -295,44 +325,40 @@ impl<W: WriteColor> Printer<W> {
|
|||||||
self.write_eol();
|
self.write_eol();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.write(&line);
|
self.write_matched_line(offsets, &*line, false);
|
||||||
if line.last() != Some(&self.eol) {
|
|
||||||
self.write_eol();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if self.only_matching {
|
let buf = if self.only_matching {
|
||||||
let buf = &buf[start + match_start..start + match_end];
|
&buf[start + match_start..start + match_end]
|
||||||
self.write_matched_line(re, buf, true);
|
|
||||||
} else {
|
} else {
|
||||||
self.write_matched_line(re, &buf[start..end], false);
|
&buf[start..end]
|
||||||
|
};
|
||||||
|
if self.max_columns.map_or(false, |m| buf.len() > m) {
|
||||||
|
let count = re.find_iter(buf).count();
|
||||||
|
let msg = format!("[Omitted long line with {} matches]", count);
|
||||||
|
self.write_colored(msg.as_bytes(), |colors| colors.matched());
|
||||||
|
self.write_eol();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
let only_match = self.only_matching;
|
||||||
|
self.write_matched_line(
|
||||||
|
re.find_iter(buf).map(|x| Offset::from(&x)), buf, only_match);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_matched_line(
|
fn write_matched_line<I>(&mut self, offsets: I, buf: &[u8], only_match: bool)
|
||||||
&mut self,
|
where I: IntoIterator<Item=Offset>,
|
||||||
re: &Regex,
|
{
|
||||||
buf: &[u8],
|
|
||||||
only_match: bool,
|
|
||||||
) {
|
|
||||||
if self.max_columns.map_or(false, |m| buf.len() > m) {
|
|
||||||
let count = re.find_iter(buf).count();
|
|
||||||
let msg = format!("[Omitted long line with {} matches]", count);
|
|
||||||
self.write_colored(msg.as_bytes(), |colors| colors.matched());
|
|
||||||
self.write_eol();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if !self.wtr.supports_color() || self.colors.matched().is_none() {
|
if !self.wtr.supports_color() || self.colors.matched().is_none() {
|
||||||
self.write(buf);
|
self.write(buf);
|
||||||
} else if only_match {
|
} else if only_match {
|
||||||
self.write_colored(buf, |colors| colors.matched());
|
self.write_colored(buf, |colors| colors.matched());
|
||||||
} else {
|
} else {
|
||||||
let mut last_written = 0;
|
let mut last_written = 0;
|
||||||
for m in re.find_iter(buf) {
|
for o in offsets {
|
||||||
self.write(&buf[last_written..m.start()]);
|
self.write(&buf[last_written..o.start]);
|
||||||
self.write_colored(
|
self.write_colored(
|
||||||
&buf[m.start()..m.end()], |colors| colors.matched());
|
&buf[o.start..o.end], |colors| colors.matched());
|
||||||
last_written = m.end();
|
last_written = o.end;
|
||||||
}
|
}
|
||||||
self.write(&buf[last_written..]);
|
self.write(&buf[last_written..]);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user