@@ -333,10 +333,14 @@
"ctrl-x ctrl-c": "editor::ShowEditPrediction", // zed specific
"ctrl-x ctrl-l": "editor::ToggleCodeActions", // zed specific
"ctrl-x ctrl-z": "editor::Cancel",
+ "ctrl-x ctrl-e": "vim::LineDown",
+ "ctrl-x ctrl-y": "vim::LineUp",
"ctrl-w": "editor::DeleteToPreviousWordStart",
"ctrl-u": "editor::DeleteToBeginningOfLine",
"ctrl-t": "vim::Indent",
"ctrl-d": "vim::Outdent",
+ "ctrl-y": "vim::InsertFromAbove",
+ "ctrl-e": "vim::InsertFromBelow",
"ctrl-k": ["vim::PushDigraph", {}],
"ctrl-v": ["vim::PushLiteral", {}],
"ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use.
@@ -3,7 +3,9 @@ use editor::{Bias, Editor};
use gpui::{Action, Context, Window, actions};
use language::SelectionGoal;
use settings::Settings;
+use text::Point;
use vim_mode_setting::HelixModeSetting;
+use workspace::searchable::Direction;
actions!(
vim,
@@ -11,13 +13,23 @@ actions!(
/// Switches to normal mode with cursor positioned before the current character.
NormalBefore,
/// Temporarily switches to normal mode for one command.
- TemporaryNormal
+ TemporaryNormal,
+ /// Inserts the next character from the line above into the current line.
+ InsertFromAbove,
+ /// Inserts the next character from the line below into the current line.
+ InsertFromBelow
]
);
pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
Vim::action(editor, cx, Vim::normal_before);
Vim::action(editor, cx, Vim::temporary_normal);
+ Vim::action(editor, cx, |vim, _: &InsertFromAbove, window, cx| {
+ vim.insert_around(Direction::Prev, window, cx)
+ });
+ Vim::action(editor, cx, |vim, _: &InsertFromBelow, window, cx| {
+ vim.insert_around(Direction::Next, window, cx)
+ })
}
impl Vim {
@@ -71,6 +83,29 @@ impl Vim {
self.switch_mode(Mode::Normal, true, window, cx);
self.temp_mode = true;
}
+
+ fn insert_around(&mut self, direction: Direction, _: &mut Window, cx: &mut Context<Self>) {
+ self.update_editor(cx, |_, editor, cx| {
+ let snapshot = editor.buffer().read(cx).snapshot(cx);
+ let mut edits = Vec::new();
+ for selection in editor.selections.all::<Point>(cx) {
+ let point = selection.head();
+ let new_row = match direction {
+ Direction::Next => point.row + 1,
+ Direction::Prev if point.row > 0 => point.row - 1,
+ _ => continue,
+ };
+ let source = snapshot.clip_point(Point::new(new_row, point.column), Bias::Left);
+ if let Some(c) = snapshot.chars_at(source).next()
+ && c != '\n'
+ {
+ edits.push((point..point, c.to_string()))
+ }
+ }
+
+ editor.edit(edits, cx);
+ });
+ }
}
#[cfg(test)]
@@ -156,4 +191,13 @@ mod test {
.await;
cx.shared_state().await.assert_eq("hehello\nˇllo\n");
}
+
+ #[gpui::test]
+ async fn test_insert_ctrl_y(cx: &mut gpui::TestAppContext) {
+ let mut cx = NeovimBackedTestContext::new(cx).await;
+
+ cx.set_shared_state("hello\nˇ\nworld").await;
+ cx.simulate_shared_keystrokes("i ctrl-y ctrl-e").await;
+ cx.shared_state().await.assert_eq("hello\nhoˇ\nworld");
+ }
}