keymap_ui: Syntax highlight context (#33864)

Closes #ISSUE

Uses Rust for syntax highlighting of context in the keymap editor.
Future pass will improve color choice to make colors less abrasive

Release Notes:

- N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Ben Kunkle 2025-07-03 12:26:35 -05:00 committed by GitHub
parent 4e6b7ee3ea
commit fcdd99e244
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 50 additions and 8 deletions

1
Cargo.lock generated
View file

@ -14590,6 +14590,7 @@ dependencies = [
"settings",
"theme",
"tree-sitter-json",
"tree-sitter-rust",
"ui",
"util",
"workspace",

View file

@ -34,6 +34,7 @@ serde.workspace = true
settings.workspace = true
theme.workspace = true
tree-sitter-json.workspace = true
tree-sitter-rust.workspace = true
ui.workspace = true
util.workspace = true
workspace-hack.workspace = true

View file

@ -249,6 +249,7 @@ impl KeymapEditor {
fn process_bindings(
json_language: Arc<Language>,
rust_language: Arc<Language>,
cx: &mut App,
) -> (Vec<ProcessedKeybinding>, Vec<StringMatchCandidate>) {
let key_bindings_ptr = cx.key_bindings();
@ -272,7 +273,9 @@ impl KeymapEditor {
let context = key_binding
.predicate()
.map(|predicate| KeybindContextString::Local(predicate.to_string().into()))
.map(|predicate| {
KeybindContextString::Local(predicate.to_string().into(), rust_language.clone())
})
.unwrap_or(KeybindContextString::Global);
let source = source.map(|source| (source, source.name().into()));
@ -320,11 +323,12 @@ impl KeymapEditor {
fn update_keybindings(&mut self, cx: &mut Context<KeymapEditor>) {
let workspace = self.workspace.clone();
cx.spawn(async move |this, cx| {
let json_language = Self::load_json_language(workspace, cx).await;
let json_language = Self::load_json_language(workspace.clone(), cx).await;
let rust_language = Self::load_rust_language(workspace.clone(), cx).await;
let query = this.update(cx, |this, cx| {
let (key_bindings, string_match_candidates) =
Self::process_bindings(json_language.clone(), cx);
Self::process_bindings(json_language, rust_language, cx);
this.keybindings = key_bindings;
this.string_match_candidates = Arc::new(string_match_candidates);
this.matches = this
@ -375,6 +379,35 @@ impl KeymapEditor {
});
}
async fn load_rust_language(
workspace: WeakEntity<Workspace>,
cx: &mut AsyncApp,
) -> Arc<Language> {
let rust_language_task = workspace
.read_with(cx, |workspace, cx| {
workspace
.project()
.read(cx)
.languages()
.language_for_name("Rust")
})
.context("Failed to load Rust language")
.log_err();
let rust_language = match rust_language_task {
Some(task) => task.await.context("Failed to load Rust language").log_err(),
None => None,
};
return rust_language.unwrap_or_else(|| {
Arc::new(Language::new(
LanguageConfig {
name: "Rust".into(),
..Default::default()
},
Some(tree_sitter_rust::LANGUAGE.into()),
))
});
}
fn dispatch_context(&self, _window: &Window, _cx: &Context<Self>) -> KeyContext {
let mut dispatch_context = KeyContext::new_with_defaults();
dispatch_context.add("KeymapEditor");
@ -550,7 +583,7 @@ struct ProcessedKeybinding {
#[derive(Clone, Debug, IntoElement)]
enum KeybindContextString {
Global,
Local(SharedString),
Local(SharedString, Arc<Language>),
}
impl KeybindContextString {
@ -559,14 +592,14 @@ impl KeybindContextString {
pub fn local(&self) -> Option<&SharedString> {
match self {
KeybindContextString::Global => None,
KeybindContextString::Local(name) => Some(name),
KeybindContextString::Local(name, _) => Some(name),
}
}
pub fn local_str(&self) -> Option<&str> {
match self {
KeybindContextString::Global => None,
KeybindContextString::Local(name) => Some(name),
KeybindContextString::Local(name, _) => Some(name),
}
}
}
@ -574,8 +607,15 @@ impl KeybindContextString {
impl RenderOnce for KeybindContextString {
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
match self {
KeybindContextString::Global => KeybindContextString::GLOBAL.clone(),
KeybindContextString::Local(name) => name,
KeybindContextString::Global => StyledText::new(KeybindContextString::GLOBAL.clone())
.with_highlights([(
0..KeybindContextString::GLOBAL.len(),
gpui::HighlightStyle::color(_cx.theme().colors().text_muted),
)])
.into_any_element(),
KeybindContextString::Local(name, language) => {
SyntaxHighlightedText::new(name, language).into_any_element()
}
}
}
}