summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2023-08-12 22:08:54 -0400
committerGitHub <noreply@github.com>2023-08-12 22:08:54 -0400
commitae26b5497cc5f7b958d7fa2683c0ebd002109c54 (patch)
tree230bdce921d98b7c3e208d7af01eebf0c896f297
parenta48a368b423da5190e54c637568264d58a3dbf9d (diff)
Fix handling of tabs in grep output (#1507)
Fixes #1501
-rw-r--r--src/handlers/grep.rs59
1 files changed, 44 insertions, 15 deletions
diff --git a/src/handlers/grep.rs b/src/handlers/grep.rs
index 772baf11..8c3b6ce8 100644
--- a/src/handlers/grep.rs
+++ b/src/handlers/grep.rs
@@ -26,6 +26,20 @@ pub struct GrepLine<'b> {
pub submatches: Option<Vec<(usize, usize)>>,
}
+impl<'b> GrepLine<'b> {
+ fn expand_tabs(&mut self, tab_cfg: &tabs::TabCfg) {
+ let old_len = self.code.len();
+ self.code = tabs::expand(&self.code, tab_cfg).into();
+ let shift = self.code.len().saturating_sub(old_len);
+ self.submatches = self.submatches.as_ref().map(|submatches| {
+ submatches
+ .iter()
+ .map(|(a, b)| (a + shift, b + shift))
+ .collect()
+ });
+ }
+}
+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LineType {
@@ -159,17 +173,17 @@ impl<'a> StateMachine<'a> {
}
// Emit the actual grep hit line
let code_style_sections = match (&grep_line.line_type, &grep_line.submatches) {
- (LineType::Match, Some(submatches)) => {
+ (LineType::Match, Some(_)) => {
// We expand tabs at this late stage because
// the tabs are escaped in the JSON, so
// expansion must come after JSON parsing.
// (At the time of writing, we are in this
// arm iff we are handling `ripgrep --json`
// output.)
- grep_line.code = tabs::expand(&grep_line.code, &self.config.tab_cfg).into();
+ grep_line.expand_tabs(&self.config.tab_cfg);
make_style_sections(
&grep_line.code,
- submatches,
+ &grep_line.submatches.unwrap(),
self.config.grep_match_word_style,
self.config.grep_match_line_style,
)
@@ -186,7 +200,8 @@ impl<'a> StateMachine<'a> {
&self.raw_line,
self.config.grep_match_word_style,
self.config.grep_match_line_style,
- &grep_line,
+ &grep_line.path,
+ grep_line.line_number,
)
.unwrap_or(StyleSectionSpecifier::Style(
self.config.grep_match_line_style,
@@ -297,17 +312,17 @@ impl<'a> StateMachine<'a> {
fn _emit_classic_format_code(&mut self, mut grep_line: GrepLine) -> std::io::Result<()> {
let code_style_sections = match (&grep_line.line_type, &grep_line.submatches) {
- (LineType::Match, Some(submatches)) => {
+ (LineType::Match, Some(_)) => {
// We expand tabs at this late stage because
// the tabs are escaped in the JSON, so
// expansion must come after JSON parsing.
// (At the time of writing, we are in this
// arm iff we are handling `ripgrep --json`
// output.)
- grep_line.code = tabs::expand(&grep_line.code, &self.config.tab_cfg).into();
+ grep_line.expand_tabs(&self.config.tab_cfg);
make_style_sections(
&grep_line.code,
- submatches,
+ &grep_line.submatches.unwrap(),
self.config.grep_match_word_style,
self.config.grep_match_line_style,
)
@@ -324,7 +339,8 @@ impl<'a> StateMachine<'a> {
&self.raw_line,
self.config.grep_match_word_style,
self.config.grep_match_line_style,
- &grep_line,
+ &grep_line.path,
+ grep_line.line_number,
)
.unwrap_or(StyleSectionSpecifier::Style(
self.config.grep_match_line_style,
@@ -369,13 +385,14 @@ fn get_code_style_sections<'b>(
raw_line: &'b str,
match_style: Style,
non_match_style: Style,
- grep: &GrepLine,
+ path: &str,
+ line_number: Option<usize>,
) -> Option<StyleSectionSpecifier<'b>> {
if let Some(prefix_end) = ansi::ansi_preserving_index(
raw_line,
- match grep.line_number {
- Some(n) => format!("{}:{}:", grep.path, n).len() - 1,
- None => grep.path.len(),
+ match line_number {
+ Some(n) => format!("{}:{}:", path, n).len() - 1,
+ None => path.len(),
},
) {
let match_style_sections = ansi::parse_style_sections(&raw_line[(prefix_end + 1)..])
@@ -1101,7 +1118,7 @@ mod tests {
let grep = parse_grep_line(&stripped).unwrap();
assert_eq!(
- get_code_style_sections(&working_example, hit, miss, &grep),
+ get_code_style_sections(&working_example, hit, miss, &grep.path, grep.line_number),
Some(StyleSectionSpecifier::StyleSections(vec![
(miss, " - "),
(hit, "kind: Service"),
@@ -1114,7 +1131,13 @@ mod tests {
let broken_grep = parse_grep_line(&broken_stripped).unwrap();
assert_eq!(
- get_code_style_sections(&broken_example, hit, miss, &broken_grep),
+ get_code_style_sections(
+ &broken_example,
+ hit,
+ miss,
+ &broken_grep.path,
+ broken_grep.line_number
+ ),
Some(StyleSectionSpecifier::StyleSections(vec![(
hit,
"kind: Service"
@@ -1126,7 +1149,13 @@ mod tests {
let plus_grep = parse_grep_line(&plus_stripped).unwrap();
assert_eq!(
- get_code_style_sections(&plus_example, hit, miss, &plus_grep),
+ get_code_style_sections(
+ &plus_example,
+ hit,
+ miss,
+ &plus_grep.path,
+ plus_grep.line_number
+ ),
Some(StyleSectionSpecifier::StyleSections(vec![
(miss, " + let (style, non_emph_style) = "),
(hit, "match"),