Define vim_mode setting in vim crate

This commit is contained in:
Max Brunsfeld 2023-05-10 11:06:55 -07:00
parent 926d7b356d
commit 9b06be2aa2
5 changed files with 70 additions and 21 deletions

View file

@ -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::<SettingsStore>()
.untyped_user_settings()
.get("vim_mode")
== Some(&serde_json::Value::Bool(true));
let settings = cx.global::<Settings>();
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(

View file

@ -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<bool>,
#[serde(default)]
pub vim_mode: Option<bool>,
#[serde(default)]
pub autosave: Option<Autosave>,
#[serde(default)]
pub default_dock_anchor: Option<DockAnchor>,
@ -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 {

View file

@ -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<T: Setting>(&mut self, value: T) {
self.setting_values
.get_mut(&TypeId::of::<T>())
.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(

View file

@ -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))
});
})
}

View file

@ -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::<VimModeSetting>(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::<Settings>().vim_mode, cx)
vim.set_enabled(settings::get_setting::<VimModeSetting>(None, cx).0, cx)
});
cx.observe_global::<Settings, _>(|cx| {
cx.observe_global::<SettingsStore, _>(|cx| {
cx.update_default_global(|vim: &mut Vim, cx: &mut AppContext| {
vim.set_enabled(cx.global::<Settings>().vim_mode, cx)
vim.set_enabled(settings::get_setting::<VimModeSetting>(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<bool>;
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 {