mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 01:34:02 +00:00
Merge pull request #1803 from zed-industries/fix-vim-motion-panic
Add more explicit neovim testcase exemptions
This commit is contained in:
commit
076d353e84
35 changed files with 678 additions and 693 deletions
|
@ -15,7 +15,7 @@ use crate::{
|
|||
Vim,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Motion {
|
||||
Left,
|
||||
Backspace,
|
||||
|
@ -139,14 +139,22 @@ impl Motion {
|
|||
|
||||
pub fn inclusive(self) -> bool {
|
||||
use Motion::*;
|
||||
if self.linewise() {
|
||||
return true;
|
||||
}
|
||||
|
||||
match self {
|
||||
EndOfLine | NextWordEnd { .. } | Matching => true,
|
||||
Left | Right | StartOfLine | NextWordStart { .. } | PreviousWordStart { .. } => false,
|
||||
_ => panic!("Exclusivity not defined for {self:?}"),
|
||||
Down
|
||||
| Up
|
||||
| StartOfDocument
|
||||
| EndOfDocument
|
||||
| CurrentLine
|
||||
| EndOfLine
|
||||
| NextWordEnd { .. }
|
||||
| Matching => true,
|
||||
Left
|
||||
| Backspace
|
||||
| Right
|
||||
| StartOfLine
|
||||
| NextWordStart { .. }
|
||||
| PreviousWordStart { .. }
|
||||
| FirstNonWhitespace => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,27 +202,29 @@ impl Motion {
|
|||
times: usize,
|
||||
expand_to_surrounding_newline: bool,
|
||||
) {
|
||||
let (head, goal) = self.move_point(map, selection.head(), selection.goal, times);
|
||||
selection.set_head(head, goal);
|
||||
let (new_head, goal) = self.move_point(map, selection.head(), selection.goal, times);
|
||||
selection.set_head(new_head, goal);
|
||||
|
||||
if self.linewise() {
|
||||
selection.start = map.prev_line_boundary(selection.start.to_point(map)).1;
|
||||
if selection.start != selection.end {
|
||||
selection.start = map.prev_line_boundary(selection.start.to_point(map)).1;
|
||||
|
||||
if expand_to_surrounding_newline {
|
||||
if selection.end.row() < map.max_point().row() {
|
||||
*selection.end.row_mut() += 1;
|
||||
*selection.end.column_mut() = 0;
|
||||
selection.end = map.clip_point(selection.end, Bias::Right);
|
||||
// Don't reset the end here
|
||||
return;
|
||||
} else if selection.start.row() > 0 {
|
||||
*selection.start.row_mut() -= 1;
|
||||
*selection.start.column_mut() = map.line_len(selection.start.row());
|
||||
selection.start = map.clip_point(selection.start, Bias::Left);
|
||||
if expand_to_surrounding_newline {
|
||||
if selection.end.row() < map.max_point().row() {
|
||||
*selection.end.row_mut() += 1;
|
||||
*selection.end.column_mut() = 0;
|
||||
selection.end = map.clip_point(selection.end, Bias::Right);
|
||||
// Don't reset the end here
|
||||
return;
|
||||
} else if selection.start.row() > 0 {
|
||||
*selection.start.row_mut() -= 1;
|
||||
*selection.start.column_mut() = map.line_len(selection.start.row());
|
||||
selection.start = map.clip_point(selection.start, Bias::Left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(_, selection.end) = map.next_line_boundary(selection.end.to_point(map));
|
||||
(_, selection.end) = map.next_line_boundary(selection.end.to_point(map));
|
||||
}
|
||||
} else {
|
||||
// If the motion is exclusive and the end of the motion is in column 1, the
|
||||
// end of the motion is moved to the end of the previous line and the motion
|
||||
|
@ -222,6 +232,7 @@ impl Motion {
|
|||
// but "d}" will not include that line.
|
||||
let mut inclusive = self.inclusive();
|
||||
if !inclusive
|
||||
&& self != Motion::Backspace
|
||||
&& selection.end.row() > selection.start.row()
|
||||
&& selection.end.column() == 0
|
||||
&& selection.end.row() > 0
|
||||
|
|
|
@ -372,7 +372,7 @@ mod test {
|
|||
Mode::{self, *},
|
||||
Namespace, Operator,
|
||||
},
|
||||
test::{NeovimBackedTestContext, VimTestContext},
|
||||
test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
|
||||
};
|
||||
|
||||
#[gpui::test]
|
||||
|
@ -741,11 +741,14 @@ mod test {
|
|||
brown ˇfox
|
||||
jumps ˇover"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇ
|
||||
brown fox"})
|
||||
.await;
|
||||
brown fox"},
|
||||
ExemptionFeatures::DeletionOnEmptyLine,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
|
|
@ -85,372 +85,271 @@ fn expand_changed_word_selection(
|
|||
mod test {
|
||||
use indoc::indoc;
|
||||
|
||||
use crate::{
|
||||
state::Mode,
|
||||
test::{NeovimBackedTestContext, VimTestContext},
|
||||
};
|
||||
use crate::test::{ExemptionFeatures, NeovimBackedTestContext};
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_h(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "h"]).mode_after(Mode::Insert);
|
||||
cx.assert("Teˇst", "Tˇst");
|
||||
cx.assert("Tˇest", "ˇest");
|
||||
cx.assert("ˇTest", "ˇTest");
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
Test
|
||||
ˇtest"},
|
||||
indoc! {"
|
||||
Test
|
||||
ˇtest"},
|
||||
);
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "h"]);
|
||||
cx.assert("Teˇst").await;
|
||||
cx.assert("Tˇest").await;
|
||||
cx.assert("ˇTest").await;
|
||||
cx.assert(indoc! {"
|
||||
Test
|
||||
ˇtest"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_backspace(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = NeovimBackedTestContext::new(cx)
|
||||
.await
|
||||
.binding(["c", "backspace"]);
|
||||
cx.assert("Teˇst").await;
|
||||
cx.assert("Tˇest").await;
|
||||
cx.assert("ˇTest").await;
|
||||
cx.assert(indoc! {"
|
||||
Test
|
||||
ˇtest"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_l(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "l"]).mode_after(Mode::Insert);
|
||||
cx.assert("Teˇst", "Teˇt");
|
||||
cx.assert("Tesˇt", "Tesˇ");
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "l"]);
|
||||
cx.assert("Teˇst").await;
|
||||
cx.assert("Tesˇt").await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_w(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "w"]).mode_after(Mode::Insert);
|
||||
cx.assert("Teˇst", "Teˇ");
|
||||
cx.assert("Tˇest test", "Tˇ test");
|
||||
cx.assert("Testˇ test", "Testˇtest");
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "w"]);
|
||||
cx.assert("Teˇst").await;
|
||||
cx.assert("Tˇest test").await;
|
||||
cx.assert("Testˇ test").await;
|
||||
cx.assert(indoc! {"
|
||||
Test teˇst
|
||||
test"},
|
||||
indoc! {"
|
||||
Test teˇ
|
||||
test"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
test"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
Test tesˇt
|
||||
test"},
|
||||
indoc! {"
|
||||
Test tesˇ
|
||||
test"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
test"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
indoc! {"
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
);
|
||||
test"})
|
||||
.await;
|
||||
|
||||
let mut cx = cx.binding(["c", "shift-w"]);
|
||||
cx.assert("Test teˇst-test test", "Test teˇ test");
|
||||
cx.assert("Test teˇst-test test").await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_e(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "e"]).mode_after(Mode::Insert);
|
||||
cx.assert("Teˇst Test", "Teˇ Test");
|
||||
cx.assert("Tˇest test", "Tˇ test");
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "e"]);
|
||||
cx.assert("Teˇst Test").await;
|
||||
cx.assert("Tˇest test").await;
|
||||
cx.assert(indoc! {"
|
||||
Test teˇst
|
||||
test"},
|
||||
indoc! {"
|
||||
Test teˇ
|
||||
test"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
test"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
Test tesˇt
|
||||
test"},
|
||||
"Test tesˇ",
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
test"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
indoc! {"
|
||||
Test test
|
||||
ˇ"},
|
||||
);
|
||||
test"})
|
||||
.await;
|
||||
|
||||
let mut cx = cx.binding(["c", "shift-e"]);
|
||||
cx.assert("Test teˇst-test test", "Test teˇ test");
|
||||
cx.assert("Test teˇst-test test").await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_b(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "b"]).mode_after(Mode::Insert);
|
||||
cx.assert("Teˇst Test", "ˇst Test");
|
||||
cx.assert("Test ˇtest", "ˇtest");
|
||||
cx.assert("Test1 test2 ˇtest3", "Test1 ˇtest3");
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "b"]);
|
||||
cx.assert("Teˇst Test").await;
|
||||
cx.assert("Test ˇtest").await;
|
||||
cx.assert("Test1 test2 ˇtest3").await;
|
||||
cx.assert(indoc! {"
|
||||
Test test
|
||||
ˇtest"},
|
||||
indoc! {"
|
||||
Test ˇ
|
||||
test"},
|
||||
);
|
||||
ˇtest"})
|
||||
.await;
|
||||
println!("Marker");
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
cx.assert(indoc! {"
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
indoc! {"
|
||||
Test ˇ
|
||||
|
||||
test"},
|
||||
);
|
||||
test"})
|
||||
.await;
|
||||
|
||||
let mut cx = cx.binding(["c", "shift-b"]);
|
||||
cx.assert("Test test-test ˇtest", "Test ˇtest");
|
||||
cx.assert("Test test-test ˇtest").await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_end_of_line(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "$"]).mode_after(Mode::Insert);
|
||||
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"},
|
||||
);
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "$"]);
|
||||
cx.assert(indoc! {"
|
||||
The qˇuick
|
||||
brown fox"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
ˇ
|
||||
brown fox"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_0(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "0"]).mode_after(Mode::Insert);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The qˇuick
|
||||
brown fox"},
|
||||
indoc! {"
|
||||
ˇuick
|
||||
brown fox"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇ
|
||||
brown fox"},
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇ
|
||||
brown fox"},
|
||||
);
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "0"]);
|
||||
cx.assert(indoc! {"
|
||||
The qˇuick
|
||||
brown fox"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
ˇ
|
||||
brown fox"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_k(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "k"]).mode_after(Mode::Insert);
|
||||
cx.assert(
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "k"]);
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown ˇfox
|
||||
jumps over"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps ˇover"})
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown ˇfox
|
||||
jumps over"},
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
ˇ
|
||||
jumps over"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps ˇover"},
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇ"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over"},
|
||||
indoc! {"
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over"},
|
||||
indoc! {"
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over"},
|
||||
);
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_j(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "j"]).mode_after(Mode::Insert);
|
||||
cx.assert(
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "j"]);
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown ˇfox
|
||||
jumps over"})
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown ˇfox
|
||||
jumps over"},
|
||||
The quick
|
||||
brown fox
|
||||
jumps ˇover"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over"})
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇ"},
|
||||
);
|
||||
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! {"
|
||||
ˇ
|
||||
jumps over"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
ˇ"},
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
ˇ"},
|
||||
);
|
||||
The quick
|
||||
brown fox
|
||||
ˇ"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_end_of_document(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "shift-g"]).mode_after(Mode::Insert);
|
||||
cx.assert(
|
||||
let mut cx = NeovimBackedTestContext::new(cx)
|
||||
.await
|
||||
.binding(["c", "shift-g"]);
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"})
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
the lˇazy"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇ"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇ"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
the lˇazy"},
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
ˇ"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
ˇ"},
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
ˇ"},
|
||||
);
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
ˇ"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_change_gg(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["c", "g", "g"]).mode_after(Mode::Insert);
|
||||
cx.assert(
|
||||
let mut cx = NeovimBackedTestContext::new(cx)
|
||||
.await
|
||||
.binding(["c", "g", "g"]);
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
the lˇazy"})
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
ˇ
|
||||
jumps over
|
||||
the lazy"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
the lˇazy"},
|
||||
"ˇ",
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
indoc! {"
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
indoc! {"
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
);
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
@ -493,14 +392,15 @@ mod test {
|
|||
async fn test_repeated_cb(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||
|
||||
// Changing back any number of times from the start of the file doesn't
|
||||
// switch to insert mode in vim. This is weird and painful to implement
|
||||
cx.add_initial_state_exemption(indoc! {"
|
||||
cx.add_initial_state_exemptions(
|
||||
indoc! {"
|
||||
ˇThe quick brown
|
||||
|
||||
|
||||
fox jumps-over
|
||||
the lazy dog
|
||||
"});
|
||||
"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
);
|
||||
|
||||
for count in 1..=5 {
|
||||
cx.assert_binding_matches_all(
|
||||
|
|
|
@ -96,354 +96,256 @@ pub fn delete_object(vim: &mut Vim, object: Object, around: bool, cx: &mut Mutab
|
|||
mod test {
|
||||
use indoc::indoc;
|
||||
|
||||
use crate::{state::Mode, test::VimTestContext};
|
||||
use crate::{
|
||||
state::Mode,
|
||||
test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
|
||||
};
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_h(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "h"]);
|
||||
cx.assert("Teˇst", "Tˇst");
|
||||
cx.assert("Tˇest", "ˇest");
|
||||
cx.assert("ˇTest", "ˇTest");
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
Test
|
||||
ˇtest"},
|
||||
indoc! {"
|
||||
Test
|
||||
ˇtest"},
|
||||
);
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "h"]);
|
||||
cx.assert("Teˇst").await;
|
||||
cx.assert("Tˇest").await;
|
||||
cx.assert("ˇTest").await;
|
||||
cx.assert(indoc! {"
|
||||
Test
|
||||
ˇtest"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_l(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "l"]);
|
||||
cx.assert("ˇTest", "ˇest");
|
||||
cx.assert("Teˇst", "Teˇt");
|
||||
cx.assert("Tesˇt", "Teˇs");
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "l"]);
|
||||
cx.assert("ˇTest").await;
|
||||
cx.assert("Teˇst").await;
|
||||
cx.assert("Tesˇt").await;
|
||||
cx.assert(indoc! {"
|
||||
Tesˇt
|
||||
test"},
|
||||
indoc! {"
|
||||
Teˇs
|
||||
test"},
|
||||
);
|
||||
test"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_w(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "w"]);
|
||||
cx.assert("Teˇst", "Tˇe");
|
||||
cx.assert("Tˇest test", "Tˇtest");
|
||||
cx.assert(
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "w"]);
|
||||
cx.assert("Teˇst").await;
|
||||
cx.assert("Tˇest test").await;
|
||||
cx.assert(indoc! {"
|
||||
Test teˇst
|
||||
test"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
Test tesˇt
|
||||
test"})
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
Test teˇst
|
||||
test"},
|
||||
indoc! {"
|
||||
Test tˇe
|
||||
test"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
Test tesˇt
|
||||
test"},
|
||||
indoc! {"
|
||||
Test teˇs
|
||||
test"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
indoc! {"
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
);
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
ExemptionFeatures::DeletionOnEmptyLine,
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut cx = cx.binding(["d", "shift-w"]);
|
||||
cx.assert("Test teˇst-test test", "Test teˇtest");
|
||||
cx.assert("Test teˇst-test test").await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_e(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "e"]);
|
||||
cx.assert("Teˇst Test", "Teˇ Test");
|
||||
cx.assert("Tˇest test", "Tˇ test");
|
||||
cx.assert(
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "e"]);
|
||||
cx.assert("Teˇst Test").await;
|
||||
cx.assert("Tˇest test").await;
|
||||
cx.assert(indoc! {"
|
||||
Test teˇst
|
||||
test"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
Test tesˇt
|
||||
test"})
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
Test teˇst
|
||||
test"},
|
||||
indoc! {"
|
||||
Test tˇe
|
||||
test"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
Test tesˇt
|
||||
test"},
|
||||
"Test teˇs",
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
indoc! {"
|
||||
Test test
|
||||
ˇ"},
|
||||
);
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
ExemptionFeatures::DeletionOnEmptyLine,
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut cx = cx.binding(["d", "shift-e"]);
|
||||
cx.assert("Test teˇst-test test", "Test teˇ test");
|
||||
cx.assert("Test teˇst-test test").await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_b(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "b"]);
|
||||
cx.assert("Teˇst Test", "ˇst Test");
|
||||
cx.assert("Test ˇtest", "ˇtest");
|
||||
cx.assert("Test1 test2 ˇtest3", "Test1 ˇtest3");
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
Test test
|
||||
ˇtest"},
|
||||
// Trailing whitespace after cursor
|
||||
indoc! {"
|
||||
Testˇ
|
||||
test"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
Test test
|
||||
ˇ
|
||||
test"},
|
||||
// Trailing whitespace after cursor
|
||||
indoc! {"
|
||||
Testˇ
|
||||
|
||||
test"},
|
||||
);
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "b"]);
|
||||
cx.assert("Teˇst Test").await;
|
||||
cx.assert("Test ˇtest").await;
|
||||
cx.assert("Test1 test2 ˇtest3").await;
|
||||
cx.assert(indoc! {"
|
||||
Test test
|
||||
ˇtest"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
Test test
|
||||
ˇ
|
||||
test"})
|
||||
.await;
|
||||
|
||||
let mut cx = cx.binding(["d", "shift-b"]);
|
||||
cx.assert("Test test-test ˇtest", "Test ˇtest");
|
||||
cx.assert("Test test-test ˇtest").await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_end_of_line(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["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"},
|
||||
);
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "$"]);
|
||||
cx.assert(indoc! {"
|
||||
The qˇuick
|
||||
brown fox"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
ˇ
|
||||
brown fox"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_0(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "0"]);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The qˇuick
|
||||
brown fox"},
|
||||
indoc! {"
|
||||
ˇuick
|
||||
brown fox"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇ
|
||||
brown fox"},
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇ
|
||||
brown fox"},
|
||||
);
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "0"]);
|
||||
cx.assert(indoc! {"
|
||||
The qˇuick
|
||||
brown fox"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
ˇ
|
||||
brown fox"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_k(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "k"]);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown ˇfox
|
||||
jumps over"},
|
||||
"jumps ˇover",
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps ˇover"},
|
||||
"The quˇick",
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over"},
|
||||
indoc! {"
|
||||
brownˇ fox
|
||||
jumps over"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
ˇbrown fox
|
||||
jumps over"},
|
||||
"ˇjumps over",
|
||||
);
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "k"]);
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown ˇfox
|
||||
jumps over"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps ˇover"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
ˇbrown fox
|
||||
jumps over"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_j(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "j"]);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown ˇfox
|
||||
jumps over"},
|
||||
"The quˇick",
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps ˇover"},
|
||||
indoc! {"
|
||||
The quick
|
||||
brown ˇfox"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over"},
|
||||
"jumpsˇ over",
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
ˇ"},
|
||||
indoc! {"
|
||||
The quick
|
||||
ˇbrown fox"},
|
||||
);
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "j"]);
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown ˇfox
|
||||
jumps over"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps ˇover"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
ˇ"})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_end_of_document(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "shift-g"]);
|
||||
cx.assert(
|
||||
let mut cx = NeovimBackedTestContext::new(cx)
|
||||
.await
|
||||
.binding(["d", "shift-g"]);
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"})
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
"The qˇuick",
|
||||
);
|
||||
cx.assert(
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
the lˇazy"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
"The qˇuick",
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
the lˇazy"},
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumpsˇ over"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
ˇ"},
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
ˇjumps over"},
|
||||
);
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
ˇ"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_delete_gg(cx: &mut gpui::TestAppContext) {
|
||||
let cx = VimTestContext::new(cx, true).await;
|
||||
let mut cx = cx.binding(["d", "g", "g"]);
|
||||
cx.assert(
|
||||
let mut cx = NeovimBackedTestContext::new(cx)
|
||||
.await
|
||||
.binding(["d", "g", "g"]);
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"})
|
||||
.await;
|
||||
cx.assert(indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
the lˇazy"})
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
The quick
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
cx.assert_exempted(
|
||||
indoc! {"
|
||||
jumpsˇ over
|
||||
the lazy"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The quick
|
||||
brown fox
|
||||
jumps over
|
||||
the lˇazy"},
|
||||
"ˇ",
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
The qˇuick
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
indoc! {"
|
||||
brownˇ fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
);
|
||||
cx.assert(
|
||||
indoc! {"
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
indoc! {"
|
||||
ˇbrown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
);
|
||||
ˇ
|
||||
brown fox
|
||||
jumps over
|
||||
the lazy"},
|
||||
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
|
|
@ -431,7 +431,7 @@ fn surrounding_markers(
|
|||
mod test {
|
||||
use indoc::indoc;
|
||||
|
||||
use crate::test::NeovimBackedTestContext;
|
||||
use crate::test::{ExemptionFeatures, NeovimBackedTestContext};
|
||||
|
||||
const WORD_LOCATIONS: &'static str = indoc! {"
|
||||
The quick ˇbrowˇnˇ
|
||||
|
@ -482,25 +482,46 @@ mod test {
|
|||
|
||||
cx.assert_binding_matches_all(["v", "i", "w"], WORD_LOCATIONS)
|
||||
.await;
|
||||
// Visual text objects are slightly broken when used with non empty selections
|
||||
// cx.assert_binding_matches_all(["v", "h", "i", "w"], WORD_LOCATIONS)
|
||||
// .await;
|
||||
// cx.assert_binding_matches_all(["v", "l", "i", "w"], WORD_LOCATIONS)
|
||||
// .await;
|
||||
cx.assert_binding_matches_all_exempted(
|
||||
["v", "h", "i", "w"],
|
||||
WORD_LOCATIONS,
|
||||
ExemptionFeatures::NonEmptyVisualTextObjects,
|
||||
)
|
||||
.await;
|
||||
cx.assert_binding_matches_all_exempted(
|
||||
["v", "l", "i", "w"],
|
||||
WORD_LOCATIONS,
|
||||
ExemptionFeatures::NonEmptyVisualTextObjects,
|
||||
)
|
||||
.await;
|
||||
cx.assert_binding_matches_all(["v", "i", "shift-w"], WORD_LOCATIONS)
|
||||
.await;
|
||||
|
||||
// Visual text objects are slightly broken when used with non empty selections
|
||||
// cx.assert_binding_matches_all(["v", "i", "h", "shift-w"], WORD_LOCATIONS)
|
||||
// .await;
|
||||
// cx.assert_binding_matches_all(["v", "i", "l", "shift-w"], WORD_LOCATIONS)
|
||||
// .await;
|
||||
cx.assert_binding_matches_all_exempted(
|
||||
["v", "i", "h", "shift-w"],
|
||||
WORD_LOCATIONS,
|
||||
ExemptionFeatures::NonEmptyVisualTextObjects,
|
||||
)
|
||||
.await;
|
||||
cx.assert_binding_matches_all_exempted(
|
||||
["v", "i", "l", "shift-w"],
|
||||
WORD_LOCATIONS,
|
||||
ExemptionFeatures::NonEmptyVisualTextObjects,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Visual around words is somewhat broken right now when it comes to newlines
|
||||
// cx.assert_binding_matches_all(["v", "a", "w"], WORD_LOCATIONS)
|
||||
// .await;
|
||||
// cx.assert_binding_matches_all(["v", "a", "shift-w"], WORD_LOCATIONS)
|
||||
// .await;
|
||||
cx.assert_binding_matches_all_exempted(
|
||||
["v", "a", "w"],
|
||||
WORD_LOCATIONS,
|
||||
ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
|
||||
)
|
||||
.await;
|
||||
cx.assert_binding_matches_all_exempted(
|
||||
["v", "a", "shift-w"],
|
||||
WORD_LOCATIONS,
|
||||
ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
const SENTENCE_EXAMPLES: &[&'static str] = &[
|
||||
|
@ -511,17 +532,15 @@ mod test {
|
|||
the lazy doˇgˇ.ˇ ˇThe quick ˇ
|
||||
brown fox jumps over
|
||||
"},
|
||||
// Position of the cursor after deletion between lines isn't quite right.
|
||||
// Deletion in a sentence at the start of a line with whitespace is incorrect.
|
||||
// indoc! {"
|
||||
// The quick brown fox jumps.
|
||||
// Over the lazy dog
|
||||
// ˇ
|
||||
// ˇ
|
||||
// ˇ fox-jumpˇs over
|
||||
// the lazy dog.ˇ
|
||||
// ˇ
|
||||
// "},
|
||||
indoc! {"
|
||||
The quick brown fox jumps.
|
||||
Over the lazy dog
|
||||
ˇ
|
||||
ˇ
|
||||
ˇ fox-jumpˇs over
|
||||
the lazy dog.ˇ
|
||||
ˇ
|
||||
"},
|
||||
r#"ˇThe ˇquick brownˇ.)ˇ]ˇ'ˇ" Brown ˇfox jumpsˇ.ˇ "#,
|
||||
];
|
||||
|
||||
|
@ -530,15 +549,28 @@ mod test {
|
|||
let mut cx = NeovimBackedTestContext::new(cx)
|
||||
.await
|
||||
.binding(["c", "i", "s"]);
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown fox jumps.\nOver the lazy dog\nˇ\nˇ\n fox-jumps over\nthe lazy dog.\n\n",
|
||||
ExemptionFeatures::SentenceOnEmptyLines);
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown fox jumps.\nOver the lazy dog\n\n\nˇ foxˇ-ˇjumpˇs over\nthe lazy dog.\n\n",
|
||||
ExemptionFeatures::SentenceAtStartOfLineWithWhitespace);
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown fox jumps.\nOver the lazy dog\n\n\n fox-jumps over\nthe lazy dog.ˇ\nˇ\n",
|
||||
ExemptionFeatures::SentenceAfterPunctuationAtEndOfFile);
|
||||
for sentence_example in SENTENCE_EXAMPLES {
|
||||
cx.assert_all(sentence_example).await;
|
||||
}
|
||||
|
||||
let mut cx = cx.binding(["c", "a", "s"]);
|
||||
// Resulting position is slightly incorrect for unintuitive reasons.
|
||||
cx.add_initial_state_exemption("The quick brown?ˇ Fox Jumps! Over the lazy.");
|
||||
// Changing around the sentence at the end of the line doesn't remove whitespace.'
|
||||
cx.add_initial_state_exemption("The quick brown.)]\'\" Brown fox jumps.ˇ ");
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown?ˇ Fox Jumps! Over the lazy.",
|
||||
ExemptionFeatures::IncorrectLandingPosition,
|
||||
);
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown.)]\'\" Brown fox jumps.ˇ ",
|
||||
ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
|
||||
);
|
||||
|
||||
for sentence_example in SENTENCE_EXAMPLES {
|
||||
cx.assert_all(sentence_example).await;
|
||||
|
@ -550,15 +582,29 @@ mod test {
|
|||
let mut cx = NeovimBackedTestContext::new(cx)
|
||||
.await
|
||||
.binding(["d", "i", "s"]);
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown fox jumps.\nOver the lazy dog\nˇ\nˇ\n fox-jumps over\nthe lazy dog.\n\n",
|
||||
ExemptionFeatures::SentenceOnEmptyLines);
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown fox jumps.\nOver the lazy dog\n\n\nˇ foxˇ-ˇjumpˇs over\nthe lazy dog.\n\n",
|
||||
ExemptionFeatures::SentenceAtStartOfLineWithWhitespace);
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown fox jumps.\nOver the lazy dog\n\n\n fox-jumps over\nthe lazy dog.ˇ\nˇ\n",
|
||||
ExemptionFeatures::SentenceAfterPunctuationAtEndOfFile);
|
||||
|
||||
for sentence_example in SENTENCE_EXAMPLES {
|
||||
cx.assert_all(sentence_example).await;
|
||||
}
|
||||
|
||||
let mut cx = cx.binding(["d", "a", "s"]);
|
||||
// Resulting position is slightly incorrect for unintuitive reasons.
|
||||
cx.add_initial_state_exemption("The quick brown?ˇ Fox Jumps! Over the lazy.");
|
||||
// Changing around the sentence at the end of the line doesn't remove whitespace.'
|
||||
cx.add_initial_state_exemption("The quick brown.)]\'\" Brown fox jumps.ˇ ");
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown?ˇ Fox Jumps! Over the lazy.",
|
||||
ExemptionFeatures::IncorrectLandingPosition,
|
||||
);
|
||||
cx.add_initial_state_exemptions(
|
||||
"The quick brown.)]\'\" Brown fox jumps.ˇ ",
|
||||
ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
|
||||
);
|
||||
|
||||
for sentence_example in SENTENCE_EXAMPLES {
|
||||
cx.assert_all(sentence_example).await;
|
||||
|
@ -571,14 +617,18 @@ mod test {
|
|||
.await
|
||||
.binding(["v", "i", "s"]);
|
||||
for sentence_example in SENTENCE_EXAMPLES {
|
||||
cx.assert_all(sentence_example).await;
|
||||
cx.assert_all_exempted(sentence_example, ExemptionFeatures::SentenceOnEmptyLines)
|
||||
.await;
|
||||
}
|
||||
|
||||
// Visual around sentences is somewhat broken right now when it comes to newlines
|
||||
// let mut cx = cx.binding(["d", "a", "s"]);
|
||||
// for sentence_example in SENTENCE_EXAMPLES {
|
||||
// cx.assert_all(sentence_example).await;
|
||||
// }
|
||||
let mut cx = cx.binding(["v", "a", "s"]);
|
||||
for sentence_example in SENTENCE_EXAMPLES {
|
||||
cx.assert_all_exempted(
|
||||
sentence_example,
|
||||
ExemptionFeatures::AroundSentenceStartingBetweenIncludesWrongWhitespace,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
// Test string with "`" for opening surrounders and "'" for closing surrounders
|
||||
|
@ -588,14 +638,13 @@ mod test {
|
|||
the ˇlazy dˇ'ˇoˇ`ˇg"};
|
||||
|
||||
const SURROUNDING_OBJECTS: &[(char, char)] = &[
|
||||
// ('\'', '\''), // Quote,
|
||||
// ('`', '`'), // Back Quote
|
||||
// ('"', '"'), // Double Quote
|
||||
// ('"', '"'), // Double Quote
|
||||
('(', ')'), // Parentheses
|
||||
('[', ']'), // SquareBrackets
|
||||
('{', '}'), // CurlyBrackets
|
||||
('<', '>'), // AngleBrackets
|
||||
('\'', '\''), // Quote
|
||||
('`', '`'), // Back Quote
|
||||
('"', '"'), // Double Quote
|
||||
('(', ')'), // Parentheses
|
||||
('[', ']'), // SquareBrackets
|
||||
('{', '}'), // CurlyBrackets
|
||||
('<', '>'), // AngleBrackets
|
||||
];
|
||||
|
||||
#[gpui::test]
|
||||
|
@ -603,16 +652,23 @@ mod test {
|
|||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||
|
||||
for (start, end) in SURROUNDING_OBJECTS {
|
||||
if ((start == &'\'' || start == &'`' || start == &'"')
|
||||
&& !ExemptionFeatures::QuotesSeekForward.supported())
|
||||
|| (start == &'<' && !ExemptionFeatures::AngleBracketsFreezeNeovim.supported())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let marked_string = SURROUNDING_MARKER_STRING
|
||||
.replace('`', &start.to_string())
|
||||
.replace('\'', &end.to_string());
|
||||
|
||||
// cx.assert_binding_matches_all(["c", "i", &start.to_string()], &marked_string)
|
||||
// .await;
|
||||
cx.assert_binding_matches_all(["c", "i", &start.to_string()], &marked_string)
|
||||
.await;
|
||||
cx.assert_binding_matches_all(["c", "i", &end.to_string()], &marked_string)
|
||||
.await;
|
||||
// cx.assert_binding_matches_all(["c", "a", &start.to_string()], &marked_string)
|
||||
// .await;
|
||||
cx.assert_binding_matches_all(["c", "a", &start.to_string()], &marked_string)
|
||||
.await;
|
||||
cx.assert_binding_matches_all(["c", "a", &end.to_string()], &marked_string)
|
||||
.await;
|
||||
}
|
||||
|
@ -623,16 +679,22 @@ mod test {
|
|||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||
|
||||
for (start, end) in SURROUNDING_OBJECTS {
|
||||
if ((start == &'\'' || start == &'`' || start == &'"')
|
||||
&& !ExemptionFeatures::QuotesSeekForward.supported())
|
||||
|| (start == &'<' && !ExemptionFeatures::AngleBracketsFreezeNeovim.supported())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let marked_string = SURROUNDING_MARKER_STRING
|
||||
.replace('`', &start.to_string())
|
||||
.replace('\'', &end.to_string());
|
||||
|
||||
// cx.assert_binding_matches_all(["d", "i", &start.to_string()], &marked_string)
|
||||
// .await;
|
||||
cx.assert_binding_matches_all(["d", "i", &start.to_string()], &marked_string)
|
||||
.await;
|
||||
cx.assert_binding_matches_all(["d", "i", &end.to_string()], &marked_string)
|
||||
.await;
|
||||
// cx.assert_binding_matches_all(["d", "a", &start.to_string()], &marked_string)
|
||||
// .await;
|
||||
cx.assert_binding_matches_all(["d", "a", &start.to_string()], &marked_string)
|
||||
.await;
|
||||
cx.assert_binding_matches_all(["d", "a", &end.to_string()], &marked_string)
|
||||
.await;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use gpui::ContextHandle;
|
|||
|
||||
use crate::state::Mode;
|
||||
|
||||
use super::NeovimBackedTestContext;
|
||||
use super::{ExemptionFeatures, NeovimBackedTestContext, SUPPORTED_FEATURES};
|
||||
|
||||
pub struct NeovimBackedBindingTestContext<'a, const COUNT: usize> {
|
||||
cx: NeovimBackedTestContext<'a>,
|
||||
|
@ -42,6 +42,20 @@ impl<'a, const COUNT: usize> NeovimBackedBindingTestContext<'a, COUNT> {
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn assert_exempted(
|
||||
&mut self,
|
||||
marked_positions: &str,
|
||||
feature: ExemptionFeatures,
|
||||
) -> Option<(ContextHandle, ContextHandle)> {
|
||||
if SUPPORTED_FEATURES.contains(&feature) {
|
||||
self.cx
|
||||
.assert_binding_matches(self.keystrokes_under_test, marked_positions)
|
||||
.await
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assert_manual(
|
||||
&mut self,
|
||||
initial_state: &str,
|
||||
|
@ -63,6 +77,18 @@ impl<'a, const COUNT: usize> NeovimBackedBindingTestContext<'a, COUNT> {
|
|||
.assert_binding_matches_all(self.keystrokes_under_test, marked_positions)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn assert_all_exempted(
|
||||
&mut self,
|
||||
marked_positions: &str,
|
||||
feature: ExemptionFeatures,
|
||||
) {
|
||||
if SUPPORTED_FEATURES.contains(&feature) {
|
||||
self.cx
|
||||
.assert_binding_matches_all(self.keystrokes_under_test, marked_positions)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const COUNT: usize> Deref for NeovimBackedBindingTestContext<'a, COUNT> {
|
||||
|
|
|
@ -8,6 +8,45 @@ use util::test::marked_text_offsets;
|
|||
use super::{neovim_connection::NeovimConnection, NeovimBackedBindingTestContext, VimTestContext};
|
||||
use crate::state::Mode;
|
||||
|
||||
pub const SUPPORTED_FEATURES: &[ExemptionFeatures] = &[];
|
||||
|
||||
/// Enum representing features we have tests for but which don't work, yet. Used
|
||||
/// to add exemptions and automatically
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum ExemptionFeatures {
|
||||
// MOTIONS
|
||||
// Deletions on empty lines miss some newlines
|
||||
DeletionOnEmptyLine,
|
||||
// When a motion fails, it should should not apply linewise operations
|
||||
OperatorAbortsOnFailedMotion,
|
||||
|
||||
// OBJECTS
|
||||
// Resulting position after the operation is slightly incorrect for unintuitive reasons.
|
||||
IncorrectLandingPosition,
|
||||
// Operator around the text object at the end of the line doesn't remove whitespace.
|
||||
AroundObjectLeavesWhitespaceAtEndOfLine,
|
||||
// Sentence object on empty lines
|
||||
SentenceOnEmptyLines,
|
||||
// Whitespace isn't included with text objects at the start of the line
|
||||
SentenceAtStartOfLineWithWhitespace,
|
||||
// Whitespace around sentences is slightly incorrect when starting between sentences
|
||||
AroundSentenceStartingBetweenIncludesWrongWhitespace,
|
||||
// Non empty selection with text objects in visual mode
|
||||
NonEmptyVisualTextObjects,
|
||||
// Quote style surrounding text objects don't seek forward properly
|
||||
QuotesSeekForward,
|
||||
// Neovim freezes up for some reason with angle brackets
|
||||
AngleBracketsFreezeNeovim,
|
||||
// Sentence Doesn't backtrack when its at the end of the file
|
||||
SentenceAfterPunctuationAtEndOfFile,
|
||||
}
|
||||
|
||||
impl ExemptionFeatures {
|
||||
pub fn supported(&self) -> bool {
|
||||
SUPPORTED_FEATURES.contains(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NeovimBackedTestContext<'a> {
|
||||
cx: VimTestContext<'a>,
|
||||
// Lookup for exempted assertions. Keyed by the insertion text, and with a value indicating which
|
||||
|
@ -27,10 +66,22 @@ impl<'a> NeovimBackedTestContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_initial_state_exemption(&mut self, initial_state: &str) {
|
||||
let initial_state = initial_state.to_string();
|
||||
// None represents all keybindings being exempted for that initial state
|
||||
self.exemptions.insert(initial_state, None);
|
||||
pub fn add_initial_state_exemptions(
|
||||
&mut self,
|
||||
marked_positions: &str,
|
||||
missing_feature: ExemptionFeatures, // Feature required to support this exempted test case
|
||||
) {
|
||||
if !missing_feature.supported() {
|
||||
let (unmarked_text, cursor_offsets) = marked_text_offsets(marked_positions);
|
||||
|
||||
for cursor_offset in cursor_offsets.iter() {
|
||||
let mut marked_text = unmarked_text.clone();
|
||||
marked_text.insert(*cursor_offset, 'ˇ');
|
||||
|
||||
// None represents all keybindings being exempted for that initial state
|
||||
self.exemptions.insert(marked_text, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn simulate_shared_keystroke(&mut self, keystroke_text: &str) -> ContextHandle {
|
||||
|
@ -120,6 +171,18 @@ impl<'a> NeovimBackedTestContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn assert_binding_matches_all_exempted<const COUNT: usize>(
|
||||
&mut self,
|
||||
keystrokes: [&str; COUNT],
|
||||
marked_positions: &str,
|
||||
feature: ExemptionFeatures,
|
||||
) {
|
||||
if SUPPORTED_FEATURES.contains(&feature) {
|
||||
self.assert_binding_matches_all(keystrokes, marked_positions)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
pub fn binding<const COUNT: usize>(
|
||||
self,
|
||||
keystrokes: [&'static str; COUNT],
|
||||
|
|
|
@ -38,11 +38,6 @@ impl<'a, const COUNT: usize> VimBindingTestContext<'a, COUNT> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mode_after(mut self, mode_after: Mode) -> Self {
|
||||
self.mode_after = mode_after;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn assert(&mut self, initial_state: &str, state_after: &str) {
|
||||
self.cx.assert_binding(
|
||||
self.keystrokes_under_test,
|
||||
|
|
1
crates/vim/test_data/test_change_0.json
Normal file
1
crates/vim/test_data/test_change_0.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"uick\nbrown fox"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"The quick\n\nbrown fox"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_b.json
Normal file
1
crates/vim/test_data/test_change_b.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"st Test"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"test"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"Test1 test3"},{"Mode":"Insert"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Insert"},{"Text":"Test \ntest"},{"Mode":"Insert"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Insert"},{"Text":"Test \n\ntest"},{"Mode":"Insert"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Insert"},{"Text":"Test test"},{"Mode":"Insert"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_backspace.json
Normal file
1
crates/vim/test_data/test_change_backspace.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"Tst"},{"Mode":"Insert"},{"Selection":{"start":[0,1],"end":[0,1]}},{"Mode":"Insert"},{"Text":"est"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"Test"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"Testtest"},{"Mode":"Insert"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_e.json
Normal file
1
crates/vim/test_data/test_change_e.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"Te Test"},{"Mode":"Insert"},{"Selection":{"start":[0,2],"end":[0,2]}},{"Mode":"Insert"},{"Text":"T test"},{"Mode":"Insert"},{"Selection":{"start":[0,1],"end":[0,1]}},{"Mode":"Insert"},{"Text":"Test te\ntest"},{"Mode":"Insert"},{"Selection":{"start":[0,7],"end":[0,7]}},{"Mode":"Insert"},{"Text":"Test tes"},{"Mode":"Insert"},{"Selection":{"start":[0,8],"end":[0,8]}},{"Mode":"Insert"},{"Text":"Test test\n"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"},{"Text":"Test te test"},{"Mode":"Insert"},{"Selection":{"start":[0,7],"end":[0,7]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_end_of_document.json
Normal file
1
crates/vim/test_data/test_change_end_of_document.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"The quick\n"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"},{"Text":"The quick\n"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_end_of_line.json
Normal file
1
crates/vim/test_data/test_change_end_of_line.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"The q\nbrown fox"},{"Mode":"Insert"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Insert"},{"Text":"The quick\n\nbrown fox"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_gg.json
Normal file
1
crates/vim/test_data/test_change_gg.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"\njumps over\nthe lazy"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":""},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_h.json
Normal file
1
crates/vim/test_data/test_change_h.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"Tst"},{"Mode":"Insert"},{"Selection":{"start":[0,1],"end":[0,1]}},{"Mode":"Insert"},{"Text":"est"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"Test"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"Test\ntest"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_j.json
Normal file
1
crates/vim/test_data/test_change_j.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"The quick\n"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"},{"Text":"\njumps over"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_k.json
Normal file
1
crates/vim/test_data/test_change_k.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"\njumps over"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"The quick\n"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"}]
|
1
crates/vim/test_data/test_change_l.json
Normal file
1
crates/vim/test_data/test_change_l.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"Tet"},{"Mode":"Insert"},{"Selection":{"start":[0,2],"end":[0,2]}},{"Mode":"Insert"},{"Text":"Tes"},{"Mode":"Insert"},{"Selection":{"start":[0,3],"end":[0,3]}},{"Mode":"Insert"}]
|
File diff suppressed because one or more lines are too long
1
crates/vim/test_data/test_change_w.json
Normal file
1
crates/vim/test_data/test_change_w.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"Te"},{"Mode":"Insert"},{"Selection":{"start":[0,2],"end":[0,2]}},{"Mode":"Insert"},{"Text":"T test"},{"Mode":"Insert"},{"Selection":{"start":[0,1],"end":[0,1]}},{"Mode":"Insert"},{"Text":"Testtest"},{"Mode":"Insert"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Insert"},{"Text":"Test te\ntest"},{"Mode":"Insert"},{"Selection":{"start":[0,7],"end":[0,7]}},{"Mode":"Insert"},{"Text":"Test tes\ntest"},{"Mode":"Insert"},{"Selection":{"start":[0,8],"end":[0,8]}},{"Mode":"Insert"},{"Text":"Test test\n\ntest"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"},{"Text":"Test te test"},{"Mode":"Insert"},{"Selection":{"start":[0,7],"end":[0,7]}},{"Mode":"Insert"}]
|
|
@ -1 +1 @@
|
|||
[{"Text":""},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":""},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"brown fox\njumps over"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"},{"Text":"The quick\njumps over"},{"Mode":"Normal"},{"Selection":{"start":[1,6],"end":[1,6]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox"},{"Mode":"Normal"},{"Selection":{"start":[1,6],"end":[1,6]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"}]
|
||||
[{"Text":""},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":""},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"brown fox\njumps over"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"},{"Text":"The quick\njumps over"},{"Mode":"Normal"},{"Selection":{"start":[1,6],"end":[1,6]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox"},{"Mode":"Normal"},{"Selection":{"start":[1,6],"end":[1,6]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_0.json
Normal file
1
crates/vim/test_data/test_delete_0.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"uick\nbrown fox"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_b.json
Normal file
1
crates/vim/test_data/test_delete_b.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"st Test"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"test"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"Test1 test3"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"Test \ntest"},{"Mode":"Normal"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Normal"},{"Text":"Test \n\ntest"},{"Mode":"Normal"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Normal"},{"Text":"Test test"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_e.json
Normal file
1
crates/vim/test_data/test_delete_e.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"Te Test"},{"Mode":"Normal"},{"Selection":{"start":[0,2],"end":[0,2]}},{"Mode":"Normal"},{"Text":"T test"},{"Mode":"Normal"},{"Selection":{"start":[0,1],"end":[0,1]}},{"Mode":"Normal"},{"Text":"Test te\ntest"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"Test tes"},{"Mode":"Normal"},{"Selection":{"start":[0,7],"end":[0,7]}},{"Mode":"Normal"},{"Text":"Test te test"},{"Mode":"Normal"},{"Selection":{"start":[0,7],"end":[0,7]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_end_of_document.json
Normal file
1
crates/vim/test_data/test_delete_end_of_document.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"The quick"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"},{"Text":"The quick"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_end_of_line.json
Normal file
1
crates/vim/test_data/test_delete_end_of_line.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"The q\nbrown fox"},{"Mode":"Normal"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_gg.json
Normal file
1
crates/vim/test_data/test_delete_gg.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"jumps over\nthe lazy"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"},{"Text":""},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_h.json
Normal file
1
crates/vim/test_data/test_delete_h.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"Tst"},{"Mode":"Normal"},{"Selection":{"start":[0,1],"end":[0,1]}},{"Mode":"Normal"},{"Text":"est"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"Test"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"Test\ntest"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_j.json
Normal file
1
crates/vim/test_data/test_delete_j.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"The quick"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox\njumps over"},{"Mode":"Normal"},{"Selection":{"start":[2,6],"end":[2,6]}},{"Mode":"Normal"},{"Text":"jumps over"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox\n"},{"Mode":"Normal"},{"Selection":{"start":[2,0],"end":[2,0]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_k.json
Normal file
1
crates/vim/test_data/test_delete_k.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"jumps over"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"The quick"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox\njumps over"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"},{"Text":"brown fox\njumps over"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"}]
|
1
crates/vim/test_data/test_delete_l.json
Normal file
1
crates/vim/test_data/test_delete_l.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"est"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"Tet"},{"Mode":"Normal"},{"Selection":{"start":[0,2],"end":[0,2]}},{"Mode":"Normal"},{"Text":"Tes"},{"Mode":"Normal"},{"Selection":{"start":[0,2],"end":[0,2]}},{"Mode":"Normal"},{"Text":"Tes\ntest"},{"Mode":"Normal"},{"Selection":{"start":[0,2],"end":[0,2]}},{"Mode":"Normal"}]
|
File diff suppressed because one or more lines are too long
1
crates/vim/test_data/test_delete_w.json
Normal file
1
crates/vim/test_data/test_delete_w.json
Normal file
|
@ -0,0 +1 @@
|
|||
[{"Text":"Te"},{"Mode":"Normal"},{"Selection":{"start":[0,1],"end":[0,1]}},{"Mode":"Normal"},{"Text":"Ttest"},{"Mode":"Normal"},{"Selection":{"start":[0,1],"end":[0,1]}},{"Mode":"Normal"},{"Text":"Test te\ntest"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"Test tes\ntest"},{"Mode":"Normal"},{"Selection":{"start":[0,7],"end":[0,7]}},{"Mode":"Normal"},{"Text":"Test tetest"},{"Mode":"Normal"},{"Selection":{"start":[0,7],"end":[0,7]}},{"Mode":"Normal"}]
|
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue