highlight both brackets, only when empty selection, and add test

This commit is contained in:
Keith Simmons 2022-07-05 15:19:05 -07:00
parent 9b36e3d009
commit 1f3dc2f534
6 changed files with 201 additions and 50 deletions

View file

@ -1,6 +1,6 @@
use gpui::ViewContext;
use crate::Editor;
use crate::{Editor, RangeToAnchorExt};
enum MatchingBracketHighlight {}
@ -8,33 +8,135 @@ pub fn refresh_matching_bracket_highlights(editor: &mut Editor, cx: &mut ViewCon
editor.clear_background_highlights::<MatchingBracketHighlight>(cx);
let newest_selection = editor.selections.newest::<usize>(cx);
// Don't highlight brackets if the selection isn't empty
if !newest_selection.is_empty() {
return;
}
let head = newest_selection.head();
let snapshot = editor.snapshot(cx);
if let Some((opening_range, closing_range)) = snapshot
.buffer_snapshot
.enclosing_bracket_ranges(newest_selection.range())
.enclosing_bracket_ranges(head..head)
{
let head = newest_selection.head();
let range_to_highlight = if opening_range.contains(&head) {
Some(closing_range)
} else if closing_range.contains(&head) {
Some(opening_range)
} else {
None
};
if let Some(range_to_highlight) = range_to_highlight {
let anchor_range = snapshot
.buffer_snapshot
.anchor_before(range_to_highlight.start)
..snapshot
.buffer_snapshot
.anchor_after(range_to_highlight.end);
editor.highlight_background::<MatchingBracketHighlight>(
vec![anchor_range],
|theme| theme.editor.document_highlight_read_background,
cx,
)
}
editor.highlight_background::<MatchingBracketHighlight>(
vec![
opening_range.to_anchors(&snapshot.buffer_snapshot),
closing_range.to_anchors(&snapshot.buffer_snapshot),
],
|theme| theme.editor.document_highlight_read_background,
cx,
)
}
}
#[cfg(test)]
mod tests {
use indoc::indoc;
use language::{BracketPair, Language, LanguageConfig};
use crate::test::EditorLspTestContext;
use super::*;
#[gpui::test]
async fn test_matching_bracket_highlights(cx: &mut gpui::TestAppContext) {
let mut cx = EditorLspTestContext::new(
Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
brackets: vec![
BracketPair {
start: "{".to_string(),
end: "}".to_string(),
close: false,
newline: true,
},
BracketPair {
start: "(".to_string(),
end: ")".to_string(),
close: false,
newline: true,
},
],
..Default::default()
},
Some(tree_sitter_rust::language()),
)
.with_brackets_query(indoc! {r#"
("{" @open "}" @close)
("(" @open ")" @close)
"#})
.unwrap(),
Default::default(),
cx,
)
.await;
// positioning cursor inside bracket highlights both
cx.set_state_by(
vec!['|'.into()],
indoc! {r#"
pub fn test("Test |argument") {
another_test(1, 2, 3);
}"#},
);
cx.assert_editor_background_highlights::<MatchingBracketHighlight>(indoc! {r#"
pub fn test[(]"Test argument"[)] {
another_test(1, 2, 3);
}"#});
cx.set_state_by(
vec!['|'.into()],
indoc! {r#"
pub fn test("Test argument") {
another_test(1, |2, 3);
}"#},
);
cx.assert_editor_background_highlights::<MatchingBracketHighlight>(indoc! {r#"
pub fn test("Test argument") {
another_test[(]1, 2, 3[)];
}"#});
cx.set_state_by(
vec!['|'.into()],
indoc! {r#"
pub fn test("Test argument") {
another|_test(1, 2, 3);
}"#},
);
cx.assert_editor_background_highlights::<MatchingBracketHighlight>(indoc! {r#"
pub fn test("Test argument") [{]
another_test(1, 2, 3);
[}]"#});
// positioning outside of brackets removes highlight
cx.set_state_by(
vec!['|'.into()],
indoc! {r#"
pub f|n test("Test argument") {
another_test(1, 2, 3);
}"#},
);
cx.assert_editor_background_highlights::<MatchingBracketHighlight>(indoc! {r#"
pub fn test("Test argument") {
another_test(1, 2, 3);
}"#});
// non empty selection dismisses highlight
// positioning outside of brackets removes highlight
cx.set_state_by(
vec![('<', '>').into()],
indoc! {r#"
pub fn test("Te<st arg>ument") {
another_test(1, 2, 3);
}"#},
);
cx.assert_editor_background_highlights::<MatchingBracketHighlight>(indoc! {r#"
pub fn test("Test argument") {
another_test(1, 2, 3);
}"#});
}
}