vim: add , and ;

This commit is contained in:
Conrad Irwin 2023-07-20 15:22:15 -06:00
parent a50d30bf8e
commit 4772e4ccee
5 changed files with 98 additions and 6 deletions

View file

@ -292,6 +292,13 @@
"backwards": true
}
],
";": "vim::RepeatFind",
",": [
"vim::RepeatFind",
{
"backwards": true
}
],
"ctrl-f": "vim::PageDown",
"pagedown": "vim::PageDown",
"ctrl-b": "vim::PageUp",

View file

@ -62,6 +62,12 @@ struct PreviousWordStart {
ignore_punctuation: bool,
}
#[derive(Clone, Deserialize, PartialEq)]
struct RepeatFind {
#[serde(default)]
backwards: bool,
}
actions!(
vim,
[
@ -82,7 +88,10 @@ actions!(
NextLineStart,
]
);
impl_actions!(vim, [NextWordStart, NextWordEnd, PreviousWordStart]);
impl_actions!(
vim,
[NextWordStart, NextWordEnd, PreviousWordStart, RepeatFind]
);
pub fn init(cx: &mut AppContext) {
cx.add_action(|_: &mut Workspace, _: &Left, cx: _| motion(Motion::Left, cx));
@ -123,7 +132,10 @@ pub fn init(cx: &mut AppContext) {
&PreviousWordStart { ignore_punctuation }: &PreviousWordStart,
cx: _| { motion(Motion::PreviousWordStart { ignore_punctuation }, cx) },
);
cx.add_action(|_: &mut Workspace, &NextLineStart, cx: _| motion(Motion::NextLineStart, cx))
cx.add_action(|_: &mut Workspace, &NextLineStart, cx: _| motion(Motion::NextLineStart, cx));
cx.add_action(|_: &mut Workspace, action: &RepeatFind, cx: _| {
repeat_motion(action.backwards, cx)
})
}
pub(crate) fn motion(motion: Motion, cx: &mut WindowContext) {
@ -145,6 +157,35 @@ pub(crate) fn motion(motion: Motion, cx: &mut WindowContext) {
Vim::update(cx, |vim, cx| vim.clear_operator(cx));
}
fn repeat_motion(backwards: bool, cx: &mut WindowContext) {
let find = match Vim::read(cx).state.last_find.clone() {
Some(Motion::FindForward { before, text }) => {
if backwards {
Motion::FindBackward {
after: before,
text,
}
} else {
Motion::FindForward { before, text }
}
}
Some(Motion::FindBackward { after, text }) => {
if backwards {
Motion::FindForward {
before: after,
text,
}
} else {
Motion::FindBackward { after, text }
}
}
_ => return,
};
motion(find, cx)
}
// Motion handling is specified here:
// https://github.com/vim/vim/blob/master/runtime/doc/motion.txt
impl Motion {
@ -742,4 +783,23 @@ mod test {
cx.simulate_shared_keystrokes(["%"]).await;
cx.assert_shared_state("func boop(ˇ) {\n}").await;
}
#[gpui::test]
async fn test_comma_semicolon(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("ˇone two three four").await;
cx.simulate_shared_keystrokes(["f", "o"]).await;
cx.assert_shared_state("one twˇo three four").await;
cx.simulate_shared_keystrokes([","]).await;
cx.assert_shared_state("ˇone two three four").await;
cx.simulate_shared_keystrokes(["2", ";"]).await;
cx.assert_shared_state("one two three fˇour").await;
cx.simulate_shared_keystrokes(["shift-t", "e"]).await;
cx.assert_shared_state("one two threeˇ four").await;
cx.simulate_shared_keystrokes(["3", ";"]).await;
cx.assert_shared_state("oneˇ two three four").await;
cx.simulate_shared_keystrokes([","]).await;
cx.assert_shared_state("one two thˇree four").await;
}
}

View file

@ -3,6 +3,8 @@ use language::CursorShape;
use serde::{Deserialize, Serialize};
use workspace::searchable::Direction;
use crate::motion::Motion;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum Mode {
Normal,
@ -33,6 +35,8 @@ pub struct VimState {
pub mode: Mode,
pub operator_stack: Vec<Operator>,
pub search: SearchState,
pub last_find: Option<Motion>,
}
pub struct SearchState {

View file

@ -14,8 +14,8 @@ use anyhow::Result;
use collections::CommandPaletteFilter;
use editor::{Bias, Editor, EditorMode, Event};
use gpui::{
actions, impl_actions,keymap_matcher::MatchResult, keymap_matcher::KeymapContext, AppContext, Subscription, ViewContext,
ViewHandle, WeakViewHandle, WindowContext,
actions, impl_actions, keymap_matcher::KeymapContext, keymap_matcher::MatchResult, AppContext,
Subscription, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
};
use language::CursorShape;
use motion::Motion;
@ -246,10 +246,14 @@ impl Vim {
match Vim::read(cx).active_operator() {
Some(Operator::FindForward { before }) => {
motion::motion(Motion::FindForward { before, text }, cx)
let find = Motion::FindForward { before, text };
Vim::update(cx, |vim, _| vim.state.last_find = Some(find.clone()));
motion::motion(find, cx)
}
Some(Operator::FindBackward { after }) => {
motion::motion(Motion::FindBackward { after, text }, cx)
let find = Motion::FindBackward { after, text };
Vim::update(cx, |vim, _| vim.state.last_find = Some(find.clone()));
motion::motion(find, cx)
}
Some(Operator::Replace) => match Vim::read(cx).state.mode {
Mode::Normal => normal_replace(text, cx),

View file

@ -0,0 +1,17 @@
{"Put":{"state":"ˇone two three four"}}
{"Key":"f"}
{"Key":"o"}
{"Get":{"state":"one twˇo three four","mode":"Normal"}}
{"Key":","}
{"Get":{"state":"ˇone two three four","mode":"Normal"}}
{"Key":"2"}
{"Key":";"}
{"Get":{"state":"one two three fˇour","mode":"Normal"}}
{"Key":"shift-t"}
{"Key":"e"}
{"Get":{"state":"one two threeˇ four","mode":"Normal"}}
{"Key":"3"}
{"Key":";"}
{"Get":{"state":"oneˇ two three four","mode":"Normal"}}
{"Key":","}
{"Get":{"state":"one two thˇree four","mode":"Normal"}}