insert.rs

  1use crate::{state::Mode, Vim};
  2use editor::{scroll::Autoscroll, Bias, Editor};
  3use gpui::{actions, Action, ViewContext};
  4use language::SelectionGoal;
  5
  6actions!(vim, [NormalBefore]);
  7
  8pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
  9    Vim::action(editor, cx, Vim::normal_before);
 10}
 11
 12impl Vim {
 13    fn normal_before(&mut self, action: &NormalBefore, cx: &mut ViewContext<Self>) {
 14        if self.active_operator().is_some() {
 15            self.operator_stack.clear();
 16            self.sync_vim_settings(cx);
 17            return;
 18        }
 19        let count = self.take_count(cx).unwrap_or(1);
 20        self.stop_recording_immediately(action.boxed_clone(), cx);
 21        if count <= 1 || Vim::globals(cx).dot_replaying {
 22            self.create_mark("^".into(), false, cx);
 23            self.update_editor(cx, |_, editor, cx| {
 24                editor.dismiss_menus_and_popups(false, cx);
 25                editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 26                    s.move_cursors_with(|map, mut cursor, _| {
 27                        *cursor.column_mut() = cursor.column().saturating_sub(1);
 28                        (map.clip_point(cursor, Bias::Left), SelectionGoal::None)
 29                    });
 30                });
 31            });
 32            self.switch_mode(Mode::Normal, false, cx);
 33            return;
 34        }
 35
 36        self.repeat(true, cx)
 37    }
 38}
 39
 40#[cfg(test)]
 41mod test {
 42    use crate::{
 43        state::Mode,
 44        test::{NeovimBackedTestContext, VimTestContext},
 45    };
 46
 47    #[gpui::test]
 48    async fn test_enter_and_exit_insert_mode(cx: &mut gpui::TestAppContext) {
 49        let mut cx = VimTestContext::new(cx, true).await;
 50        cx.simulate_keystrokes("i");
 51        assert_eq!(cx.mode(), Mode::Insert);
 52        cx.simulate_keystrokes("T e s t");
 53        cx.assert_editor_state("Testˇ");
 54        cx.simulate_keystrokes("escape");
 55        assert_eq!(cx.mode(), Mode::Normal);
 56        cx.assert_editor_state("Tesˇt");
 57    }
 58
 59    #[gpui::test]
 60    async fn test_insert_with_counts(cx: &mut gpui::TestAppContext) {
 61        let mut cx = NeovimBackedTestContext::new(cx).await;
 62
 63        cx.set_shared_state("ˇhello\n").await;
 64        cx.simulate_shared_keystrokes("5 i - escape").await;
 65        cx.shared_state().await.assert_eq("----ˇ-hello\n");
 66
 67        cx.set_shared_state("ˇhello\n").await;
 68        cx.simulate_shared_keystrokes("5 a - escape").await;
 69        cx.shared_state().await.assert_eq("h----ˇ-ello\n");
 70
 71        cx.simulate_shared_keystrokes("4 shift-i - escape").await;
 72        cx.shared_state().await.assert_eq("---ˇ-h-----ello\n");
 73
 74        cx.simulate_shared_keystrokes("3 shift-a - escape").await;
 75        cx.shared_state().await.assert_eq("----h-----ello--ˇ-\n");
 76
 77        cx.set_shared_state("ˇhello\n").await;
 78        cx.simulate_shared_keystrokes("3 o o i escape").await;
 79        cx.shared_state().await.assert_eq("hello\noi\noi\noˇi\n");
 80
 81        cx.set_shared_state("ˇhello\n").await;
 82        cx.simulate_shared_keystrokes("3 shift-o o i escape").await;
 83        cx.shared_state().await.assert_eq("oi\noi\noˇi\nhello\n");
 84    }
 85
 86    #[gpui::test]
 87    async fn test_insert_with_repeat(cx: &mut gpui::TestAppContext) {
 88        let mut cx = NeovimBackedTestContext::new(cx).await;
 89
 90        cx.set_shared_state("ˇhello\n").await;
 91        cx.simulate_shared_keystrokes("3 i - escape").await;
 92        cx.shared_state().await.assert_eq("--ˇ-hello\n");
 93        cx.simulate_shared_keystrokes(".").await;
 94        cx.shared_state().await.assert_eq("----ˇ--hello\n");
 95        cx.simulate_shared_keystrokes("2 .").await;
 96        cx.shared_state().await.assert_eq("-----ˇ---hello\n");
 97
 98        cx.set_shared_state("ˇhello\n").await;
 99        cx.simulate_shared_keystrokes("2 o k k escape").await;
100        cx.shared_state().await.assert_eq("hello\nkk\nkˇk\n");
101        cx.simulate_shared_keystrokes(".").await;
102        cx.shared_state()
103            .await
104            .assert_eq("hello\nkk\nkk\nkk\nkˇk\n");
105        cx.simulate_shared_keystrokes("1 .").await;
106        cx.shared_state()
107            .await
108            .assert_eq("hello\nkk\nkk\nkk\nkk\nkˇk\n");
109    }
110
111    #[gpui::test]
112    async fn test_insert_ctrl_r(cx: &mut gpui::TestAppContext) {
113        let mut cx = NeovimBackedTestContext::new(cx).await;
114
115        cx.set_shared_state("heˇllo\n").await;
116        cx.simulate_shared_keystrokes("y y i ctrl-r \"").await;
117        cx.shared_state().await.assert_eq("hehello\nˇllo\n");
118
119        cx.simulate_shared_keystrokes("ctrl-r x ctrl-r escape")
120            .await;
121        cx.shared_state().await.assert_eq("hehello\nˇllo\n");
122    }
123}