perf: fast-path grapheme counts and cache terminal layouts
This commit is contained in:
+35
-1
@@ -4516,7 +4516,12 @@ fn split_lines(text: &str) -> Vec<String> {
|
||||
}
|
||||
|
||||
fn grapheme_count(line: &str) -> usize {
|
||||
line.graphemes(true).count()
|
||||
if line.is_ascii() {
|
||||
// CRLF is the only multi-byte ASCII grapheme.
|
||||
line.len() - line.matches("\r\n").count()
|
||||
} else {
|
||||
line.graphemes(true).count()
|
||||
}
|
||||
}
|
||||
fn grapheme_byte(line: &str, column: usize) -> usize {
|
||||
line.grapheme_indices(true)
|
||||
@@ -5525,6 +5530,35 @@ mod tests {
|
||||
assert!(editor.semantic_tokens().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn semantic_column_bounds_preserve_ascii_tabs_and_unicode_graphemes() {
|
||||
use crate::plugin::SemanticTokenKind;
|
||||
for text in ["a\tb", "e\u{301}界👩🚀"] {
|
||||
let mut editor = editor();
|
||||
editor.apply(vec![Effect::Replace(text.into())]).unwrap();
|
||||
let token = SemanticToken {
|
||||
start: TextPosition { row: 0, column: 0 },
|
||||
end: TextPosition { row: 0, column: 3 },
|
||||
kind: SemanticTokenKind::Variable,
|
||||
modifiers: 0,
|
||||
};
|
||||
editor
|
||||
.replace_semantic_tokens(1, editor.text_revision(), Some(Arc::from([token])))
|
||||
.unwrap();
|
||||
let outside = SemanticToken {
|
||||
end: TextPosition { row: 0, column: 4 },
|
||||
..token
|
||||
};
|
||||
assert!(
|
||||
editor
|
||||
.replace_semantic_tokens(1, editor.text_revision(), Some(Arc::from([outside])))
|
||||
.is_err(),
|
||||
"{text:?}",
|
||||
);
|
||||
assert_eq!(editor.semantic_tokens(), &[token]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_scroll_and_escape_preserve_carets_and_edits_dismiss_normally() {
|
||||
let mut editor = editor();
|
||||
|
||||
Reference in New Issue
Block a user