From 9b06be2aa27146ee39fdbb86facdb189380e8639 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 10 May 2023 11:06:55 -0700 Subject: [PATCH] Define vim_mode setting in vim crate --- crates/editor/src/editor.rs | 12 +++++++--- crates/settings/src/settings.rs | 9 ++----- crates/settings/src/settings_store.rs | 26 +++++++++++++++++++- crates/vim/src/test/vim_test_context.rs | 12 +++++----- crates/vim/src/vim.rs | 32 +++++++++++++++++++++---- 5 files changed, 70 insertions(+), 21 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 2bb9869e6d..964b98450b 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -70,7 +70,7 @@ use scroll::{ }; use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection}; use serde::{Deserialize, Serialize}; -use settings::Settings; +use settings::{Settings, SettingsStore}; use smallvec::SmallVec; use snippet::Snippet; use std::{ @@ -6868,6 +6868,12 @@ impl Editor { .as_singleton() .and_then(|b| b.read(cx).file()), ) { + let vim_mode = cx + .global::() + .untyped_user_settings() + .get("vim_mode") + == Some(&serde_json::Value::Bool(true)); + let settings = cx.global::(); let extension = Path::new(file.file_name(cx)) @@ -6880,12 +6886,12 @@ impl Editor { "save" => "save editor", _ => name, }, - json!({ "File Extension": extension, "Vim Mode": settings.vim_mode, "In Clickhouse": true }), + json!({ "File Extension": extension, "Vim Mode": vim_mode, "In Clickhouse": true }), settings.telemetry(), ); let event = ClickhouseEvent::Editor { file_extension: extension.map(ToString::to_string), - vim_mode: settings.vim_mode, + vim_mode, operation: name, copilot_enabled: settings.features.copilot, copilot_enabled_for_language: settings.show_copilot_suggestions( diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index 6428e4100d..5284d3a69a 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -43,7 +43,6 @@ pub struct Settings { pub hover_popover_enabled: bool, pub show_completions_on_input: bool, pub show_call_status_icon: bool, - pub vim_mode: bool, pub autosave: Autosave, pub default_dock_anchor: DockAnchor, pub editor_defaults: EditorSettings, @@ -65,6 +64,8 @@ pub struct Settings { } impl Setting for Settings { + const KEY: Option<&'static str> = None; + type FileContent = SettingsFileContent; fn load( @@ -93,7 +94,6 @@ impl Setting for Settings { hover_popover_enabled: defaults.hover_popover_enabled.unwrap(), show_completions_on_input: defaults.show_completions_on_input.unwrap(), show_call_status_icon: defaults.show_call_status_icon.unwrap(), - vim_mode: defaults.vim_mode.unwrap(), autosave: defaults.autosave.unwrap(), default_dock_anchor: defaults.default_dock_anchor.unwrap(), editor_defaults: EditorSettings { @@ -550,8 +550,6 @@ pub struct SettingsFileContent { #[serde(default)] pub show_call_status_icon: Option, #[serde(default)] - pub vim_mode: Option, - #[serde(default)] pub autosave: Option, #[serde(default)] pub default_dock_anchor: Option, @@ -647,7 +645,6 @@ impl Settings { hover_popover_enabled: defaults.hover_popover_enabled.unwrap(), show_completions_on_input: defaults.show_completions_on_input.unwrap(), show_call_status_icon: defaults.show_call_status_icon.unwrap(), - vim_mode: defaults.vim_mode.unwrap(), autosave: defaults.autosave.unwrap(), default_dock_anchor: defaults.default_dock_anchor.unwrap(), editor_defaults: EditorSettings { @@ -741,7 +738,6 @@ impl Settings { &mut self.show_completions_on_input, data.show_completions_on_input, ); - merge(&mut self.vim_mode, data.vim_mode); merge(&mut self.autosave, data.autosave); merge(&mut self.default_dock_anchor, data.default_dock_anchor); merge(&mut self.base_keymap, data.base_keymap); @@ -940,7 +936,6 @@ impl Settings { hover_popover_enabled: true, show_completions_on_input: true, show_call_status_icon: true, - vim_mode: false, autosave: Autosave::Off, default_dock_anchor: DockAnchor::Bottom, editor_defaults: EditorSettings { diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 38f9d09df0..d986ea0683 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -23,7 +23,7 @@ pub trait Setting: 'static { /// The name of a key within the JSON file from which this setting should /// be deserialized. If this is `None`, then the setting will be deserialized /// from the root object. - const KEY: Option<&'static str> = None; + const KEY: Option<&'static str>; /// The type that is stored in an individual JSON file. type FileContent: Clone + Serialize + DeserializeOwned + JsonSchema; @@ -165,6 +165,28 @@ impl SettingsStore { .expect("no default value for setting type") } + /// Get the user's settings as a raw JSON value. + /// + /// This is only for debugging and reporting. For user-facing functionality, + /// use the typed setting interface. + pub fn untyped_user_settings(&self) -> &serde_json::Value { + self.user_deserialized_settings + .as_ref() + .map_or(&serde_json::Value::Null, |s| &s.untyped) + } + + /// Override the global value for a particular setting. + /// + /// This is only for tests. Normally, settings are only loaded from + /// JSON files. + #[cfg(any(test, feature = "test-support"))] + pub fn replace_value(&mut self, value: T) { + self.setting_values + .get_mut(&TypeId::of::()) + .expect("unregistered setting type") + .set_global_value(Box::new(value)) + } + /// Update the value of a setting. /// /// Returns a list of edits to apply to the JSON file. @@ -1164,6 +1186,8 @@ mod tests { } impl Setting for MultiKeySettings { + const KEY: Option<&'static str> = None; + type FileContent = MultiKeySettingsJson; fn load( diff --git a/crates/vim/src/test/vim_test_context.rs b/crates/vim/src/test/vim_test_context.rs index 69227a0e45..69e432079a 100644 --- a/crates/vim/src/test/vim_test_context.rs +++ b/crates/vim/src/test/vim_test_context.rs @@ -18,8 +18,8 @@ impl<'a> VimTestContext<'a> { pub async fn new(cx: &'a mut gpui::TestAppContext, enabled: bool) -> VimTestContext<'a> { let mut cx = EditorLspTestContext::new_rust(Default::default(), cx).await; cx.update(|cx| { - cx.update_global(|settings: &mut Settings, _| { - settings.vim_mode = enabled; + cx.update_global(|store: &mut SettingsStore, _| { + store.replace_value(VimModeSetting(enabled)); }); search::init(cx); crate::init(cx); @@ -52,16 +52,16 @@ impl<'a> VimTestContext<'a> { pub fn enable_vim(&mut self) { self.cx.update(|cx| { - cx.update_global(|settings: &mut Settings, _| { - settings.vim_mode = true; + cx.update_global(|store: &mut SettingsStore, _| { + store.replace_value(VimModeSetting(true)) }); }) } pub fn disable_vim(&mut self) { self.cx.update(|cx| { - cx.update_global(|settings: &mut Settings, _| { - settings.vim_mode = false; + cx.update_global(|store: &mut SettingsStore, _| { + store.replace_value(VimModeSetting(false)) }); }) } diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index cc686f851f..65c46e81cf 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -22,11 +22,13 @@ use language::CursorShape; use motion::Motion; use normal::normal_replace; use serde::Deserialize; -use settings::Settings; +use settings::{Setting, SettingsStore}; use state::{Mode, Operator, VimState}; use visual::visual_replace; use workspace::{self, Workspace}; +struct VimModeSetting(bool); + #[derive(Clone, Deserialize, PartialEq)] pub struct SwitchMode(pub Mode); @@ -40,6 +42,8 @@ actions!(vim, [Tab, Enter]); impl_actions!(vim, [Number, SwitchMode, PushOperator]); pub fn init(cx: &mut AppContext) { + settings::register_setting::(cx); + editor_events::init(cx); normal::init(cx); visual::init(cx); @@ -91,11 +95,11 @@ pub fn init(cx: &mut AppContext) { filter.filtered_namespaces.insert("vim"); }); cx.update_default_global(|vim: &mut Vim, cx: &mut AppContext| { - vim.set_enabled(cx.global::().vim_mode, cx) + vim.set_enabled(settings::get_setting::(None, cx).0, cx) }); - cx.observe_global::(|cx| { + cx.observe_global::(|cx| { cx.update_default_global(|vim: &mut Vim, cx: &mut AppContext| { - vim.set_enabled(cx.global::().vim_mode, cx) + vim.set_enabled(settings::get_setting::(None, cx).0, cx) }); }) .detach(); @@ -330,6 +334,26 @@ impl Vim { } } +impl Setting for VimModeSetting { + const KEY: Option<&'static str> = Some("vim_mode"); + + type FileContent = Option; + + fn load( + default_value: &Self::FileContent, + user_values: &[&Self::FileContent], + _: &AppContext, + ) -> Self { + Self( + user_values + .first() + .map(|e| **e) + .flatten() + .unwrap_or(default_value.unwrap()), + ) + } +} + fn local_selections_changed(newest_empty: bool, cx: &mut WindowContext) { Vim::update(cx, |vim, cx| { if vim.enabled && vim.state.mode == Mode::Normal && !newest_empty {