From 58807f0dd2e54a623c82a078023b04bd54ad265b Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Wed, 16 Jul 2025 12:00:47 -0500 Subject: [PATCH] keymap_ui: Create language for Zed keybind context (#34558) Closes #ISSUE Creates a new language in the languages crate for the DSL used in Zed keybinding context. Previously, keybind context was highlighted as Rust in the keymap UI due to the expression syntax of Rust matching that of the context DSL, however, this had the side effect of highlighting upper case contexts (e.g. `Editor`) however Rust types would be highlighted based on the theme. By extracting only the necessary pieces of the Rust language `highlights.scm`, `brackets.scm`, and `config.toml`, and continuing to use the Rust grammar, we get a better result across different themes Release Notes: - N/A *or* Added/Fixed/Improved ... --- crates/languages/src/lib.rs | 4 ++ .../src/zed-keybind-context/brackets.scm | 1 + .../src/zed-keybind-context/config.toml | 6 +++ .../src/zed-keybind-context/highlights.scm | 23 ++++++++++ crates/settings_ui/src/keybindings.rs | 43 +++++++++++++------ crates/ui_input/src/ui_input.rs | 1 + 6 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 crates/languages/src/zed-keybind-context/brackets.scm create mode 100644 crates/languages/src/zed-keybind-context/config.toml create mode 100644 crates/languages/src/zed-keybind-context/highlights.scm diff --git a/crates/languages/src/lib.rs b/crates/languages/src/lib.rs index 3db015a241..431c051081 100644 --- a/crates/languages/src/lib.rs +++ b/crates/languages/src/lib.rs @@ -212,6 +212,10 @@ pub fn init(languages: Arc, node: NodeRuntime, cx: &mut App) { name: "gitcommit", ..Default::default() }, + LanguageInfo { + name: "zed-keybind-context", + ..Default::default() + }, ]; for registration in built_in_languages { diff --git a/crates/languages/src/zed-keybind-context/brackets.scm b/crates/languages/src/zed-keybind-context/brackets.scm new file mode 100644 index 0000000000..d086b2e98d --- /dev/null +++ b/crates/languages/src/zed-keybind-context/brackets.scm @@ -0,0 +1 @@ +("(" @open ")" @close) diff --git a/crates/languages/src/zed-keybind-context/config.toml b/crates/languages/src/zed-keybind-context/config.toml new file mode 100644 index 0000000000..a999c70f66 --- /dev/null +++ b/crates/languages/src/zed-keybind-context/config.toml @@ -0,0 +1,6 @@ +name = "Zed Keybind Context" +grammar = "rust" +autoclose_before = ")" +brackets = [ + { start = "(", end = ")", close = true, newline = false }, +] diff --git a/crates/languages/src/zed-keybind-context/highlights.scm b/crates/languages/src/zed-keybind-context/highlights.scm new file mode 100644 index 0000000000..9c5ec58eae --- /dev/null +++ b/crates/languages/src/zed-keybind-context/highlights.scm @@ -0,0 +1,23 @@ +(identifier) @variable + +[ + "(" + ")" +] @punctuation.bracket + +[ + (integer_literal) + (float_literal) +] @number + +(boolean_literal) @boolean + +[ + "!=" + "==" + "=>" + ">" + "&&" + "||" + "!" +] @operator diff --git a/crates/settings_ui/src/keybindings.rs b/crates/settings_ui/src/keybindings.rs index c83a4c2423..2bfa6f820e 100644 --- a/crates/settings_ui/src/keybindings.rs +++ b/crates/settings_ui/src/keybindings.rs @@ -505,7 +505,7 @@ impl KeymapEditor { fn process_bindings( json_language: Arc, - rust_language: Arc, + zed_keybind_context_language: Arc, cx: &mut App, ) -> (Vec, Vec) { let key_bindings_ptr = cx.key_bindings(); @@ -536,7 +536,10 @@ impl KeymapEditor { let context = key_binding .predicate() .map(|predicate| { - KeybindContextString::Local(predicate.to_string().into(), rust_language.clone()) + KeybindContextString::Local( + predicate.to_string().into(), + zed_keybind_context_language.clone(), + ) }) .unwrap_or(KeybindContextString::Global); @@ -588,11 +591,12 @@ impl KeymapEditor { let workspace = self.workspace.clone(); cx.spawn(async move |this, cx| { let json_language = load_json_language(workspace.clone(), cx).await; - let rust_language = load_rust_language(workspace.clone(), cx).await; + let zed_keybind_context_language = + load_keybind_context_language(workspace.clone(), cx).await; let (action_query, keystroke_query) = this.update(cx, |this, cx| { let (key_bindings, string_match_candidates) = - Self::process_bindings(json_language, rust_language, cx); + Self::process_bindings(json_language, zed_keybind_context_language, cx); this.keybinding_conflict_state = ConflictState::new(&key_bindings); @@ -1590,13 +1594,20 @@ impl KeybindingEditorModal { } let editor_entity = input.editor().clone(); + let workspace = workspace.clone(); cx.spawn(async move |_input_handle, cx| { let contexts = cx .background_spawn(async { collect_contexts_from_assets() }) .await; + let language = load_keybind_context_language(workspace, cx).await; editor_entity - .update(cx, |editor, _cx| { + .update(cx, |editor, cx| { + if let Some(buffer) = editor.buffer().read(cx).as_singleton() { + buffer.update(cx, |buffer, cx| { + buffer.set_language(Some(language), cx); + }); + } editor.set_completion_provider(Some(std::rc::Rc::new( KeyContextCompletionProvider { contexts }, ))); @@ -2131,25 +2142,31 @@ async fn load_json_language(workspace: WeakEntity, cx: &mut AsyncApp) }); } -async fn load_rust_language(workspace: WeakEntity, cx: &mut AsyncApp) -> Arc { - let rust_language_task = workspace +async fn load_keybind_context_language( + workspace: WeakEntity, + cx: &mut AsyncApp, +) -> Arc { + let language_task = workspace .read_with(cx, |workspace, cx| { workspace .project() .read(cx) .languages() - .language_for_name("Rust") + .language_for_name("Zed Keybind Context") }) - .context("Failed to load Rust language") + .context("Failed to load Zed Keybind Context language") .log_err(); - let rust_language = match rust_language_task { - Some(task) => task.await.context("Failed to load Rust language").log_err(), + let language = match language_task { + Some(task) => task + .await + .context("Failed to load Zed Keybind Context language") + .log_err(), None => None, }; - return rust_language.unwrap_or_else(|| { + return language.unwrap_or_else(|| { Arc::new(Language::new( LanguageConfig { - name: "Rust".into(), + name: "Zed Keybind Context".into(), ..Default::default() }, Some(tree_sitter_rust::LANGUAGE.into()), diff --git a/crates/ui_input/src/ui_input.rs b/crates/ui_input/src/ui_input.rs index ca2dea36df..18aa732e81 100644 --- a/crates/ui_input/src/ui_input.rs +++ b/crates/ui_input/src/ui_input.rs @@ -135,6 +135,7 @@ impl Render for SingleLineInput { let editor_style = EditorStyle { background: theme_color.ghost_element_background, local_player: cx.theme().players().local(), + syntax: cx.theme().syntax().clone(), text: text_style, ..Default::default() };