Added experimental keymaps support

This commit is contained in:
Mikayla Maki 2022-08-22 14:49:01 -07:00
parent fa48440ba3
commit 0a40cc0370
6 changed files with 54 additions and 20 deletions

View file

@ -1,4 +1,4 @@
use crate::parse_json_with_comments;
use crate::{parse_json_with_comments, Settings};
use anyhow::{Context, Result};
use assets::Assets;
use collections::BTreeMap;
@ -10,6 +10,7 @@ use schemars::{
};
use serde::Deserialize;
use serde_json::{value::RawValue, Value};
use util::ResultExt;
#[derive(Deserialize, Default, Clone, JsonSchema)]
#[serde(transparent)]
@ -41,7 +42,9 @@ struct ActionWithData(Box<str>, Box<RawValue>);
impl KeymapFileContent {
pub fn load_defaults(cx: &mut MutableAppContext) {
for path in ["keymaps/default.json", "keymaps/vim.json"] {
let mut paths = vec!["keymaps/default.json", "keymaps/vim.json"];
paths.extend(cx.global::<Settings>().experiments.keymap_files());
for path in paths {
Self::load(path, cx).unwrap();
}
}
@ -56,26 +59,27 @@ impl KeymapFileContent {
for KeymapBlock { context, bindings } in self.0 {
let bindings = bindings
.into_iter()
.map(|(keystroke, action)| {
.filter_map(|(keystroke, action)| {
let action = action.0.get();
// This is a workaround for a limitation in serde: serde-rs/json#497
// We want to deserialize the action data as a `RawValue` so that we can
// deserialize the action itself dynamically directly from the JSON
// string. But `RawValue` currently does not work inside of an untagged enum.
let action = if action.starts_with('[') {
let ActionWithData(name, data) = serde_json::from_str(action)?;
if action.starts_with('[') {
let ActionWithData(name, data) = serde_json::from_str(action).log_err()?;
cx.deserialize_action(&name, Some(data.get()))
} else {
let name = serde_json::from_str(action)?;
let name = serde_json::from_str(action).log_err()?;
cx.deserialize_action(name, None)
}
.with_context(|| {
format!(
"invalid binding value for keystroke {keystroke}, context {context:?}"
)
})?;
Binding::load(&keystroke, action, context.as_deref())
})
.log_err()
.map(|action| Binding::load(&keystroke, action, context.as_deref()))
})
.collect::<Result<Vec<_>>>()?;

View file

@ -20,6 +20,7 @@ pub use keymap_file::{keymap_file_json_schema, KeymapFileContent};
#[derive(Clone)]
pub struct Settings {
pub experiments: FeatureFlags,
pub projects_online_by_default: bool,
pub buffer_font_family: FamilyId,
pub default_buffer_font_size: f32,
@ -38,6 +39,25 @@ pub struct Settings {
pub theme: Arc<Theme>,
}
#[derive(Copy, Clone, Debug, Default, Deserialize, JsonSchema)]
pub struct FeatureFlags {
modal_terminal: Option<bool>,
}
impl FeatureFlags {
pub fn keymap_files(&self) -> Vec<&'static str> {
let mut res = vec![];
if self.modal_terminal() {
res.push("keymaps/experiments/modal_terminal.json")
}
res
}
pub fn modal_terminal(&self) -> bool {
self.modal_terminal.unwrap_or_default()
}
}
#[derive(Clone, Debug, Default, Deserialize, JsonSchema)]
pub struct EditorSettings {
pub tab_size: Option<NonZeroU32>,
@ -139,6 +159,7 @@ pub enum WorkingDirectory {
#[derive(Clone, Debug, Default, Deserialize, JsonSchema)]
pub struct SettingsFileContent {
pub experiments: Option<FeatureFlags>,
#[serde(default)]
pub projects_online_by_default: Option<bool>,
#[serde(default)]
@ -189,6 +210,7 @@ impl Settings {
.unwrap();
Self {
experiments: FeatureFlags::default(),
buffer_font_family: font_cache
.load_family(&[defaults.buffer_font_family.as_ref().unwrap()])
.unwrap(),
@ -247,6 +269,7 @@ impl Settings {
);
merge(&mut self.vim_mode, data.vim_mode);
merge(&mut self.autosave, data.autosave);
merge(&mut self.experiments, data.experiments);
// Ensure terminal font is loaded, so we can request it in terminal_element layout
if let Some(terminal_font) = &data.terminal.font_family {
@ -308,6 +331,7 @@ impl Settings {
#[cfg(any(test, feature = "test-support"))]
pub fn test(cx: &gpui::AppContext) -> Settings {
Settings {
experiments: FeatureFlags::default(),
buffer_font_family: cx.font_cache().load_family(&["Monaco"]).unwrap(),
buffer_font_size: 14.,
default_buffer_font_size: 14.,