mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 08:54:04 +00:00
11058765be
Closes https://github.com/zed-industries/zed/issues/16380 Currently brackets are highlighted with `editor.document_highlight.read_background`. This commit adds a separate `editor.document_highlight.bracket_background` theme setting so bracket highlights can be made more prominent without doing the same to other highlights, making the display too busy. (My own theme) https://github.com/user-attachments/assets/29a8c05e-2f1a-4c16-9be8-a4b4cb143548 I set defaults for light and dark theme that I hope are sensible and not too obnoxious, but noticeable so people can change it if they don't like it. Release Notes: - Added `editor.document_highlight.bracket_background` field to the theme to set background color of highlighted brackets. - This will fall back to `editor.document_highlight.read_background`, if not set. <img width="355" alt="Screenshot 2024-09-08 at 8 46 57 AM" src="https://github.com/user-attachments/assets/3270bb4d-19f5-4b34-8003-982377b2ceb6"> <img width="444" alt="Screenshot 2024-09-08 at 9 03 27 AM" src="https://github.com/user-attachments/assets/3b12d84d-913c-4bde-9132-9b10f4a8d49b"> --------- Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
151 lines
5 KiB
Rust
151 lines
5 KiB
Rust
use gpui::ViewContext;
|
|
use language::CursorShape;
|
|
|
|
use crate::{Editor, RangeToAnchorExt};
|
|
|
|
enum MatchingBracketHighlight {}
|
|
|
|
pub fn refresh_matching_bracket_highlights(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
|
|
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 snapshot = editor.snapshot(cx);
|
|
let head = newest_selection.head();
|
|
let mut tail = head;
|
|
if (editor.cursor_shape == CursorShape::Block || editor.cursor_shape == CursorShape::Hollow)
|
|
&& head < snapshot.buffer_snapshot.len()
|
|
{
|
|
tail += 1;
|
|
}
|
|
|
|
if let Some((opening_range, closing_range)) = snapshot
|
|
.buffer_snapshot
|
|
.innermost_enclosing_bracket_ranges(head..tail, None)
|
|
{
|
|
editor.highlight_background::<MatchingBracketHighlight>(
|
|
&[
|
|
opening_range.to_anchors(&snapshot.buffer_snapshot),
|
|
closing_range.to_anchors(&snapshot.buffer_snapshot),
|
|
],
|
|
|theme| theme.editor_document_highlight_bracket_background,
|
|
cx,
|
|
)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::{editor_tests::init_test, test::editor_lsp_test_context::EditorLspTestContext};
|
|
use indoc::indoc;
|
|
use language::{BracketPair, BracketPairConfig, Language, LanguageConfig, LanguageMatcher};
|
|
|
|
#[gpui::test]
|
|
async fn test_matching_bracket_highlights(cx: &mut gpui::TestAppContext) {
|
|
init_test(cx, |_| {});
|
|
|
|
let mut cx = EditorLspTestContext::new(
|
|
Language::new(
|
|
LanguageConfig {
|
|
name: "Rust".into(),
|
|
matcher: LanguageMatcher {
|
|
path_suffixes: vec!["rs".to_string()],
|
|
..Default::default()
|
|
},
|
|
brackets: BracketPairConfig {
|
|
pairs: vec![
|
|
BracketPair {
|
|
start: "{".to_string(),
|
|
end: "}".to_string(),
|
|
close: false,
|
|
surround: false,
|
|
newline: true,
|
|
},
|
|
BracketPair {
|
|
start: "(".to_string(),
|
|
end: ")".to_string(),
|
|
close: false,
|
|
surround: false,
|
|
newline: true,
|
|
},
|
|
],
|
|
..Default::default()
|
|
},
|
|
..Default::default()
|
|
},
|
|
Some(tree_sitter_rust::LANGUAGE.into()),
|
|
)
|
|
.with_brackets_query(indoc! {r#"
|
|
("{" @open "}" @close)
|
|
("(" @open ")" @close)
|
|
"#})
|
|
.unwrap(),
|
|
Default::default(),
|
|
cx,
|
|
)
|
|
.await;
|
|
|
|
// positioning cursor inside bracket highlights both
|
|
cx.set_state(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(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(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(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
|
|
cx.set_state(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);
|
|
}
|
|
"#});
|
|
}
|
|
}
|