Fully disable vim mode on start unless it's enabled

Also: Make some structural adjustments to remove the need for defer. Instead of accessing the global in associated VimState functions, have a single method that allows us to call update instance methods.
This commit is contained in:
Nathan Sobo 2022-03-26 14:30:55 -06:00
parent 30e31f6561
commit daf999c3be
5 changed files with 99 additions and 83 deletions

View file

@ -19,10 +19,14 @@ pub fn init(cx: &mut MutableAppContext) {
insert::init(cx);
normal::init(cx);
cx.add_action(|_: &mut Workspace, action: &SwitchMode, cx| VimState::switch_mode(action, cx));
cx.add_action(|_: &mut Workspace, action: &SwitchMode, cx| {
VimState::update_global(cx, |state, cx| state.switch_mode(action, cx))
});
cx.observe_global::<Settings, _>(VimState::settings_changed)
.detach();
cx.observe_global::<Settings, _>(|settings, cx| {
VimState::update_global(cx, |state, cx| state.set_enabled(settings.vim_mode, cx))
})
.detach();
}
#[derive(Default)]
@ -35,62 +39,56 @@ pub struct VimState {
}
impl VimState {
fn update_global<F, S>(cx: &mut MutableAppContext, update: F) -> S
where
F: FnOnce(&mut Self, &mut MutableAppContext) -> S,
{
cx.update_default_global(update)
}
fn update_active_editor<S>(
&self,
cx: &mut MutableAppContext,
update: impl FnOnce(&mut Editor, &mut ViewContext<Editor>) -> S,
) -> Option<S> {
cx.global::<Self>()
.active_editor
self.active_editor
.clone()
.and_then(|ae| ae.upgrade(cx))
.map(|ae| ae.update(cx, update))
}
fn switch_mode(SwitchMode(mode): &SwitchMode, cx: &mut MutableAppContext) {
cx.update_default_global(|this: &mut Self, _| {
this.mode = *mode;
});
VimState::sync_editor_options(cx);
fn switch_mode(&mut self, SwitchMode(mode): &SwitchMode, cx: &mut MutableAppContext) {
self.mode = *mode;
self.sync_editor_options(cx);
}
fn settings_changed(cx: &mut MutableAppContext) {
cx.update_default_global(|this: &mut Self, cx| {
let settings = cx.global::<Settings>();
if this.enabled != settings.vim_mode {
this.enabled = settings.vim_mode;
this.mode = if settings.vim_mode {
Mode::Normal
} else {
Mode::Insert
};
Self::sync_editor_options(cx);
}
});
fn set_enabled(&mut self, enabled: bool, cx: &mut MutableAppContext) {
if self.enabled != enabled {
self.enabled = enabled;
self.sync_editor_options(cx);
}
}
fn sync_editor_options(cx: &mut MutableAppContext) {
cx.defer(move |cx| {
cx.update_default_global(|this: &mut VimState, cx| {
let mode = this.mode;
let cursor_shape = mode.cursor_shape();
let keymap_layer_active = this.enabled;
for editor in this.editors.values() {
if let Some(editor) = editor.upgrade(cx) {
editor.update(cx, |editor, cx| {
editor.set_cursor_shape(cursor_shape, cx);
editor.set_clip_at_line_ends(cursor_shape == CursorShape::Block, cx);
editor.set_input_enabled(mode == Mode::Insert);
if keymap_layer_active {
let context_layer = mode.keymap_context_layer();
editor.set_keymap_context_layer::<Self>(context_layer);
} else {
editor.remove_keymap_context_layer::<Self>();
}
});
fn sync_editor_options(&self, cx: &mut MutableAppContext) {
let mode = self.mode;
let cursor_shape = mode.cursor_shape();
for editor in self.editors.values() {
if let Some(editor) = editor.upgrade(cx) {
editor.update(cx, |editor, cx| {
if self.enabled {
editor.set_cursor_shape(cursor_shape, cx);
editor.set_clip_at_line_ends(cursor_shape == CursorShape::Block, cx);
editor.set_input_enabled(mode == Mode::Insert);
let context_layer = mode.keymap_context_layer();
editor.set_keymap_context_layer::<Self>(context_layer);
} else {
editor.set_cursor_shape(CursorShape::Bar, cx);
editor.set_clip_at_line_ends(false, cx);
editor.set_input_enabled(true);
editor.remove_keymap_context_layer::<Self>();
}
}
});
});
});
}
}
}
}