1use anyhow::{Context, Result};
2use assets::Assets;
3use collections::BTreeMap;
4use gpui::{keymap::Binding, MutableAppContext};
5use serde::Deserialize;
6use serde_json::value::RawValue;
7
8#[derive(Deserialize)]
9struct ActionWithData<'a>(#[serde(borrow)] &'a str, #[serde(borrow)] &'a RawValue);
10type ActionSetsByContext<'a> = BTreeMap<&'a str, ActionsByKeystroke<'a>>;
11type ActionsByKeystroke<'a> = BTreeMap<&'a str, &'a RawValue>;
12
13pub fn load_built_in_keymaps(cx: &mut MutableAppContext) {
14 for path in ["keymaps/default.json", "keymaps/vim.json"] {
15 load_keymap(
16 cx,
17 std::str::from_utf8(Assets::get(path).unwrap().data.as_ref()).unwrap(),
18 )
19 .unwrap();
20 }
21}
22
23pub fn load_keymap(cx: &mut MutableAppContext, content: &str) -> Result<()> {
24 let actions: ActionSetsByContext = serde_json::from_str(content)?;
25 for (context, actions) in actions {
26 let context = if context.is_empty() {
27 None
28 } else {
29 Some(context)
30 };
31 cx.add_bindings(
32 actions
33 .into_iter()
34 .map(|(keystroke, action)| {
35 let action = action.get();
36 let action = if action.starts_with('[') {
37 let ActionWithData(name, data) = serde_json::from_str(action)?;
38 cx.deserialize_action(name, Some(data.get()))
39 } else {
40 let name = serde_json::from_str(action)?;
41 cx.deserialize_action(name, None)
42 }
43 .with_context(|| {
44 format!(
45 "invalid binding value for keystroke {keystroke}, context {context:?}"
46 )
47 })?;
48 Binding::load(keystroke, action, context)
49 })
50 .collect::<Result<Vec<_>>>()?,
51 )
52 }
53 Ok(())
54}