Watch ~/.zed/bindings.json file for custom key bindings
Co-authored-by: Keith Simmons <keith@zed.dev>
This commit is contained in:
parent
92a5c30389
commit
be11f63f1e
8 changed files with 110 additions and 60 deletions
|
@ -5,50 +5,57 @@ use gpui::{keymap::Binding, MutableAppContext};
|
|||
use serde::Deserialize;
|
||||
use serde_json::value::RawValue;
|
||||
|
||||
#[derive(Deserialize, Default, Clone)]
|
||||
#[serde(transparent)]
|
||||
pub struct KeyMapFile(BTreeMap<String, ActionsByKeystroke>);
|
||||
|
||||
type ActionsByKeystroke = BTreeMap<String, Box<RawValue>>;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ActionWithData<'a>(#[serde(borrow)] &'a str, #[serde(borrow)] &'a RawValue);
|
||||
type ActionSetsByContext<'a> = BTreeMap<&'a str, ActionsByKeystroke<'a>>;
|
||||
type ActionsByKeystroke<'a> = BTreeMap<&'a str, &'a RawValue>;
|
||||
|
||||
pub fn load_built_in_keymaps(cx: &mut MutableAppContext) {
|
||||
for path in ["keymaps/default.json", "keymaps/vim.json"] {
|
||||
load_keymap(
|
||||
cx,
|
||||
std::str::from_utf8(Assets::get(path).unwrap().data.as_ref()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
impl KeyMapFile {
|
||||
pub fn load_defaults(cx: &mut MutableAppContext) {
|
||||
for path in ["keymaps/default.json", "keymaps/vim.json"] {
|
||||
Self::load(path, cx).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_keymap(cx: &mut MutableAppContext, content: &str) -> Result<()> {
|
||||
let actions: ActionSetsByContext = serde_json::from_str(content)?;
|
||||
for (context, actions) in actions {
|
||||
let context = if context.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(context)
|
||||
};
|
||||
cx.add_bindings(
|
||||
actions
|
||||
.into_iter()
|
||||
.map(|(keystroke, action)| {
|
||||
let action = action.get();
|
||||
let action = if action.starts_with('[') {
|
||||
let ActionWithData(name, data) = serde_json::from_str(action)?;
|
||||
cx.deserialize_action(name, Some(data.get()))
|
||||
} else {
|
||||
let name = serde_json::from_str(action)?;
|
||||
cx.deserialize_action(name, None)
|
||||
}
|
||||
.with_context(|| {
|
||||
format!(
|
||||
pub fn load(asset_path: &str, cx: &mut MutableAppContext) -> Result<()> {
|
||||
let content = Assets::get(asset_path).unwrap().data;
|
||||
let content_str = std::str::from_utf8(content.as_ref()).unwrap();
|
||||
Ok(serde_json::from_str::<Self>(content_str)?.add(cx)?)
|
||||
}
|
||||
|
||||
pub fn add(self, cx: &mut MutableAppContext) -> Result<()> {
|
||||
for (context, actions) in self.0 {
|
||||
let context = if context.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(context)
|
||||
};
|
||||
cx.add_bindings(
|
||||
actions
|
||||
.into_iter()
|
||||
.map(|(keystroke, action)| {
|
||||
let action = action.get();
|
||||
let action = if action.starts_with('[') {
|
||||
let ActionWithData(name, data) = serde_json::from_str(action)?;
|
||||
cx.deserialize_action(name, Some(data.get()))
|
||||
} else {
|
||||
let name = serde_json::from_str(action)?;
|
||||
cx.deserialize_action(name, None)
|
||||
}
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"invalid binding value for keystroke {keystroke}, context {context:?}"
|
||||
)
|
||||
})?;
|
||||
Binding::load(keystroke, action, context)
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?,
|
||||
)
|
||||
})?;
|
||||
Binding::load(&keystroke, action, context.as_deref())
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?,
|
||||
)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue