From b9c48685e8abce35d4d6e7a882af7801722140c6 Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Mon, 10 Mar 2025 17:20:48 -0400 Subject: [PATCH] terminal: Support trailing `:description or error message` after file path (#26401) Closes #25086 Release Notes: - Fixed a bug where file paths in the built in terminal of the format `path/to/file.ext:row:col:description or error message` would not be correctly identified as file paths due to the colon & additional text at the end --- crates/terminal/src/terminal.rs | 55 ++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 487a260c24..f7adfd6088 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -929,18 +929,51 @@ impl Terminal { } else if let Some(word_match) = regex_match_at(term, point, &mut self.word_regex) { let file_path = term.bounds_to_string(*word_match.start(), *word_match.end()); - let (sanitized_match, sanitized_word) = + let (sanitized_match, sanitized_word) = 'sanitize: { + let mut word_match = word_match; + let mut file_path = file_path; + if is_path_surrounded_by_common_symbols(&file_path) { - ( - Match::new( - word_match.start().add(term, Boundary::Cursor, 1), - word_match.end().sub(term, Boundary::Cursor, 1), - ), - file_path[1..file_path.len() - 1].to_owned(), - ) - } else { - (word_match, file_path) - }; + word_match = Match::new( + word_match.start().add(term, Boundary::Cursor, 1), + word_match.end().sub(term, Boundary::Cursor, 1), + ); + file_path = file_path[1..file_path.len() - 1].to_owned(); + } + + let mut colon_count = 0; + for c in file_path.chars() { + if c == ':' { + colon_count += 1; + } + } + // strip trailing comment after colon in case of + // file/at/path.rs:row:column:description or error message + // so that the file path is `file/at/path.rs:row:column` + if colon_count > 2 { + let last_index = file_path.rfind(':').unwrap(); + let prev_is_digit = last_index > 0 + && file_path + .chars() + .nth(last_index - 1) + .map_or(false, |c| c.is_ascii_digit()); + let next_is_digit = last_index < file_path.len() - 1 + && file_path + .chars() + .nth(last_index + 1) + .map_or(true, |c| c.is_ascii_digit()); + if prev_is_digit && !next_is_digit { + let stripped_len = file_path.len() - last_index; + word_match = Match::new( + *word_match.start(), + word_match.end().sub(term, Boundary::Cursor, stripped_len), + ); + file_path = file_path[0..last_index].to_owned(); + } + } + + break 'sanitize (word_match, file_path); + }; Some((sanitized_word, false, sanitized_match)) } else {