vim: Add support for temporary normal mode (ctrl-o) within insert mode (#19454)
Support has been added for the ctrl-o command within insert mode. Ctrl-o is used to partially enter normal mode for 1 motion to then return back into insert mode. Release Notes: - vim: Added support for `ctrl-o` in insert mode to enter temporary normal mode --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
parent
254ce74036
commit
b1cd9e4d24
14 changed files with 145 additions and 11 deletions
|
@ -28,7 +28,7 @@ use gpui::{
|
|||
actions, impl_actions, Action, AppContext, Entity, EventEmitter, KeyContext, KeystrokeEvent,
|
||||
Render, Subscription, View, ViewContext, WeakView,
|
||||
};
|
||||
use insert::NormalBefore;
|
||||
use insert::{NormalBefore, TemporaryNormal};
|
||||
use language::{CursorShape, Point, Selection, SelectionGoal, TransactionId};
|
||||
pub use mode_indicator::ModeIndicator;
|
||||
use motion::Motion;
|
||||
|
@ -38,7 +38,7 @@ use serde::Deserialize;
|
|||
use serde_derive::Serialize;
|
||||
use settings::{update_settings_file, Settings, SettingsSources, SettingsStore};
|
||||
use state::{Mode, Operator, RecordedSelection, SearchState, VimGlobals};
|
||||
use std::{ops::Range, sync::Arc};
|
||||
use std::{mem, ops::Range, sync::Arc};
|
||||
use surrounds::SurroundsType;
|
||||
use ui::{IntoElement, VisualContext};
|
||||
use workspace::{self, Pane, Workspace};
|
||||
|
@ -147,6 +147,8 @@ impl editor::Addon for VimAddon {
|
|||
pub(crate) struct Vim {
|
||||
pub(crate) mode: Mode,
|
||||
pub last_mode: Mode,
|
||||
pub temp_mode: bool,
|
||||
pub exit_temporary_mode: bool,
|
||||
|
||||
/// pre_count is the number before an operator is specified (3 in 3d2d)
|
||||
pre_count: Option<usize>,
|
||||
|
@ -197,6 +199,8 @@ impl Vim {
|
|||
cx.new_view(|cx| Vim {
|
||||
mode: Mode::Normal,
|
||||
last_mode: Mode::Normal,
|
||||
temp_mode: false,
|
||||
exit_temporary_mode: false,
|
||||
pre_count: None,
|
||||
post_count: None,
|
||||
operator_stack: Vec::new(),
|
||||
|
@ -353,6 +357,16 @@ impl Vim {
|
|||
/// Called whenever an keystroke is typed so vim can observe all actions
|
||||
/// and keystrokes accordingly.
|
||||
fn observe_keystrokes(&mut self, keystroke_event: &KeystrokeEvent, cx: &mut ViewContext<Self>) {
|
||||
if self.exit_temporary_mode {
|
||||
self.exit_temporary_mode = false;
|
||||
// Don't switch to insert mode if the action is temporary_normal.
|
||||
if let Some(action) = keystroke_event.action.as_ref() {
|
||||
if action.as_any().downcast_ref::<TemporaryNormal>().is_some() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.switch_mode(Mode::Insert, false, cx)
|
||||
}
|
||||
if let Some(action) = keystroke_event.action.as_ref() {
|
||||
// Keystroke is handled by the vim system, so continue forward
|
||||
if action.name().starts_with("vim::") {
|
||||
|
@ -438,6 +452,17 @@ impl Vim {
|
|||
}
|
||||
|
||||
pub fn switch_mode(&mut self, mode: Mode, leave_selections: bool, cx: &mut ViewContext<Self>) {
|
||||
if self.temp_mode && mode == Mode::Normal {
|
||||
self.temp_mode = false;
|
||||
self.switch_mode(Mode::Normal, leave_selections, cx);
|
||||
self.switch_mode(Mode::Insert, false, cx);
|
||||
return;
|
||||
} else if self.temp_mode
|
||||
&& !matches!(mode, Mode::Visual | Mode::VisualLine | Mode::VisualBlock)
|
||||
{
|
||||
self.temp_mode = false;
|
||||
}
|
||||
|
||||
let last_mode = self.mode;
|
||||
let prior_mode = self.last_mode;
|
||||
let prior_tx = self.current_tx;
|
||||
|
@ -729,7 +754,7 @@ impl Vim {
|
|||
Vim::update_globals(cx, |globals, cx| {
|
||||
if !globals.dot_replaying {
|
||||
globals.dot_recording = true;
|
||||
globals.recorded_actions = Default::default();
|
||||
globals.recording_actions = Default::default();
|
||||
globals.recorded_count = None;
|
||||
|
||||
let selections = self.editor().map(|editor| {
|
||||
|
@ -784,6 +809,7 @@ impl Vim {
|
|||
if globals.dot_recording {
|
||||
globals.stop_recording_after_next_action = true;
|
||||
}
|
||||
self.exit_temporary_mode = self.temp_mode;
|
||||
}
|
||||
|
||||
/// Stops recording actions immediately rather than waiting until after the
|
||||
|
@ -798,11 +824,13 @@ impl Vim {
|
|||
let globals = Vim::globals(cx);
|
||||
if globals.dot_recording {
|
||||
globals
|
||||
.recorded_actions
|
||||
.recording_actions
|
||||
.push(ReplayableAction::Action(action.boxed_clone()));
|
||||
globals.recorded_actions = mem::take(&mut globals.recording_actions);
|
||||
globals.dot_recording = false;
|
||||
globals.stop_recording_after_next_action = false;
|
||||
}
|
||||
self.exit_temporary_mode = self.temp_mode;
|
||||
}
|
||||
|
||||
/// Explicitly record one action (equivalents to start_recording and stop_recording)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue