vim: Fix edge-case in } when trailing newline is absent
Added .assert_shared_state() to NeovimBackedTestContext – although it's not strictly necessary to show the expected behaviour in the test file (as we can just compare to neovim's JSON recording), it makes it much easier to understand what we're testing.
This commit is contained in:
parent
9ee2707d43
commit
abb58c41db
4 changed files with 94 additions and 48 deletions
|
@ -210,6 +210,10 @@ impl<'a> EditorTestContext<'a> {
|
||||||
self.assert_selections(expected_selections, marked_text.to_string())
|
self.assert_selections(expected_selections, marked_text.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn editor_state(&mut self) -> String {
|
||||||
|
generate_marked_text(self.buffer_text().as_str(), &self.editor_selections(), true)
|
||||||
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn assert_editor_background_highlights<Tag: 'static>(&mut self, marked_text: &str) {
|
pub fn assert_editor_background_highlights<Tag: 'static>(&mut self, marked_text: &str) {
|
||||||
let expected_ranges = self.ranges(marked_text);
|
let expected_ranges = self.ranges(marked_text);
|
||||||
|
@ -248,14 +252,8 @@ impl<'a> EditorTestContext<'a> {
|
||||||
self.assert_selections(expected_selections, expected_marked_text)
|
self.assert_selections(expected_selections, expected_marked_text)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
fn editor_selections(&self) -> Vec<Range<usize>> {
|
||||||
fn assert_selections(
|
self.editor
|
||||||
&mut self,
|
|
||||||
expected_selections: Vec<Range<usize>>,
|
|
||||||
expected_marked_text: String,
|
|
||||||
) {
|
|
||||||
let actual_selections = self
|
|
||||||
.editor
|
|
||||||
.read_with(self.cx, |editor, cx| editor.selections.all::<usize>(cx))
|
.read_with(self.cx, |editor, cx| editor.selections.all::<usize>(cx))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
|
@ -265,12 +263,22 @@ impl<'a> EditorTestContext<'a> {
|
||||||
s.start..s.end
|
s.start..s.end
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn assert_selections(
|
||||||
|
&mut self,
|
||||||
|
expected_selections: Vec<Range<usize>>,
|
||||||
|
expected_marked_text: String,
|
||||||
|
) {
|
||||||
|
let actual_selections = self.editor_selections();
|
||||||
let actual_marked_text =
|
let actual_marked_text =
|
||||||
generate_marked_text(&self.buffer_text(), &actual_selections, true);
|
generate_marked_text(&self.buffer_text(), &actual_selections, true);
|
||||||
if expected_selections != actual_selections {
|
if expected_selections != actual_selections {
|
||||||
panic!(
|
panic!(
|
||||||
indoc! {"
|
indoc! {"
|
||||||
|
|
||||||
{}Editor has unexpected selections.
|
{}Editor has unexpected selections.
|
||||||
|
|
||||||
Expected selections:
|
Expected selections:
|
||||||
|
|
|
@ -255,7 +255,7 @@ impl Motion {
|
||||||
SelectionGoal::None,
|
SelectionGoal::None,
|
||||||
),
|
),
|
||||||
EndOfParagraph => (
|
EndOfParagraph => (
|
||||||
movement::end_of_paragraph(map, point, times),
|
map.clip_at_line_end(movement::end_of_paragraph(map, point, times)),
|
||||||
SelectionGoal::None,
|
SelectionGoal::None,
|
||||||
),
|
),
|
||||||
CurrentLine => (end_of_line(map, point), SelectionGoal::None),
|
CurrentLine => (end_of_line(map, point), SelectionGoal::None),
|
||||||
|
@ -618,12 +618,12 @@ fn next_line_start(map: &DisplaySnapshot, point: DisplayPoint, times: usize) ->
|
||||||
|
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use crate::{state::Mode, test::VimTestContext};
|
use crate::test::NeovimBackedTestContext;
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_start_end_of_paragraph(cx: &mut gpui::TestAppContext) {
|
async fn test_start_end_of_paragraph(cx: &mut gpui::TestAppContext) {
|
||||||
let mut cx = VimTestContext::new(cx, true).await;
|
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||||
|
|
||||||
let initial_state = indoc! {r"ˇabc
|
let initial_state = indoc! {r"ˇabc
|
||||||
def
|
def
|
||||||
|
@ -637,10 +637,9 @@ mod test {
|
||||||
final"};
|
final"};
|
||||||
|
|
||||||
// goes down once
|
// goes down once
|
||||||
cx.set_state(initial_state, Mode::Normal);
|
cx.set_shared_state(initial_state).await;
|
||||||
cx.simulate_keystrokes(["}"]);
|
cx.simulate_shared_keystrokes(["}"]).await;
|
||||||
cx.assert_state(
|
cx.assert_shared_state(indoc! {r"abc
|
||||||
indoc! {r"abc
|
|
||||||
def
|
def
|
||||||
ˇ
|
ˇ
|
||||||
paragraph
|
paragraph
|
||||||
|
@ -649,18 +648,16 @@ mod test {
|
||||||
|
|
||||||
|
|
||||||
third and
|
third and
|
||||||
final"},
|
final"})
|
||||||
Mode::Normal,
|
.await;
|
||||||
);
|
|
||||||
|
|
||||||
// goes up once
|
// goes up once
|
||||||
cx.simulate_keystrokes(["{"]);
|
cx.simulate_shared_keystrokes(["{"]).await;
|
||||||
cx.assert_state(initial_state, Mode::Normal);
|
cx.assert_shared_state(initial_state).await;
|
||||||
|
|
||||||
// goes down twice
|
// goes down twice
|
||||||
cx.simulate_keystrokes(["2", "}"]);
|
cx.simulate_shared_keystrokes(["2", "}"]).await;
|
||||||
cx.assert_state(
|
cx.assert_shared_state(indoc! {r"abc
|
||||||
indoc! {r"abc
|
|
||||||
def
|
def
|
||||||
|
|
||||||
paragraph
|
paragraph
|
||||||
|
@ -669,14 +666,12 @@ mod test {
|
||||||
|
|
||||||
|
|
||||||
third and
|
third and
|
||||||
final"},
|
final"})
|
||||||
Mode::Normal,
|
.await;
|
||||||
);
|
|
||||||
|
|
||||||
// goes down over multiple blanks
|
// goes down over multiple blanks
|
||||||
cx.simulate_keystrokes(["}"]);
|
cx.simulate_shared_keystrokes(["}"]).await;
|
||||||
cx.assert_state(
|
cx.assert_shared_state(indoc! {r"abc
|
||||||
indoc! {r"abc
|
|
||||||
def
|
def
|
||||||
|
|
||||||
paragraph
|
paragraph
|
||||||
|
@ -685,14 +680,12 @@ mod test {
|
||||||
|
|
||||||
|
|
||||||
third and
|
third and
|
||||||
finalˇ"},
|
finaˇl"})
|
||||||
Mode::Normal,
|
.await;
|
||||||
);
|
|
||||||
|
|
||||||
// goes up twice
|
// goes up twice
|
||||||
cx.simulate_keystrokes(["2", "{"]);
|
cx.simulate_shared_keystrokes(["2", "{"]).await;
|
||||||
cx.assert_state(
|
cx.assert_shared_state(indoc! {r"abc
|
||||||
indoc! {r"abc
|
|
||||||
def
|
def
|
||||||
ˇ
|
ˇ
|
||||||
paragraph
|
paragraph
|
||||||
|
@ -701,8 +694,7 @@ mod test {
|
||||||
|
|
||||||
|
|
||||||
third and
|
third and
|
||||||
final"},
|
final"})
|
||||||
Mode::Normal,
|
.await
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use std::ops::{Deref, DerefMut};
|
use indoc::indoc;
|
||||||
|
use std::ops::{Deref, DerefMut, Range};
|
||||||
|
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use gpui::ContextHandle;
|
use gpui::ContextHandle;
|
||||||
use language::OffsetRangeExt;
|
use language::OffsetRangeExt;
|
||||||
use util::test::marked_text_offsets;
|
use util::test::{generate_marked_text, 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;
|
||||||
|
@ -112,6 +113,43 @@ impl<'a> NeovimBackedTestContext<'a> {
|
||||||
context_handle
|
context_handle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn assert_shared_state(&mut self, marked_text: &str) {
|
||||||
|
let neovim = self.neovim_state().await;
|
||||||
|
if neovim != marked_text {
|
||||||
|
panic!(
|
||||||
|
indoc! {"Test is incorrect (currently expected != neovim state)
|
||||||
|
|
||||||
|
# currently expected:
|
||||||
|
{}
|
||||||
|
# neovim state:
|
||||||
|
{}
|
||||||
|
# zed state:
|
||||||
|
{}"},
|
||||||
|
marked_text,
|
||||||
|
neovim,
|
||||||
|
self.editor_state(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
self.assert_editor_state(marked_text)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn neovim_state(&mut self) -> String {
|
||||||
|
generate_marked_text(
|
||||||
|
self.neovim.text().await.as_str(),
|
||||||
|
&vec![self.neovim_selection().await],
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn neovim_selection(&mut self) -> Range<usize> {
|
||||||
|
let mut neovim_selection = self.neovim.selection().await;
|
||||||
|
// Zed selections adjust themselves to make the end point visually make sense
|
||||||
|
if neovim_selection.start > neovim_selection.end {
|
||||||
|
neovim_selection.start.column += 1;
|
||||||
|
}
|
||||||
|
neovim_selection.to_offset(&self.buffer_snapshot())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn assert_state_matches(&mut self) {
|
pub async fn assert_state_matches(&mut self) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.neovim.text().await,
|
self.neovim.text().await,
|
||||||
|
@ -120,13 +158,8 @@ impl<'a> NeovimBackedTestContext<'a> {
|
||||||
self.assertion_context()
|
self.assertion_context()
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut neovim_selection = self.neovim.selection().await;
|
let selections = vec![self.neovim_selection().await];
|
||||||
// Zed selections adjust themselves to make the end point visually make sense
|
self.assert_editor_selections(selections);
|
||||||
if neovim_selection.start > neovim_selection.end {
|
|
||||||
neovim_selection.start.column += 1;
|
|
||||||
}
|
|
||||||
let neovim_selection = neovim_selection.to_offset(&self.buffer_snapshot());
|
|
||||||
self.assert_editor_selections(vec![neovim_selection]);
|
|
||||||
|
|
||||||
if let Some(neovim_mode) = self.neovim.mode().await {
|
if let Some(neovim_mode) = self.neovim.mode().await {
|
||||||
assert_eq!(neovim_mode, self.mode(), "{}", self.assertion_context(),);
|
assert_eq!(neovim_mode, self.mode(), "{}", self.assertion_context(),);
|
||||||
|
|
13
crates/vim/test_data/test_start_end_of_paragraph.json
Normal file
13
crates/vim/test_data/test_start_end_of_paragraph.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{"Put":{"state":"ˇabc\ndef\n\nparagraph\nthe second\n\n\n\nthird and\nfinal"}}
|
||||||
|
{"Key":"}"}
|
||||||
|
{"Get":{"state":"abc\ndef\nˇ\nparagraph\nthe second\n\n\n\nthird and\nfinal","mode":"Normal"}}
|
||||||
|
{"Key":"{"}
|
||||||
|
{"Get":{"state":"ˇabc\ndef\n\nparagraph\nthe second\n\n\n\nthird and\nfinal","mode":"Normal"}}
|
||||||
|
{"Key":"2"}
|
||||||
|
{"Key":"}"}
|
||||||
|
{"Get":{"state":"abc\ndef\n\nparagraph\nthe second\nˇ\n\n\nthird and\nfinal","mode":"Normal"}}
|
||||||
|
{"Key":"}"}
|
||||||
|
{"Get":{"state":"abc\ndef\n\nparagraph\nthe second\n\n\n\nthird and\nfinaˇl","mode":"Normal"}}
|
||||||
|
{"Key":"2"}
|
||||||
|
{"Key":"{"}
|
||||||
|
{"Get":{"state":"abc\ndef\nˇ\nparagraph\nthe second\n\n\n\nthird and\nfinal","mode":"Normal"}}
|
Loading…
Add table
Add a link
Reference in a new issue