vim: { } to navigate by paragraph (#2668)

As part of this I added `assert_shared_state()` to the
NeovimBackedTestContext so that it is more like a drop-in replacement
for the VimTestContext.

The remaining part of zed-industries/community#682 is adding bracket
matching to plain text. It looks like the current logic requires there
to be a tree sitter language for the language in order to support
bracket matching. I didn't fix this in this PR because I was unsure
whether to try and work around that, or to try and add a plain text tree
sitter language.

Release Notes:

- vim: support `{` and `}` for paragraph motion
([#470](https://github.com/zed-industries/community/issues/470)).
- vim: fix `%` at the end of the line
([#682](https://github.com/zed-industries/community/issues/682)).
This commit is contained in:
Conrad Irwin 2023-07-07 14:59:06 -06:00 committed by GitHub
commit 460bf93866
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 377 additions and 60 deletions

View file

@ -1,9 +1,10 @@
use std::ops::{Deref, DerefMut};
use indoc::indoc;
use std::ops::{Deref, DerefMut, Range};
use collections::{HashMap, HashSet};
use gpui::ContextHandle;
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 crate::state::Mode;
@ -112,6 +113,43 @@ impl<'a> NeovimBackedTestContext<'a> {
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) {
assert_eq!(
self.neovim.text().await,
@ -120,13 +158,8 @@ impl<'a> NeovimBackedTestContext<'a> {
self.assertion_context()
);
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;
}
let neovim_selection = neovim_selection.to_offset(&self.buffer_snapshot());
self.assert_editor_selections(vec![neovim_selection]);
let selections = vec![self.neovim_selection().await];
self.assert_editor_selections(selections);
if let Some(neovim_mode) = self.neovim.mode().await {
assert_eq!(neovim_mode, self.mode(), "{}", self.assertion_context(),);

View file

@ -167,15 +167,25 @@ impl NeovimConnection {
.await
.expect("Could not get neovim window");
if !selection.is_empty() {
panic!("Setting neovim state with non empty selection not yet supported");
}
let cursor = selection.start;
nvim_window
.set_cursor((cursor.row as i64 + 1, cursor.column as i64))
.await
.expect("Could not set nvim cursor position");
if !selection.is_empty() {
self.nvim
.input("v")
.await
.expect("could not enter visual mode");
let cursor = selection.end;
nvim_window
.set_cursor((cursor.row as i64 + 1, cursor.column as i64))
.await
.expect("Could not set nvim cursor position");
}
if let Some(NeovimData::Get { mode, state }) = self.data.back() {
if *mode == Some(Mode::Normal) && *state == marked_text {
return;