WIP just missing insert line above and below
This commit is contained in:
parent
c268099554
commit
833a7b6e76
4 changed files with 648 additions and 35 deletions
|
@ -2,10 +2,6 @@
|
||||||
{
|
{
|
||||||
"context": "Editor && VimControl",
|
"context": "Editor && VimControl",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"i": [
|
|
||||||
"vim::SwitchMode",
|
|
||||||
"Insert"
|
|
||||||
],
|
|
||||||
"g": [
|
"g": [
|
||||||
"vim::PushOperator",
|
"vim::PushOperator",
|
||||||
{
|
{
|
||||||
|
@ -13,6 +9,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"h": "vim::Left",
|
"h": "vim::Left",
|
||||||
|
"backspace": "vim::Left",
|
||||||
"j": "vim::Down",
|
"j": "vim::Down",
|
||||||
"k": "vim::Up",
|
"k": "vim::Up",
|
||||||
"l": "vim::Right",
|
"l": "vim::Right",
|
||||||
|
@ -46,29 +43,39 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"context": "Editor && vim_operator == g",
|
|
||||||
"bindings": {
|
|
||||||
"g": "vim::StartOfDocument"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"context": "Editor && vim_mode == insert",
|
|
||||||
"bindings": {
|
|
||||||
"escape": "vim::NormalBefore",
|
|
||||||
"ctrl-c": "vim::NormalBefore"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"context": "Editor && vim_mode == normal",
|
"context": "Editor && vim_mode == normal",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
|
"escape": "editor::Cancel",
|
||||||
"c": [
|
"c": [
|
||||||
"vim::PushOperator",
|
"vim::PushOperator",
|
||||||
"Change"
|
"Change"
|
||||||
],
|
],
|
||||||
|
"shift-C": "vim::ChangeToEndOfLine",
|
||||||
"d": [
|
"d": [
|
||||||
"vim::PushOperator",
|
"vim::PushOperator",
|
||||||
"Delete"
|
"Delete"
|
||||||
|
],
|
||||||
|
"shift-D": "vim::DeleteToEndOfLine",
|
||||||
|
"i": [
|
||||||
|
"vim::SwitchMode",
|
||||||
|
"Insert"
|
||||||
|
],
|
||||||
|
"shift-I": "vim::InsertFirstNonWhitespace",
|
||||||
|
"a": "vim::InsertAfter",
|
||||||
|
"shift-A": "vim::InsertEndOfLine",
|
||||||
|
"x": "vim::DeleteRight",
|
||||||
|
"shift-X": "vim::DeleteLeft",
|
||||||
|
"shift-^": "vim::FirstNonWhitespace"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "Editor && vim_operator == g",
|
||||||
|
"bindings": {
|
||||||
|
"g": "vim::StartOfDocument",
|
||||||
|
"escape": [
|
||||||
|
"vim::SwitchMode",
|
||||||
|
"Normal"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -81,7 +88,27 @@
|
||||||
{
|
{
|
||||||
"ignorePunctuation": true
|
"ignorePunctuation": true
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"c": "vim::CurrentLine"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "Editor && vim_operator == d",
|
||||||
|
"bindings": {
|
||||||
|
"d": "vim::CurrentLine"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "Editor && vim_mode == insert",
|
||||||
|
"bindings": {
|
||||||
|
"escape": "vim::NormalBefore",
|
||||||
|
"ctrl-c": "vim::NormalBefore"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"context": "Editor && mode == singleline",
|
||||||
|
"bindings": {
|
||||||
|
"escape": "editor::Cancel"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -1456,6 +1456,7 @@ impl Editor {
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
let buffer = &display_map.buffer_snapshot;
|
let buffer = &display_map.buffer_snapshot;
|
||||||
let newest_selection = self.newest_anchor_selection().clone();
|
let newest_selection = self.newest_anchor_selection().clone();
|
||||||
|
let position = display_map.clip_point(position, Bias::Left);
|
||||||
|
|
||||||
let start;
|
let start;
|
||||||
let end;
|
let end;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use editor::{
|
use editor::{
|
||||||
char_kind,
|
char_kind,
|
||||||
display_map::{DisplaySnapshot, ToDisplayPoint},
|
display_map::{DisplaySnapshot, ToDisplayPoint},
|
||||||
movement, Bias, DisplayPoint,
|
movement, Bias, CharKind, DisplayPoint,
|
||||||
};
|
};
|
||||||
use gpui::{actions, impl_actions, MutableAppContext};
|
use gpui::{actions, impl_actions, MutableAppContext};
|
||||||
use language::{Selection, SelectionGoal};
|
use language::{Selection, SelectionGoal};
|
||||||
|
@ -23,6 +23,8 @@ pub enum Motion {
|
||||||
NextWordStart { ignore_punctuation: bool },
|
NextWordStart { ignore_punctuation: bool },
|
||||||
NextWordEnd { ignore_punctuation: bool },
|
NextWordEnd { ignore_punctuation: bool },
|
||||||
PreviousWordStart { ignore_punctuation: bool },
|
PreviousWordStart { ignore_punctuation: bool },
|
||||||
|
FirstNonWhitespace,
|
||||||
|
CurrentLine,
|
||||||
StartOfLine,
|
StartOfLine,
|
||||||
EndOfLine,
|
EndOfLine,
|
||||||
StartOfDocument,
|
StartOfDocument,
|
||||||
|
@ -57,8 +59,10 @@ actions!(
|
||||||
Down,
|
Down,
|
||||||
Up,
|
Up,
|
||||||
Right,
|
Right,
|
||||||
|
FirstNonWhitespace,
|
||||||
StartOfLine,
|
StartOfLine,
|
||||||
EndOfLine,
|
EndOfLine,
|
||||||
|
CurrentLine,
|
||||||
StartOfDocument,
|
StartOfDocument,
|
||||||
EndOfDocument
|
EndOfDocument
|
||||||
]
|
]
|
||||||
|
@ -70,8 +74,12 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(|_: &mut Workspace, _: &Down, cx: _| motion(Motion::Down, cx));
|
cx.add_action(|_: &mut Workspace, _: &Down, cx: _| motion(Motion::Down, cx));
|
||||||
cx.add_action(|_: &mut Workspace, _: &Up, cx: _| motion(Motion::Up, cx));
|
cx.add_action(|_: &mut Workspace, _: &Up, cx: _| motion(Motion::Up, cx));
|
||||||
cx.add_action(|_: &mut Workspace, _: &Right, cx: _| motion(Motion::Right, cx));
|
cx.add_action(|_: &mut Workspace, _: &Right, cx: _| motion(Motion::Right, cx));
|
||||||
|
cx.add_action(|_: &mut Workspace, _: &FirstNonWhitespace, cx: _| {
|
||||||
|
motion(Motion::FirstNonWhitespace, cx)
|
||||||
|
});
|
||||||
cx.add_action(|_: &mut Workspace, _: &StartOfLine, cx: _| motion(Motion::StartOfLine, cx));
|
cx.add_action(|_: &mut Workspace, _: &StartOfLine, cx: _| motion(Motion::StartOfLine, cx));
|
||||||
cx.add_action(|_: &mut Workspace, _: &EndOfLine, cx: _| motion(Motion::EndOfLine, cx));
|
cx.add_action(|_: &mut Workspace, _: &EndOfLine, cx: _| motion(Motion::EndOfLine, cx));
|
||||||
|
cx.add_action(|_: &mut Workspace, _: &CurrentLine, cx: _| motion(Motion::CurrentLine, cx));
|
||||||
cx.add_action(|_: &mut Workspace, _: &StartOfDocument, cx: _| {
|
cx.add_action(|_: &mut Workspace, _: &StartOfDocument, cx: _| {
|
||||||
motion(Motion::StartOfDocument, cx)
|
motion(Motion::StartOfDocument, cx)
|
||||||
});
|
});
|
||||||
|
@ -114,7 +122,7 @@ impl Motion {
|
||||||
pub fn linewise(self) -> bool {
|
pub fn linewise(self) -> bool {
|
||||||
use Motion::*;
|
use Motion::*;
|
||||||
match self {
|
match self {
|
||||||
Down | Up | StartOfDocument | EndOfDocument => true,
|
Down | Up | StartOfDocument | EndOfDocument | CurrentLine => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,8 +164,10 @@ impl Motion {
|
||||||
previous_word_start(map, point, ignore_punctuation),
|
previous_word_start(map, point, ignore_punctuation),
|
||||||
SelectionGoal::None,
|
SelectionGoal::None,
|
||||||
),
|
),
|
||||||
|
FirstNonWhitespace => (first_non_whitespace(map, point), SelectionGoal::None),
|
||||||
StartOfLine => (start_of_line(map, point), SelectionGoal::None),
|
StartOfLine => (start_of_line(map, point), SelectionGoal::None),
|
||||||
EndOfLine => (end_of_line(map, point), SelectionGoal::None),
|
EndOfLine => (end_of_line(map, point), SelectionGoal::None),
|
||||||
|
CurrentLine => (end_of_line(map, point), SelectionGoal::None),
|
||||||
StartOfDocument => (start_of_document(map, point), SelectionGoal::None),
|
StartOfDocument => (start_of_document(map, point), SelectionGoal::None),
|
||||||
EndOfDocument => (end_of_document(map, point), SelectionGoal::None),
|
EndOfDocument => (end_of_document(map, point), SelectionGoal::None),
|
||||||
}
|
}
|
||||||
|
@ -290,6 +300,24 @@ fn previous_word_start(
|
||||||
point
|
point
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn first_non_whitespace(map: &DisplaySnapshot, mut point: DisplayPoint) -> DisplayPoint {
|
||||||
|
let mut column = 0;
|
||||||
|
for ch in map.chars_at(DisplayPoint::new(point.row(), 0)) {
|
||||||
|
if ch == '\n' {
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
if char_kind(ch) != CharKind::Whitespace {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
column += ch.len_utf8() as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
*point.column_mut() = column;
|
||||||
|
map.clip_point(point, Bias::Left)
|
||||||
|
}
|
||||||
|
|
||||||
fn start_of_line(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint {
|
fn start_of_line(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint {
|
||||||
map.prev_line_boundary(point.to_point(map)).1
|
map.prev_line_boundary(point.to_point(map)).1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,60 @@
|
||||||
mod change;
|
mod change;
|
||||||
mod delete;
|
mod delete;
|
||||||
|
|
||||||
use crate::{motion::Motion, state::Operator, Vim};
|
use crate::{
|
||||||
|
motion::Motion,
|
||||||
|
state::{Mode, Operator},
|
||||||
|
Vim,
|
||||||
|
};
|
||||||
use change::init as change_init;
|
use change::init as change_init;
|
||||||
use gpui::{actions, MutableAppContext};
|
use gpui::{actions, MutableAppContext, ViewContext};
|
||||||
|
use language::SelectionGoal;
|
||||||
|
use workspace::Workspace;
|
||||||
|
|
||||||
use self::{change::change_over, delete::delete_over};
|
use self::{change::change_over, delete::delete_over};
|
||||||
|
|
||||||
actions!(vim, [InsertLineAbove, InsertLineBelow, InsertAfter]);
|
actions!(
|
||||||
|
vim,
|
||||||
|
[
|
||||||
|
InsertAfter,
|
||||||
|
InsertFirstNonWhitespace,
|
||||||
|
InsertEndOfLine,
|
||||||
|
InsertLineAbove,
|
||||||
|
InsertLineBelow,
|
||||||
|
DeleteLeft,
|
||||||
|
DeleteRight,
|
||||||
|
ChangeToEndOfLine,
|
||||||
|
DeleteToEndOfLine,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext) {
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
|
cx.add_action(insert_after);
|
||||||
|
cx.add_action(insert_first_non_whitespace);
|
||||||
|
cx.add_action(insert_end_of_line);
|
||||||
|
cx.add_action(insert_line_above);
|
||||||
|
cx.add_action(insert_line_below);
|
||||||
|
cx.add_action(|_: &mut Workspace, _: &DeleteLeft, cx| {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
delete_over(vim, Motion::Left, cx);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
cx.add_action(|_: &mut Workspace, _: &DeleteRight, cx| {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
delete_over(vim, Motion::Right, cx);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
cx.add_action(|_: &mut Workspace, _: &ChangeToEndOfLine, cx| {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
change_over(vim, Motion::EndOfLine, cx);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
cx.add_action(|_: &mut Workspace, _: &DeleteToEndOfLine, cx| {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
delete_over(vim, Motion::EndOfLine, cx);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
change_init(cx);
|
change_init(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +78,88 @@ fn move_cursor(vim: &mut Vim, motion: Motion, cx: &mut MutableAppContext) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn insert_after(_: &mut Workspace, _: &InsertAfter, cx: &mut ViewContext<Workspace>) {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
vim.switch_mode(Mode::Insert, cx);
|
||||||
|
vim.update_active_editor(cx, |editor, cx| {
|
||||||
|
editor.move_cursors(cx, |map, cursor, goal| {
|
||||||
|
Motion::Right.move_point(map, cursor, goal)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_first_non_whitespace(
|
||||||
|
_: &mut Workspace,
|
||||||
|
_: &InsertFirstNonWhitespace,
|
||||||
|
cx: &mut ViewContext<Workspace>,
|
||||||
|
) {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
vim.switch_mode(Mode::Insert, cx);
|
||||||
|
vim.update_active_editor(cx, |editor, cx| {
|
||||||
|
editor.move_cursors(cx, |map, cursor, goal| {
|
||||||
|
Motion::FirstNonWhitespace.move_point(map, cursor, goal)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_end_of_line(_: &mut Workspace, _: &InsertEndOfLine, cx: &mut ViewContext<Workspace>) {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
vim.switch_mode(Mode::Insert, cx);
|
||||||
|
vim.update_active_editor(cx, |editor, cx| {
|
||||||
|
editor.move_cursors(cx, |map, cursor, goal| {
|
||||||
|
Motion::EndOfLine.move_point(map, cursor, goal)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_line_above(_: &mut Workspace, _: &InsertLineAbove, cx: &mut ViewContext<Workspace>) {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
vim.switch_mode(Mode::Insert, cx);
|
||||||
|
vim.update_active_editor(cx, |editor, cx| {
|
||||||
|
editor.transact(cx, |editor, cx| {
|
||||||
|
editor.move_cursors(cx, |map, cursor, goal| {
|
||||||
|
let (indent, _) = map.line_indent(cursor.row());
|
||||||
|
let (cursor, _) = Motion::EndOfLine.move_point(map, cursor, goal);
|
||||||
|
(cursor, SelectionGoal::Column(indent))
|
||||||
|
});
|
||||||
|
editor.insert("\n", cx);
|
||||||
|
editor.move_cursors(cx, |_, mut cursor, goal| {
|
||||||
|
if let SelectionGoal::Column(column) = goal {
|
||||||
|
*cursor.column_mut() = column;
|
||||||
|
}
|
||||||
|
(cursor, SelectionGoal::None)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_line_below(_: &mut Workspace, _: &InsertLineAbove, cx: &mut ViewContext<Workspace>) {
|
||||||
|
Vim::update(cx, |vim, cx| {
|
||||||
|
vim.switch_mode(Mode::Insert, cx);
|
||||||
|
vim.update_active_editor(cx, |editor, cx| {
|
||||||
|
editor.transact(cx, |editor, cx| {
|
||||||
|
editor.move_cursors(cx, |map, cursor, goal| {
|
||||||
|
let (indent, _) = map.line_indent(cursor.row());
|
||||||
|
let (cursor, _) = Motion::StartOfLine.move_point(map, cursor, goal);
|
||||||
|
(cursor, SelectionGoal::Column(indent))
|
||||||
|
});
|
||||||
|
editor.insert("\n", cx);
|
||||||
|
editor.move_cursors(cx, |_, mut cursor, goal| {
|
||||||
|
*cursor.row_mut() -= 1;
|
||||||
|
if let SelectionGoal::Column(column) = goal {
|
||||||
|
*cursor.column_mut() = column;
|
||||||
|
}
|
||||||
|
(cursor, SelectionGoal::None)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
@ -63,18 +190,18 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_l(cx: &mut gpui::TestAppContext) {
|
async fn test_backspace(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
let mut cx = cx.binding(["l"]);
|
let mut cx = cx.binding(["backspace"]);
|
||||||
cx.assert("The q|uick", "The qu|ick");
|
cx.assert("The q|uick", "The |quick");
|
||||||
cx.assert("The quic|k", "The quic|k");
|
cx.assert("|The quick", "|The quick");
|
||||||
cx.assert(
|
cx.assert(
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The quic|k
|
The quick
|
||||||
brown"},
|
|brown"},
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The quic|k
|
The quick
|
||||||
brown"},
|
|brown"},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +273,22 @@ mod test {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_l(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["l"]);
|
||||||
|
cx.assert("The q|uick", "The qu|ick");
|
||||||
|
cx.assert("The quic|k", "The quic|k");
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quic|k
|
||||||
|
brown"},
|
||||||
|
indoc! {"
|
||||||
|
The quic|k
|
||||||
|
brown"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_jump_to_line_boundaries(cx: &mut gpui::TestAppContext) {
|
async fn test_jump_to_line_boundaries(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
@ -242,7 +385,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_next_word_start(cx: &mut gpui::TestAppContext) {
|
async fn test_w(cx: &mut gpui::TestAppContext) {
|
||||||
let mut cx = VimTestContext::new(cx, true).await;
|
let mut cx = VimTestContext::new(cx, true).await;
|
||||||
let (_, cursor_offsets) = marked_text(indoc! {"
|
let (_, cursor_offsets) = marked_text(indoc! {"
|
||||||
The |quick|-|brown
|
The |quick|-|brown
|
||||||
|
@ -289,7 +432,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_next_word_end(cx: &mut gpui::TestAppContext) {
|
async fn test_e(cx: &mut gpui::TestAppContext) {
|
||||||
let mut cx = VimTestContext::new(cx, true).await;
|
let mut cx = VimTestContext::new(cx, true).await;
|
||||||
let (_, cursor_offsets) = marked_text(indoc! {"
|
let (_, cursor_offsets) = marked_text(indoc! {"
|
||||||
Th|e quic|k|-brow|n
|
Th|e quic|k|-brow|n
|
||||||
|
@ -335,7 +478,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_previous_word_start(cx: &mut gpui::TestAppContext) {
|
async fn test_b(cx: &mut gpui::TestAppContext) {
|
||||||
let mut cx = VimTestContext::new(cx, true).await;
|
let mut cx = VimTestContext::new(cx, true).await;
|
||||||
let (_, cursor_offsets) = marked_text(indoc! {"
|
let (_, cursor_offsets) = marked_text(indoc! {"
|
||||||
||The |quick|-|brown
|
||The |quick|-|brown
|
||||||
|
@ -397,7 +540,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_move_to_start(cx: &mut gpui::TestAppContext) {
|
async fn test_gg(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
let mut cx = cx.binding(["g", "g"]);
|
let mut cx = cx.binding(["g", "g"]);
|
||||||
cx.assert(
|
cx.assert(
|
||||||
|
@ -449,4 +592,418 @@ mod test {
|
||||||
over the lazy dog"},
|
over the lazy dog"},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_a(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["a"]).mode_after(Mode::Insert);
|
||||||
|
|
||||||
|
cx.assert("The q|uick", "The qu|ick");
|
||||||
|
cx.assert("The quic|k", "The quick|");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_insert_end_of_line(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["shift-A"]).mode_after(Mode::Insert);
|
||||||
|
cx.assert("The q|uick", "The quick|");
|
||||||
|
cx.assert("The q|uick ", "The quick |");
|
||||||
|
cx.assert("|", "|");
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The q|uick
|
||||||
|
brown fox"},
|
||||||
|
indoc! {"
|
||||||
|
The quick|
|
||||||
|
brown fox"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick"},
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_jump_to_first_non_whitespace(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["shift-^"]);
|
||||||
|
cx.assert("The q|uick", "|The quick");
|
||||||
|
cx.assert(" The q|uick", " |The quick");
|
||||||
|
cx.assert("|", "|");
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The q|uick
|
||||||
|
brown fox"},
|
||||||
|
indoc! {"
|
||||||
|
|The quick
|
||||||
|
brown fox"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick"},
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick"},
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_insert_first_non_whitespace(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["shift-I"]).mode_after(Mode::Insert);
|
||||||
|
cx.assert("The q|uick", "|The quick");
|
||||||
|
cx.assert(" The q|uick", " |The quick");
|
||||||
|
cx.assert("|", "|");
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The q|uick
|
||||||
|
brown fox"},
|
||||||
|
indoc! {"
|
||||||
|
|The quick
|
||||||
|
brown fox"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick"},
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_delete_to_end_of_line(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["shift-D"]);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The q|uick
|
||||||
|
brown fox"},
|
||||||
|
indoc! {"
|
||||||
|
The |q
|
||||||
|
brown fox"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
brown fox"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
brown fox"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_x(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["x"]);
|
||||||
|
cx.assert("|Test", "|est");
|
||||||
|
cx.assert("Te|st", "Te|t");
|
||||||
|
cx.assert("Tes|t", "Te|s");
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
Tes|t
|
||||||
|
test"},
|
||||||
|
indoc! {"
|
||||||
|
Te|s
|
||||||
|
test"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_delete_left(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["shift-X"]);
|
||||||
|
cx.assert("Te|st", "T|st");
|
||||||
|
cx.assert("T|est", "|est");
|
||||||
|
cx.assert("|Test", "|Test");
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
Test
|
||||||
|
|test"},
|
||||||
|
indoc! {"
|
||||||
|
Test
|
||||||
|
|test"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_o(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["o"]).mode_after(Mode::Insert);
|
||||||
|
|
||||||
|
cx.assert(
|
||||||
|
"|",
|
||||||
|
indoc! {"
|
||||||
|
|
||||||
|
|"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
"The |quick",
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown |fox
|
||||||
|
jumps over"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown fox
|
||||||
|
|
|
||||||
|
jumps over"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown fox
|
||||||
|
jumps |over"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown fox
|
||||||
|
jumps over
|
||||||
|
|"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The q|uick
|
||||||
|
brown fox
|
||||||
|
jumps over"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
brown fox
|
||||||
|
jumps over"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
brown fox"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
||||||
|
|
|
||||||
|
brown fox"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
fn test() {
|
||||||
|
println!(|);
|
||||||
|
}"},
|
||||||
|
indoc! {"
|
||||||
|
fn test() {
|
||||||
|
println!();
|
||||||
|
|
|
||||||
|
}"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
fn test(|) {
|
||||||
|
println!();
|
||||||
|
}"},
|
||||||
|
indoc! {"
|
||||||
|
fn test() {
|
||||||
|
|
|
||||||
|
println!();
|
||||||
|
}"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_insert_line_above(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["shift-O"]).mode_after(Mode::Insert);
|
||||||
|
|
||||||
|
cx.assert(
|
||||||
|
"|",
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
"The |quick",
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown |fox
|
||||||
|
jumps over"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
brown fox
|
||||||
|
jumps over"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown fox
|
||||||
|
jumps |over"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown fox
|
||||||
|
|
|
||||||
|
jumps over"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The q|uick
|
||||||
|
brown fox
|
||||||
|
jumps over"},
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
The quick
|
||||||
|
brown fox
|
||||||
|
jumps over"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
brown fox"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
|
||||||
|
brown fox"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
fn test() {
|
||||||
|
println!(|);
|
||||||
|
}"},
|
||||||
|
indoc! {"
|
||||||
|
fn test() {
|
||||||
|
|
|
||||||
|
println!();
|
||||||
|
}"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
fn test(|) {
|
||||||
|
println!();
|
||||||
|
}"},
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
fn test() {
|
||||||
|
println!();
|
||||||
|
}"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_dd(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["d", "d"]);
|
||||||
|
|
||||||
|
cx.assert("|", "|");
|
||||||
|
cx.assert("The |quick", "|");
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown |fox
|
||||||
|
jumps over"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
jumps |over"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown fox
|
||||||
|
jumps |over"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown |fox"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The q|uick
|
||||||
|
brown fox
|
||||||
|
jumps over"},
|
||||||
|
indoc! {"
|
||||||
|
brown| fox
|
||||||
|
jumps over"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
brown fox"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|brown fox"},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_cc(cx: &mut gpui::TestAppContext) {
|
||||||
|
let cx = VimTestContext::new(cx, true).await;
|
||||||
|
let mut cx = cx.binding(["c", "c"]).mode_after(Mode::Insert);
|
||||||
|
|
||||||
|
cx.assert("|", "|");
|
||||||
|
cx.assert("The |quick", "|");
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown |fox
|
||||||
|
jumps over"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
jumps over"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown fox
|
||||||
|
jumps |over"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
brown fox
|
||||||
|
|"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The q|uick
|
||||||
|
brown fox
|
||||||
|
jumps over"},
|
||||||
|
indoc! {"
|
||||||
|
|
|
||||||
|
brown fox
|
||||||
|
jumps over"},
|
||||||
|
);
|
||||||
|
cx.assert(
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
brown fox"},
|
||||||
|
indoc! {"
|
||||||
|
The quick
|
||||||
|
|
|
||||||
|
brown fox"},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue