Fix panic in vim motion when not listed as exclusive and add features enum to capture why tests are ignored
This commit is contained in:
parent
c295f943ba
commit
21ad375b42
34 changed files with 678 additions and 688 deletions
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
Vim,
|
Vim,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Motion {
|
pub enum Motion {
|
||||||
Left,
|
Left,
|
||||||
Backspace,
|
Backspace,
|
||||||
|
@ -139,14 +139,22 @@ impl Motion {
|
||||||
|
|
||||||
pub fn inclusive(self) -> bool {
|
pub fn inclusive(self) -> bool {
|
||||||
use Motion::*;
|
use Motion::*;
|
||||||
if self.linewise() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
EndOfLine | NextWordEnd { .. } | Matching => true,
|
Down
|
||||||
Left | Right | StartOfLine | NextWordStart { .. } | PreviousWordStart { .. } => false,
|
| Up
|
||||||
_ => panic!("Exclusivity not defined for {self:?}"),
|
| StartOfDocument
|
||||||
|
| EndOfDocument
|
||||||
|
| CurrentLine
|
||||||
|
| EndOfLine
|
||||||
|
| NextWordEnd { .. }
|
||||||
|
| Matching => true,
|
||||||
|
Left
|
||||||
|
| Backspace
|
||||||
|
| Right
|
||||||
|
| StartOfLine
|
||||||
|
| NextWordStart { .. }
|
||||||
|
| PreviousWordStart { .. }
|
||||||
|
| FirstNonWhitespace => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,10 +202,11 @@ impl Motion {
|
||||||
times: usize,
|
times: usize,
|
||||||
expand_to_surrounding_newline: bool,
|
expand_to_surrounding_newline: bool,
|
||||||
) {
|
) {
|
||||||
let (head, goal) = self.move_point(map, selection.head(), selection.goal, times);
|
let (new_head, goal) = self.move_point(map, selection.head(), selection.goal, times);
|
||||||
selection.set_head(head, goal);
|
selection.set_head(new_head, goal);
|
||||||
|
|
||||||
if self.linewise() {
|
if self.linewise() {
|
||||||
|
if selection.start != selection.end {
|
||||||
selection.start = map.prev_line_boundary(selection.start.to_point(map)).1;
|
selection.start = map.prev_line_boundary(selection.start.to_point(map)).1;
|
||||||
|
|
||||||
if expand_to_surrounding_newline {
|
if expand_to_surrounding_newline {
|
||||||
|
@ -215,6 +224,7 @@ impl Motion {
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, selection.end) = map.next_line_boundary(selection.end.to_point(map));
|
(_, selection.end) = map.next_line_boundary(selection.end.to_point(map));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the motion is exclusive and the end of the motion is in column 1, the
|
// 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
|
// 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.
|
// but "d}" will not include that line.
|
||||||
let mut inclusive = self.inclusive();
|
let mut inclusive = self.inclusive();
|
||||||
if !inclusive
|
if !inclusive
|
||||||
|
&& self != Motion::Backspace
|
||||||
&& selection.end.row() > selection.start.row()
|
&& selection.end.row() > selection.start.row()
|
||||||
&& selection.end.column() == 0
|
&& selection.end.column() == 0
|
||||||
&& selection.end.row() > 0
|
&& selection.end.row() > 0
|
||||||
|
|
|
@ -372,7 +372,7 @@ mod test {
|
||||||
Mode::{self, *},
|
Mode::{self, *},
|
||||||
Namespace, Operator,
|
Namespace, Operator,
|
||||||
},
|
},
|
||||||
test::{NeovimBackedTestContext, VimTestContext},
|
test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
@ -741,10 +741,13 @@ mod test {
|
||||||
brown ˇfox
|
brown ˇfox
|
||||||
jumps ˇover"})
|
jumps ˇover"})
|
||||||
.await;
|
.await;
|
||||||
cx.assert(indoc! {"
|
cx.assert_exempted(
|
||||||
|
indoc! {"
|
||||||
The quick
|
The quick
|
||||||
ˇ
|
ˇ
|
||||||
brown fox"})
|
brown fox"},
|
||||||
|
ExemptionFeatures::DeletionOnEmptyLine,
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,372 +85,271 @@ fn expand_changed_word_selection(
|
||||||
mod test {
|
mod test {
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
use crate::{
|
use crate::test::{ExemptionFeatures, NeovimBackedTestContext};
|
||||||
state::Mode,
|
|
||||||
test::{NeovimBackedTestContext, VimTestContext},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_change_h(cx: &mut gpui::TestAppContext) {
|
async fn test_change_h(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "h"]);
|
||||||
let mut cx = cx.binding(["c", "h"]).mode_after(Mode::Insert);
|
cx.assert("Teˇst").await;
|
||||||
cx.assert("Teˇst", "Tˇst");
|
cx.assert("Tˇest").await;
|
||||||
cx.assert("Tˇest", "ˇest");
|
cx.assert("ˇTest").await;
|
||||||
cx.assert("ˇTest", "ˇTest");
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test
|
Test
|
||||||
ˇtest"},
|
ˇtest"})
|
||||||
indoc! {"
|
.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
|
||||||
ˇtest"},
|
ˇtest"})
|
||||||
);
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_change_l(cx: &mut gpui::TestAppContext) {
|
async fn test_change_l(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "l"]);
|
||||||
let mut cx = cx.binding(["c", "l"]).mode_after(Mode::Insert);
|
cx.assert("Teˇst").await;
|
||||||
cx.assert("Teˇst", "Teˇt");
|
cx.assert("Tesˇt").await;
|
||||||
cx.assert("Tesˇt", "Tesˇ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_change_w(cx: &mut gpui::TestAppContext) {
|
async fn test_change_w(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "w"]);
|
||||||
let mut cx = cx.binding(["c", "w"]).mode_after(Mode::Insert);
|
cx.assert("Teˇst").await;
|
||||||
cx.assert("Teˇst", "Teˇ");
|
cx.assert("Tˇest test").await;
|
||||||
cx.assert("Tˇest test", "Tˇ test");
|
cx.assert("Testˇ test").await;
|
||||||
cx.assert("Testˇ test", "Testˇtest");
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test teˇst
|
Test teˇst
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test teˇ
|
cx.assert(indoc! {"
|
||||||
test"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test tesˇt
|
Test tesˇt
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test tesˇ
|
cx.assert(indoc! {"
|
||||||
test"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test test
|
Test test
|
||||||
ˇ
|
ˇ
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test test
|
|
||||||
ˇ
|
|
||||||
test"},
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut cx = cx.binding(["c", "shift-w"]);
|
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]
|
#[gpui::test]
|
||||||
async fn test_change_e(cx: &mut gpui::TestAppContext) {
|
async fn test_change_e(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "e"]);
|
||||||
let mut cx = cx.binding(["c", "e"]).mode_after(Mode::Insert);
|
cx.assert("Teˇst Test").await;
|
||||||
cx.assert("Teˇst Test", "Teˇ Test");
|
cx.assert("Tˇest test").await;
|
||||||
cx.assert("Tˇest test", "Tˇ test");
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test teˇst
|
Test teˇst
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test teˇ
|
cx.assert(indoc! {"
|
||||||
test"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test tesˇt
|
Test tesˇt
|
||||||
test"},
|
test"})
|
||||||
"Test tesˇ",
|
.await;
|
||||||
);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test test
|
Test test
|
||||||
ˇ
|
ˇ
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test test
|
|
||||||
ˇ"},
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut cx = cx.binding(["c", "shift-e"]);
|
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]
|
#[gpui::test]
|
||||||
async fn test_change_b(cx: &mut gpui::TestAppContext) {
|
async fn test_change_b(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "b"]);
|
||||||
let mut cx = cx.binding(["c", "b"]).mode_after(Mode::Insert);
|
cx.assert("Teˇst Test").await;
|
||||||
cx.assert("Teˇst Test", "ˇst Test");
|
cx.assert("Test ˇtest").await;
|
||||||
cx.assert("Test ˇtest", "ˇtest");
|
cx.assert("Test1 test2 ˇtest3").await;
|
||||||
cx.assert("Test1 test2 ˇtest3", "Test1 ˇtest3");
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test test
|
Test test
|
||||||
ˇtest"},
|
ˇtest"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test ˇ
|
|
||||||
test"},
|
|
||||||
);
|
|
||||||
println!("Marker");
|
println!("Marker");
|
||||||
cx.assert(
|
cx.assert(indoc! {"
|
||||||
indoc! {"
|
|
||||||
Test test
|
Test test
|
||||||
ˇ
|
ˇ
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test ˇ
|
|
||||||
|
|
||||||
test"},
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut cx = cx.binding(["c", "shift-b"]);
|
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]
|
#[gpui::test]
|
||||||
async fn test_change_end_of_line(cx: &mut gpui::TestAppContext) {
|
async fn test_change_end_of_line(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "$"]);
|
||||||
let mut cx = cx.binding(["c", "$"]).mode_after(Mode::Insert);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox"},
|
brown fox"})
|
||||||
indoc! {"
|
.await;
|
||||||
The qˇ
|
cx.assert(indoc! {"
|
||||||
brown fox"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
ˇ
|
ˇ
|
||||||
brown fox"},
|
brown fox"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
|
||||||
ˇ
|
|
||||||
brown fox"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_change_0(cx: &mut gpui::TestAppContext) {
|
async fn test_change_0(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "0"]);
|
||||||
let mut cx = cx.binding(["c", "0"]).mode_after(Mode::Insert);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox"},
|
brown fox"})
|
||||||
indoc! {"
|
.await;
|
||||||
ˇuick
|
cx.assert(indoc! {"
|
||||||
brown fox"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
ˇ
|
ˇ
|
||||||
brown fox"},
|
brown fox"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
|
||||||
ˇ
|
|
||||||
brown fox"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_change_k(cx: &mut gpui::TestAppContext) {
|
async fn test_change_k(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "k"]);
|
||||||
let mut cx = cx.binding(["c", "k"]).mode_after(Mode::Insert);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown ˇfox
|
brown ˇfox
|
||||||
jumps over"},
|
jumps over"})
|
||||||
indoc! {"
|
.await;
|
||||||
ˇ
|
cx.assert(indoc! {"
|
||||||
jumps over"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps ˇover"},
|
jumps ˇover"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
cx.assert_exempted(
|
||||||
ˇ"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over"},
|
jumps over"},
|
||||||
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
cx.assert_exempted(
|
||||||
indoc! {"
|
indoc! {"
|
||||||
ˇ
|
ˇ
|
||||||
brown fox
|
brown fox
|
||||||
jumps over"},
|
jumps over"},
|
||||||
);
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
cx.assert(
|
)
|
||||||
indoc! {"
|
.await;
|
||||||
ˇ
|
|
||||||
brown fox
|
|
||||||
jumps over"},
|
|
||||||
indoc! {"
|
|
||||||
ˇ
|
|
||||||
brown fox
|
|
||||||
jumps over"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_change_j(cx: &mut gpui::TestAppContext) {
|
async fn test_change_j(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "j"]);
|
||||||
let mut cx = cx.binding(["c", "j"]).mode_after(Mode::Insert);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown ˇfox
|
brown ˇfox
|
||||||
jumps over"},
|
jumps over"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
cx.assert_exempted(
|
||||||
ˇ"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps ˇover"},
|
jumps ˇover"},
|
||||||
indoc! {"
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
The quick
|
)
|
||||||
brown fox
|
.await;
|
||||||
ˇ"},
|
cx.assert(indoc! {"
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over"},
|
jumps over"})
|
||||||
indoc! {"
|
.await;
|
||||||
ˇ
|
cx.assert_exempted(
|
||||||
jumps over"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
ˇ"},
|
ˇ"},
|
||||||
indoc! {"
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
The quick
|
)
|
||||||
brown fox
|
.await;
|
||||||
ˇ"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_change_end_of_document(cx: &mut gpui::TestAppContext) {
|
async fn test_change_end_of_document(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx)
|
||||||
let mut cx = cx.binding(["c", "shift-g"]).mode_after(Mode::Insert);
|
.await
|
||||||
cx.assert(
|
.binding(["c", "shift-g"]);
|
||||||
indoc! {"
|
cx.assert(indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brownˇ fox
|
brownˇ fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
cx.assert(indoc! {"
|
||||||
ˇ"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brownˇ fox
|
brownˇ fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
cx.assert_exempted(
|
||||||
ˇ"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
the lˇazy"},
|
the lˇazy"},
|
||||||
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
cx.assert_exempted(
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
ˇ"},
|
ˇ"},
|
||||||
);
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
cx.assert(
|
)
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
|
||||||
brown fox
|
|
||||||
jumps over
|
|
||||||
ˇ"},
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
|
||||||
brown fox
|
|
||||||
jumps over
|
|
||||||
ˇ"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_change_gg(cx: &mut gpui::TestAppContext) {
|
async fn test_change_gg(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx)
|
||||||
let mut cx = cx.binding(["c", "g", "g"]).mode_after(Mode::Insert);
|
.await
|
||||||
cx.assert(
|
.binding(["c", "g", "g"]);
|
||||||
indoc! {"
|
cx.assert(indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brownˇ fox
|
brownˇ fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"})
|
||||||
indoc! {"
|
.await;
|
||||||
ˇ
|
cx.assert(indoc! {"
|
||||||
jumps over
|
|
||||||
the lazy"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
the lˇazy"},
|
the lˇazy"})
|
||||||
"ˇ",
|
.await;
|
||||||
);
|
cx.assert_exempted(
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"},
|
||||||
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
cx.assert_exempted(
|
||||||
indoc! {"
|
indoc! {"
|
||||||
ˇ
|
ˇ
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"},
|
||||||
);
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
cx.assert(
|
)
|
||||||
indoc! {"
|
.await;
|
||||||
ˇ
|
|
||||||
brown fox
|
|
||||||
jumps over
|
|
||||||
the lazy"},
|
|
||||||
indoc! {"
|
|
||||||
ˇ
|
|
||||||
brown fox
|
|
||||||
jumps over
|
|
||||||
the lazy"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
@ -493,14 +392,15 @@ mod test {
|
||||||
async fn test_repeated_cb(cx: &mut gpui::TestAppContext) {
|
async fn test_repeated_cb(cx: &mut gpui::TestAppContext) {
|
||||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||||
|
|
||||||
// Changing back any number of times from the start of the file doesn't
|
cx.add_initial_state_exemptions(
|
||||||
// switch to insert mode in vim. This is weird and painful to implement
|
indoc! {"
|
||||||
cx.add_initial_state_exemption(indoc! {"
|
|
||||||
ˇThe quick brown
|
ˇThe quick brown
|
||||||
|
|
||||||
fox jumps-over
|
fox jumps-over
|
||||||
the lazy dog
|
the lazy dog
|
||||||
"});
|
"},
|
||||||
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
|
);
|
||||||
|
|
||||||
for count in 1..=5 {
|
for count in 1..=5 {
|
||||||
cx.assert_binding_matches_all(
|
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 {
|
mod test {
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
use crate::{state::Mode, test::VimTestContext};
|
use crate::{
|
||||||
|
state::Mode,
|
||||||
|
test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
|
||||||
|
};
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_delete_h(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_h(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "h"]);
|
||||||
let mut cx = cx.binding(["d", "h"]);
|
cx.assert("Teˇst").await;
|
||||||
cx.assert("Teˇst", "Tˇst");
|
cx.assert("Tˇest").await;
|
||||||
cx.assert("Tˇest", "ˇest");
|
cx.assert("ˇTest").await;
|
||||||
cx.assert("ˇTest", "ˇTest");
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test
|
Test
|
||||||
ˇtest"},
|
ˇtest"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test
|
|
||||||
ˇtest"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_delete_l(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_l(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "l"]);
|
||||||
let mut cx = cx.binding(["d", "l"]);
|
cx.assert("ˇTest").await;
|
||||||
cx.assert("ˇTest", "ˇest");
|
cx.assert("Teˇst").await;
|
||||||
cx.assert("Teˇst", "Teˇt");
|
cx.assert("Tesˇt").await;
|
||||||
cx.assert("Tesˇt", "Teˇs");
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Tesˇt
|
Tesˇt
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Teˇs
|
|
||||||
test"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_delete_w(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_w(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "w"]);
|
||||||
let mut cx = cx.binding(["d", "w"]);
|
cx.assert("Teˇst").await;
|
||||||
cx.assert("Teˇst", "Tˇe");
|
cx.assert("Tˇest test").await;
|
||||||
cx.assert("Tˇest test", "Tˇtest");
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test teˇst
|
Test teˇst
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test tˇe
|
cx.assert(indoc! {"
|
||||||
test"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test tesˇt
|
Test tesˇt
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test teˇs
|
cx.assert_exempted(
|
||||||
test"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
Test test
|
Test test
|
||||||
ˇ
|
ˇ
|
||||||
test"},
|
test"},
|
||||||
indoc! {"
|
ExemptionFeatures::DeletionOnEmptyLine,
|
||||||
Test test
|
)
|
||||||
ˇ
|
.await;
|
||||||
test"},
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut cx = cx.binding(["d", "shift-w"]);
|
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]
|
#[gpui::test]
|
||||||
async fn test_delete_e(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_e(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "e"]);
|
||||||
let mut cx = cx.binding(["d", "e"]);
|
cx.assert("Teˇst Test").await;
|
||||||
cx.assert("Teˇst Test", "Teˇ Test");
|
cx.assert("Tˇest test").await;
|
||||||
cx.assert("Tˇest test", "Tˇ test");
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test teˇst
|
Test teˇst
|
||||||
test"},
|
test"})
|
||||||
indoc! {"
|
.await;
|
||||||
Test tˇe
|
cx.assert(indoc! {"
|
||||||
test"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test tesˇt
|
Test tesˇt
|
||||||
test"},
|
test"})
|
||||||
"Test teˇs",
|
.await;
|
||||||
);
|
cx.assert_exempted(
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
Test test
|
Test test
|
||||||
ˇ
|
ˇ
|
||||||
test"},
|
test"},
|
||||||
indoc! {"
|
ExemptionFeatures::DeletionOnEmptyLine,
|
||||||
Test test
|
)
|
||||||
ˇ"},
|
.await;
|
||||||
);
|
|
||||||
|
|
||||||
let mut cx = cx.binding(["d", "shift-e"]);
|
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]
|
#[gpui::test]
|
||||||
async fn test_delete_b(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_b(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "b"]);
|
||||||
let mut cx = cx.binding(["d", "b"]);
|
cx.assert("Teˇst Test").await;
|
||||||
cx.assert("Teˇst Test", "ˇst Test");
|
cx.assert("Test ˇtest").await;
|
||||||
cx.assert("Test ˇtest", "ˇtest");
|
cx.assert("Test1 test2 ˇtest3").await;
|
||||||
cx.assert("Test1 test2 ˇtest3", "Test1 ˇtest3");
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test test
|
Test test
|
||||||
ˇtest"},
|
ˇtest"})
|
||||||
// Trailing whitespace after cursor
|
.await;
|
||||||
indoc! {"
|
cx.assert(indoc! {"
|
||||||
Testˇ
|
|
||||||
test"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
Test test
|
Test test
|
||||||
ˇ
|
ˇ
|
||||||
test"},
|
test"})
|
||||||
// Trailing whitespace after cursor
|
.await;
|
||||||
indoc! {"
|
|
||||||
Testˇ
|
|
||||||
|
|
||||||
test"},
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut cx = cx.binding(["d", "shift-b"]);
|
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]
|
#[gpui::test]
|
||||||
async fn test_delete_end_of_line(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_end_of_line(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "$"]);
|
||||||
let mut cx = cx.binding(["d", "$"]);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox"},
|
brown fox"})
|
||||||
indoc! {"
|
.await;
|
||||||
The ˇq
|
cx.assert(indoc! {"
|
||||||
brown fox"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
ˇ
|
ˇ
|
||||||
brown fox"},
|
brown fox"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
|
||||||
ˇ
|
|
||||||
brown fox"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_delete_0(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_0(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "0"]);
|
||||||
let mut cx = cx.binding(["d", "0"]);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox"},
|
brown fox"})
|
||||||
indoc! {"
|
.await;
|
||||||
ˇuick
|
cx.assert(indoc! {"
|
||||||
brown fox"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
ˇ
|
ˇ
|
||||||
brown fox"},
|
brown fox"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
|
||||||
ˇ
|
|
||||||
brown fox"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_delete_k(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_k(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "k"]);
|
||||||
let mut cx = cx.binding(["d", "k"]);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown ˇfox
|
brown ˇfox
|
||||||
jumps over"},
|
jumps over"})
|
||||||
"jumps ˇover",
|
.await;
|
||||||
);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps ˇover"},
|
jumps ˇover"})
|
||||||
"The quˇick",
|
.await;
|
||||||
);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over"},
|
jumps over"})
|
||||||
indoc! {"
|
.await;
|
||||||
brownˇ fox
|
cx.assert(indoc! {"
|
||||||
jumps over"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
ˇbrown fox
|
ˇbrown fox
|
||||||
jumps over"},
|
jumps over"})
|
||||||
"ˇjumps over",
|
.await;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_delete_j(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_j(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "j"]);
|
||||||
let mut cx = cx.binding(["d", "j"]);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown ˇfox
|
brown ˇfox
|
||||||
jumps over"},
|
jumps over"})
|
||||||
"The quˇick",
|
.await;
|
||||||
);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps ˇover"},
|
jumps ˇover"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
cx.assert(indoc! {"
|
||||||
brown ˇfox"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over"},
|
jumps over"})
|
||||||
"jumpsˇ over",
|
.await;
|
||||||
);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
ˇ"},
|
ˇ"})
|
||||||
indoc! {"
|
.await;
|
||||||
The quick
|
|
||||||
ˇbrown fox"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_delete_end_of_document(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_end_of_document(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx)
|
||||||
let mut cx = cx.binding(["d", "shift-g"]);
|
.await
|
||||||
cx.assert(
|
.binding(["d", "shift-g"]);
|
||||||
indoc! {"
|
cx.assert(indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brownˇ fox
|
brownˇ fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"})
|
||||||
"The qˇuick",
|
.await;
|
||||||
);
|
cx.assert(indoc! {"
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brownˇ fox
|
brownˇ fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"})
|
||||||
"The qˇuick",
|
.await;
|
||||||
);
|
cx.assert_exempted(
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
the lˇazy"},
|
the lˇazy"},
|
||||||
indoc! {"
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
The quick
|
)
|
||||||
brown fox
|
.await;
|
||||||
jumpsˇ over"},
|
cx.assert_exempted(
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
ˇ"},
|
ˇ"},
|
||||||
indoc! {"
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
The quick
|
)
|
||||||
brown fox
|
.await;
|
||||||
ˇjumps over"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_delete_gg(cx: &mut gpui::TestAppContext) {
|
async fn test_delete_gg(cx: &mut gpui::TestAppContext) {
|
||||||
let cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx)
|
||||||
let mut cx = cx.binding(["d", "g", "g"]);
|
.await
|
||||||
cx.assert(
|
.binding(["d", "g", "g"]);
|
||||||
indoc! {"
|
cx.assert(indoc! {"
|
||||||
The quick
|
The quick
|
||||||
brownˇ fox
|
brownˇ fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"})
|
||||||
indoc! {"
|
.await;
|
||||||
jumpsˇ over
|
cx.assert(indoc! {"
|
||||||
the lazy"},
|
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
|
||||||
The quick
|
The quick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
the lˇazy"},
|
the lˇazy"})
|
||||||
"ˇ",
|
.await;
|
||||||
);
|
cx.assert_exempted(
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
The qˇuick
|
The qˇuick
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"},
|
||||||
indoc! {"
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
brownˇ fox
|
)
|
||||||
jumps over
|
.await;
|
||||||
the lazy"},
|
cx.assert_exempted(
|
||||||
);
|
|
||||||
cx.assert(
|
|
||||||
indoc! {"
|
indoc! {"
|
||||||
ˇ
|
ˇ
|
||||||
brown fox
|
brown fox
|
||||||
jumps over
|
jumps over
|
||||||
the lazy"},
|
the lazy"},
|
||||||
indoc! {"
|
ExemptionFeatures::OperatorAbortsOnFailedMotion,
|
||||||
ˇbrown fox
|
)
|
||||||
jumps over
|
.await;
|
||||||
the lazy"},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
|
|
@ -431,7 +431,7 @@ fn surrounding_markers(
|
||||||
mod test {
|
mod test {
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
use crate::test::NeovimBackedTestContext;
|
use crate::test::{ExemptionFeatures, NeovimBackedTestContext};
|
||||||
|
|
||||||
const WORD_LOCATIONS: &'static str = indoc! {"
|
const WORD_LOCATIONS: &'static str = indoc! {"
|
||||||
The quick ˇbrowˇnˇ
|
The quick ˇbrowˇnˇ
|
||||||
|
@ -482,25 +482,46 @@ mod test {
|
||||||
|
|
||||||
cx.assert_binding_matches_all(["v", "i", "w"], WORD_LOCATIONS)
|
cx.assert_binding_matches_all(["v", "i", "w"], WORD_LOCATIONS)
|
||||||
.await;
|
.await;
|
||||||
// Visual text objects are slightly broken when used with non empty selections
|
cx.assert_binding_matches_all_exempted(
|
||||||
// cx.assert_binding_matches_all(["v", "h", "i", "w"], WORD_LOCATIONS)
|
["v", "h", "i", "w"],
|
||||||
// .await;
|
WORD_LOCATIONS,
|
||||||
// cx.assert_binding_matches_all(["v", "l", "i", "w"], WORD_LOCATIONS)
|
ExemptionFeatures::NonEmptyVisualTextObjects,
|
||||||
// .await;
|
)
|
||||||
|
.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)
|
cx.assert_binding_matches_all(["v", "i", "shift-w"], WORD_LOCATIONS)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Visual text objects are slightly broken when used with non empty selections
|
cx.assert_binding_matches_all_exempted(
|
||||||
// cx.assert_binding_matches_all(["v", "i", "h", "shift-w"], WORD_LOCATIONS)
|
["v", "i", "h", "shift-w"],
|
||||||
// .await;
|
WORD_LOCATIONS,
|
||||||
// cx.assert_binding_matches_all(["v", "i", "l", "shift-w"], WORD_LOCATIONS)
|
ExemptionFeatures::NonEmptyVisualTextObjects,
|
||||||
// .await;
|
)
|
||||||
|
.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_exempted(
|
||||||
// cx.assert_binding_matches_all(["v", "a", "w"], WORD_LOCATIONS)
|
["v", "a", "w"],
|
||||||
// .await;
|
WORD_LOCATIONS,
|
||||||
// cx.assert_binding_matches_all(["v", "a", "shift-w"], WORD_LOCATIONS)
|
ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
|
||||||
// .await;
|
)
|
||||||
|
.await;
|
||||||
|
cx.assert_binding_matches_all_exempted(
|
||||||
|
["v", "a", "shift-w"],
|
||||||
|
WORD_LOCATIONS,
|
||||||
|
ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SENTENCE_EXAMPLES: &[&'static str] = &[
|
const SENTENCE_EXAMPLES: &[&'static str] = &[
|
||||||
|
@ -511,17 +532,15 @@ mod test {
|
||||||
the lazy doˇgˇ.ˇ ˇThe quick ˇ
|
the lazy doˇgˇ.ˇ ˇThe quick ˇ
|
||||||
brown fox jumps over
|
brown fox jumps over
|
||||||
"},
|
"},
|
||||||
// Position of the cursor after deletion between lines isn't quite right.
|
indoc! {"
|
||||||
// Deletion in a sentence at the start of a line with whitespace is incorrect.
|
The quick brown fox jumps.
|
||||||
// indoc! {"
|
Over the lazy dog
|
||||||
// The quick brown fox jumps.
|
ˇ
|
||||||
// Over the lazy dog
|
ˇ
|
||||||
// ˇ
|
ˇ fox-jumpˇs over
|
||||||
// ˇ
|
the lazy dog.ˇ
|
||||||
// ˇ fox-jumpˇs over
|
ˇ
|
||||||
// the lazy dog.ˇ
|
"},
|
||||||
// ˇ
|
|
||||||
// "},
|
|
||||||
r#"ˇThe ˇquick brownˇ.)ˇ]ˇ'ˇ" Brown ˇfox jumpsˇ.ˇ "#,
|
r#"ˇThe ˇquick brownˇ.)ˇ]ˇ'ˇ" Brown ˇfox jumpsˇ.ˇ "#,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -530,15 +549,28 @@ mod test {
|
||||||
let mut cx = NeovimBackedTestContext::new(cx)
|
let mut cx = NeovimBackedTestContext::new(cx)
|
||||||
.await
|
.await
|
||||||
.binding(["c", "i", "s"]);
|
.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 {
|
for sentence_example in SENTENCE_EXAMPLES {
|
||||||
cx.assert_all(sentence_example).await;
|
cx.assert_all(sentence_example).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cx = cx.binding(["c", "a", "s"]);
|
let mut cx = cx.binding(["c", "a", "s"]);
|
||||||
// Resulting position is slightly incorrect for unintuitive reasons.
|
cx.add_initial_state_exemptions(
|
||||||
cx.add_initial_state_exemption("The quick brown?ˇ Fox Jumps! Over the lazy.");
|
"The quick brown?ˇ Fox Jumps! Over the lazy.",
|
||||||
// Changing around the sentence at the end of the line doesn't remove whitespace.'
|
ExemptionFeatures::IncorrectLandingPosition,
|
||||||
cx.add_initial_state_exemption("The quick brown.)]\'\" Brown fox jumps.ˇ ");
|
);
|
||||||
|
cx.add_initial_state_exemptions(
|
||||||
|
"The quick brown.)]\'\" Brown fox jumps.ˇ ",
|
||||||
|
ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
|
||||||
|
);
|
||||||
|
|
||||||
for sentence_example in SENTENCE_EXAMPLES {
|
for sentence_example in SENTENCE_EXAMPLES {
|
||||||
cx.assert_all(sentence_example).await;
|
cx.assert_all(sentence_example).await;
|
||||||
|
@ -550,15 +582,29 @@ mod test {
|
||||||
let mut cx = NeovimBackedTestContext::new(cx)
|
let mut cx = NeovimBackedTestContext::new(cx)
|
||||||
.await
|
.await
|
||||||
.binding(["d", "i", "s"]);
|
.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 {
|
for sentence_example in SENTENCE_EXAMPLES {
|
||||||
cx.assert_all(sentence_example).await;
|
cx.assert_all(sentence_example).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cx = cx.binding(["d", "a", "s"]);
|
let mut cx = cx.binding(["d", "a", "s"]);
|
||||||
// Resulting position is slightly incorrect for unintuitive reasons.
|
cx.add_initial_state_exemptions(
|
||||||
cx.add_initial_state_exemption("The quick brown?ˇ Fox Jumps! Over the lazy.");
|
"The quick brown?ˇ Fox Jumps! Over the lazy.",
|
||||||
// Changing around the sentence at the end of the line doesn't remove whitespace.'
|
ExemptionFeatures::IncorrectLandingPosition,
|
||||||
cx.add_initial_state_exemption("The quick brown.)]\'\" Brown fox jumps.ˇ ");
|
);
|
||||||
|
cx.add_initial_state_exemptions(
|
||||||
|
"The quick brown.)]\'\" Brown fox jumps.ˇ ",
|
||||||
|
ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
|
||||||
|
);
|
||||||
|
|
||||||
for sentence_example in SENTENCE_EXAMPLES {
|
for sentence_example in SENTENCE_EXAMPLES {
|
||||||
cx.assert_all(sentence_example).await;
|
cx.assert_all(sentence_example).await;
|
||||||
|
@ -571,14 +617,18 @@ mod test {
|
||||||
.await
|
.await
|
||||||
.binding(["v", "i", "s"]);
|
.binding(["v", "i", "s"]);
|
||||||
for sentence_example in SENTENCE_EXAMPLES {
|
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(["v", "a", "s"]);
|
||||||
// let mut cx = cx.binding(["d", "a", "s"]);
|
for sentence_example in SENTENCE_EXAMPLES {
|
||||||
// for sentence_example in SENTENCE_EXAMPLES {
|
cx.assert_all_exempted(
|
||||||
// cx.assert_all(sentence_example).await;
|
sentence_example,
|
||||||
// }
|
ExemptionFeatures::AroundSentenceStartingBetweenIncludesWrongWhitespace,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test string with "`" for opening surrounders and "'" for closing surrounders
|
// Test string with "`" for opening surrounders and "'" for closing surrounders
|
||||||
|
@ -588,10 +638,9 @@ mod test {
|
||||||
the ˇlazy dˇ'ˇoˇ`ˇg"};
|
the ˇlazy dˇ'ˇoˇ`ˇg"};
|
||||||
|
|
||||||
const SURROUNDING_OBJECTS: &[(char, char)] = &[
|
const SURROUNDING_OBJECTS: &[(char, char)] = &[
|
||||||
// ('\'', '\''), // Quote,
|
('\'', '\''), // Quote
|
||||||
// ('`', '`'), // Back Quote
|
('`', '`'), // Back Quote
|
||||||
// ('"', '"'), // Double Quote
|
('"', '"'), // Double Quote
|
||||||
// ('"', '"'), // Double Quote
|
|
||||||
('(', ')'), // Parentheses
|
('(', ')'), // Parentheses
|
||||||
('[', ']'), // SquareBrackets
|
('[', ']'), // SquareBrackets
|
||||||
('{', '}'), // CurlyBrackets
|
('{', '}'), // CurlyBrackets
|
||||||
|
@ -603,16 +652,23 @@ mod test {
|
||||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||||
|
|
||||||
for (start, end) in SURROUNDING_OBJECTS {
|
for (start, end) in SURROUNDING_OBJECTS {
|
||||||
|
if ((start == &'\'' || start == &'`' || start == &'"')
|
||||||
|
&& !ExemptionFeatures::QuotesSeekForward.supported())
|
||||||
|
|| (start == &'<' && !ExemptionFeatures::AngleBracketsFreezeNeovim.supported())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let marked_string = SURROUNDING_MARKER_STRING
|
let marked_string = SURROUNDING_MARKER_STRING
|
||||||
.replace('`', &start.to_string())
|
.replace('`', &start.to_string())
|
||||||
.replace('\'', &end.to_string());
|
.replace('\'', &end.to_string());
|
||||||
|
|
||||||
// cx.assert_binding_matches_all(["c", "i", &start.to_string()], &marked_string)
|
cx.assert_binding_matches_all(["c", "i", &start.to_string()], &marked_string)
|
||||||
// .await;
|
.await;
|
||||||
cx.assert_binding_matches_all(["c", "i", &end.to_string()], &marked_string)
|
cx.assert_binding_matches_all(["c", "i", &end.to_string()], &marked_string)
|
||||||
.await;
|
.await;
|
||||||
// cx.assert_binding_matches_all(["c", "a", &start.to_string()], &marked_string)
|
cx.assert_binding_matches_all(["c", "a", &start.to_string()], &marked_string)
|
||||||
// .await;
|
.await;
|
||||||
cx.assert_binding_matches_all(["c", "a", &end.to_string()], &marked_string)
|
cx.assert_binding_matches_all(["c", "a", &end.to_string()], &marked_string)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
@ -623,16 +679,22 @@ mod test {
|
||||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||||
|
|
||||||
for (start, end) in SURROUNDING_OBJECTS {
|
for (start, end) in SURROUNDING_OBJECTS {
|
||||||
|
if ((start == &'\'' || start == &'`' || start == &'"')
|
||||||
|
&& !ExemptionFeatures::QuotesSeekForward.supported())
|
||||||
|
|| (start == &'<' && !ExemptionFeatures::AngleBracketsFreezeNeovim.supported())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let marked_string = SURROUNDING_MARKER_STRING
|
let marked_string = SURROUNDING_MARKER_STRING
|
||||||
.replace('`', &start.to_string())
|
.replace('`', &start.to_string())
|
||||||
.replace('\'', &end.to_string());
|
.replace('\'', &end.to_string());
|
||||||
|
|
||||||
// cx.assert_binding_matches_all(["d", "i", &start.to_string()], &marked_string)
|
cx.assert_binding_matches_all(["d", "i", &start.to_string()], &marked_string)
|
||||||
// .await;
|
.await;
|
||||||
cx.assert_binding_matches_all(["d", "i", &end.to_string()], &marked_string)
|
cx.assert_binding_matches_all(["d", "i", &end.to_string()], &marked_string)
|
||||||
.await;
|
.await;
|
||||||
// cx.assert_binding_matches_all(["d", "a", &start.to_string()], &marked_string)
|
cx.assert_binding_matches_all(["d", "a", &start.to_string()], &marked_string)
|
||||||
// .await;
|
.await;
|
||||||
cx.assert_binding_matches_all(["d", "a", &end.to_string()], &marked_string)
|
cx.assert_binding_matches_all(["d", "a", &end.to_string()], &marked_string)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use gpui::ContextHandle;
|
||||||
|
|
||||||
use crate::state::Mode;
|
use crate::state::Mode;
|
||||||
|
|
||||||
use super::NeovimBackedTestContext;
|
use super::{ExemptionFeatures, NeovimBackedTestContext, SUPPORTED_FEATURES};
|
||||||
|
|
||||||
pub struct NeovimBackedBindingTestContext<'a, const COUNT: usize> {
|
pub struct NeovimBackedBindingTestContext<'a, const COUNT: usize> {
|
||||||
cx: NeovimBackedTestContext<'a>,
|
cx: NeovimBackedTestContext<'a>,
|
||||||
|
@ -42,6 +42,20 @@ impl<'a, const COUNT: usize> NeovimBackedBindingTestContext<'a, COUNT> {
|
||||||
.await
|
.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(
|
pub fn assert_manual(
|
||||||
&mut self,
|
&mut self,
|
||||||
initial_state: &str,
|
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)
|
.assert_binding_matches_all(self.keystrokes_under_test, marked_positions)
|
||||||
.await
|
.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> {
|
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 super::{neovim_connection::NeovimConnection, NeovimBackedBindingTestContext, VimTestContext};
|
||||||
use crate::state::Mode;
|
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> {
|
pub struct NeovimBackedTestContext<'a> {
|
||||||
cx: VimTestContext<'a>,
|
cx: VimTestContext<'a>,
|
||||||
// Lookup for exempted assertions. Keyed by the insertion text, and with a value indicating which
|
// 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) {
|
pub fn add_initial_state_exemptions(
|
||||||
let initial_state = initial_state.to_string();
|
&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
|
// None represents all keybindings being exempted for that initial state
|
||||||
self.exemptions.insert(initial_state, None);
|
self.exemptions.insert(marked_text, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn simulate_shared_keystroke(&mut self, keystroke_text: &str) -> ContextHandle {
|
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>(
|
pub fn binding<const COUNT: usize>(
|
||||||
self,
|
self,
|
||||||
keystrokes: [&'static str; COUNT],
|
keystrokes: [&'static str; COUNT],
|
||||||
|
|
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…
Add table
Add a link
Reference in a new issue