From d1805d8ada4f402a90073e2949b3fb96d3633d84 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 11 Dec 2023 13:57:46 -0700 Subject: [PATCH 1/3] First round of vim tests --- .../editor2/src/test/editor_test_context.rs | 4 + crates/gpui2/src/app.rs | 26 +- crates/gpui2/src/key_dispatch.rs | 8 +- crates/gpui2/src/keymap/binding.rs | 2 +- crates/gpui2/src/keymap/matcher.rs | 13 +- crates/gpui2/src/platform/test/platform.rs | 2 +- crates/gpui2/src/window.rs | 41 +- crates/picker2/src/picker2.rs | 1 + crates/search2/src/search.rs | 1 + crates/vim2/src/mode_indicator.rs | 50 +- crates/vim2/src/normal.rs | 1 - crates/vim2/src/test.rs | 1513 ++++++++--------- .../src/test/neovim_backed_test_context.rs | 35 +- crates/vim2/src/test/neovim_connection.rs | 26 +- crates/vim2/src/test/vim_test_context.rs | 29 +- crates/vim2/src/vim.rs | 70 +- 16 files changed, 938 insertions(+), 884 deletions(-) diff --git a/crates/editor2/src/test/editor_test_context.rs b/crates/editor2/src/test/editor_test_context.rs index 1d497b4837..0b6fb69d71 100644 --- a/crates/editor2/src/test/editor_test_context.rs +++ b/crates/editor2/src/test/editor_test_context.rs @@ -170,6 +170,10 @@ impl<'a> EditorTestContext<'a> { keystrokes_under_test_handle } + pub fn run_until_parked(&mut self) { + self.cx.background_executor.run_until_parked(); + } + pub fn ranges(&mut self, marked_text: &str) -> Vec> { let (unmarked_text, ranges) = marked_text_ranges(marked_text, false); assert_eq!(self.buffer_text(), unmarked_text); diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 842ac0b704..1d369e0286 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -19,10 +19,10 @@ use crate::{ current_platform, image_cache::ImageCache, init_app_menus, Action, ActionRegistry, Any, AnyView, AnyWindowHandle, AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context, DispatchPhase, DisplayId, Entity, EventEmitter, FocusEvent, FocusHandle, FocusId, - ForegroundExecutor, KeyBinding, Keymap, LayoutId, Menu, PathPromptOptions, Pixels, Platform, - PlatformDisplay, Point, Render, SharedString, SubscriberSet, Subscription, SvgRenderer, Task, - TextStyle, TextStyleRefinement, TextSystem, View, ViewContext, Window, WindowContext, - WindowHandle, WindowId, + ForegroundExecutor, KeyBinding, Keymap, Keystroke, LayoutId, Menu, PathPromptOptions, Pixels, + Platform, PlatformDisplay, Point, Render, SharedString, SubscriberSet, Subscription, + SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, ViewContext, Window, + WindowContext, WindowHandle, WindowId, }; use anyhow::{anyhow, Result}; use collections::{HashMap, HashSet, VecDeque}; @@ -171,6 +171,7 @@ impl App { pub(crate) type FrameCallback = Box; type Handler = Box bool + 'static>; type Listener = Box bool + 'static>; +type KeystrokeObserver = Box; type QuitHandler = Box LocalBoxFuture<'static, ()> + 'static>; type ReleaseListener = Box; type NewViewListener = Box; @@ -212,6 +213,7 @@ pub struct AppContext { pub(crate) observers: SubscriberSet, // TypeId is the type of the event that the listener callback expects pub(crate) event_listeners: SubscriberSet, + pub(crate) keystroke_observers: SubscriberSet<(), KeystrokeObserver>, pub(crate) release_listeners: SubscriberSet, pub(crate) global_observers: SubscriberSet, pub(crate) quit_observers: SubscriberSet<(), QuitHandler>, @@ -272,6 +274,7 @@ impl AppContext { observers: SubscriberSet::new(), event_listeners: SubscriberSet::new(), release_listeners: SubscriberSet::new(), + keystroke_observers: SubscriberSet::new(), global_observers: SubscriberSet::new(), quit_observers: SubscriberSet::new(), layout_id_buffer: Default::default(), @@ -955,6 +958,15 @@ impl AppContext { subscription } + pub fn observe_keystrokes( + &mut self, + f: impl FnMut(&KeystrokeEvent, &mut WindowContext) + 'static, + ) -> Subscription { + let (subscription, activate) = self.keystroke_observers.insert((), Box::new(f)); + activate(); + subscription + } + pub(crate) fn push_text_style(&mut self, text_style: TextStyleRefinement) { self.text_style_stack.push(text_style); } @@ -1281,3 +1293,9 @@ pub(crate) struct AnyTooltip { pub view: AnyView, pub cursor_offset: Point, } + +#[derive(Debug)] +pub struct KeystrokeEvent { + pub keystroke: Keystroke, + pub action: Option>, +} diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index 1e08c11a52..6c8c19aa65 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -208,7 +208,7 @@ impl DispatchTree { &mut self, keystroke: &Keystroke, context: &[KeyContext], - ) -> Option> { + ) -> Vec> { if !self.keystroke_matchers.contains_key(context) { let keystroke_contexts = context.iter().cloned().collect(); self.keystroke_matchers.insert( @@ -218,15 +218,15 @@ impl DispatchTree { } let keystroke_matcher = self.keystroke_matchers.get_mut(context).unwrap(); - if let KeyMatch::Some(action) = keystroke_matcher.match_keystroke(keystroke, context) { + if let KeyMatch::Some(actions) = keystroke_matcher.match_keystroke(keystroke, context) { // Clear all pending keystrokes when an action has been found. for keystroke_matcher in self.keystroke_matchers.values_mut() { keystroke_matcher.clear_pending(); } - Some(action) + actions } else { - None + vec![] } } diff --git a/crates/gpui2/src/keymap/binding.rs b/crates/gpui2/src/keymap/binding.rs index e55d664610..4b677b3071 100644 --- a/crates/gpui2/src/keymap/binding.rs +++ b/crates/gpui2/src/keymap/binding.rs @@ -59,7 +59,7 @@ impl KeyBinding { { // If the binding is completed, push it onto the matches list if self.keystrokes.as_ref().len() == pending_keystrokes.len() { - KeyMatch::Some(self.action.boxed_clone()) + KeyMatch::Some(vec![self.action.boxed_clone()]) } else { KeyMatch::Pending } diff --git a/crates/gpui2/src/keymap/matcher.rs b/crates/gpui2/src/keymap/matcher.rs index a842913aef..7d4e408e93 100644 --- a/crates/gpui2/src/keymap/matcher.rs +++ b/crates/gpui2/src/keymap/matcher.rs @@ -54,14 +54,14 @@ impl KeystrokeMatcher { } let mut pending_key = None; + let mut found_actions = Vec::new(); for binding in keymap.bindings().iter().rev() { for candidate in keystroke.match_candidates() { self.pending_keystrokes.push(candidate.clone()); match binding.match_keystrokes(&self.pending_keystrokes, context_stack) { - KeyMatch::Some(action) => { - self.pending_keystrokes.clear(); - return KeyMatch::Some(action); + KeyMatch::Some(mut actions) => { + found_actions.append(&mut actions); } KeyMatch::Pending => { pending_key.get_or_insert(candidate); @@ -72,6 +72,11 @@ impl KeystrokeMatcher { } } + if !found_actions.is_empty() { + self.pending_keystrokes.clear(); + return KeyMatch::Some(found_actions); + } + if let Some(pending_key) = pending_key { self.pending_keystrokes.push(pending_key); } @@ -101,7 +106,7 @@ impl KeystrokeMatcher { pub enum KeyMatch { None, Pending, - Some(Box), + Some(Vec>), } impl KeyMatch { diff --git a/crates/gpui2/src/platform/test/platform.rs b/crates/gpui2/src/platform/test/platform.rs index 876120b626..7b1178e3a3 100644 --- a/crates/gpui2/src/platform/test/platform.rs +++ b/crates/gpui2/src/platform/test/platform.rs @@ -128,7 +128,7 @@ impl Platform for TestPlatform { } fn active_window(&self) -> Option { - unimplemented!() + self.active_window.lock().clone() } fn open_window( diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index f98d9820c2..f1a5ef5abd 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -3,9 +3,9 @@ use crate::{ AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, - ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, LayoutId, Model, - ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseMoveEvent, MouseUpEvent, Path, - Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point, + ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeystrokeEvent, LayoutId, + Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseMoveEvent, MouseUpEvent, + Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, SubscriberSet, Subscription, Surface, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext, @@ -478,6 +478,29 @@ impl<'a> WindowContext<'a> { }) } + pub(crate) fn dispatch_keystroke_observers( + &mut self, + event: &dyn Any, + action: Option>, + ) { + let Some(key_down_event) = event.downcast_ref::() else { + return; + }; + + self.keystroke_observers + .clone() + .retain(&(), move |callback| { + (callback)( + &KeystrokeEvent { + keystroke: key_down_event.keystroke.clone(), + action: action.as_ref().map(|action| action.boxed_clone()), + }, + self, + ); + true + }); + } + /// Schedules the given function to be run at the end of the current effect cycle, allowing entities /// that are currently on the stack to be returned to the app. pub fn defer(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) { @@ -1406,14 +1429,12 @@ impl<'a> WindowContext<'a> { let node = self.window.rendered_frame.dispatch_tree.node(*node_id); if node.context.is_some() { if let Some(key_down_event) = event.downcast_ref::() { - if let Some(found) = self + let mut new_actions = self .window .rendered_frame .dispatch_tree - .dispatch_key(&key_down_event.keystroke, &context_stack) - { - actions.push(found.boxed_clone()) - } + .dispatch_key(&key_down_event.keystroke, &context_stack); + actions.append(&mut new_actions); } context_stack.pop(); @@ -1421,11 +1442,13 @@ impl<'a> WindowContext<'a> { } for action in actions { - self.dispatch_action_on_node(node_id, action); + self.dispatch_action_on_node(node_id, action.boxed_clone()); if !self.propagate_event { + self.dispatch_keystroke_observers(event, Some(action)); return; } } + self.dispatch_keystroke_observers(event, None); } fn dispatch_action_on_node(&mut self, node_id: DispatchNodeId, action: Box) { diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 54df321cb1..f0f3f70e57 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -114,6 +114,7 @@ impl Picker { } fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { + dbg!("picker cancel"); self.delegate.dismissed(cx); } diff --git a/crates/search2/src/search.rs b/crates/search2/src/search.rs index 202893d52d..1118f197a5 100644 --- a/crates/search2/src/search.rs +++ b/crates/search2/src/search.rs @@ -17,6 +17,7 @@ pub mod project_search; pub(crate) mod search_bar; pub fn init(cx: &mut AppContext) { + menu::init(); buffer_search::init(cx); project_search::init(cx); } diff --git a/crates/vim2/src/mode_indicator.rs b/crates/vim2/src/mode_indicator.rs index 38f0bd6c96..8c831ba797 100644 --- a/crates/vim2/src/mode_indicator.rs +++ b/crates/vim2/src/mode_indicator.rs @@ -1,42 +1,40 @@ -use gpui::{div, AnyElement, Element, IntoElement, Render, ViewContext}; -use settings::{Settings, SettingsStore}; +use gpui::{div, AnyElement, Element, IntoElement, Render, Subscription, ViewContext}; +use settings::SettingsStore; use workspace::{item::ItemHandle, ui::Label, StatusItemView}; -use crate::{state::Mode, Vim, VimModeSetting}; +use crate::{state::Mode, Vim}; pub struct ModeIndicator { pub mode: Option, - // _subscription: Subscription, + _subscriptions: Vec, } impl ModeIndicator { pub fn new(cx: &mut ViewContext) -> Self { - cx.observe_global::(|this, cx| this.set_mode(Vim::read(cx).state().mode, cx)) - .detach(); + let _subscriptions = vec![ + cx.observe_global::(|this, cx| this.update_mode(cx)), + cx.observe_global::(|this, cx| this.update_mode(cx)), + ]; - cx.observe_global::(move |mode_indicator, cx| { - if VimModeSetting::get_global(cx).0 { - mode_indicator.mode = cx - .has_global::() - .then(|| cx.global::().state().mode); - } else { - mode_indicator.mode.take(); - } - }) - .detach(); + let mut this = Self { + mode: None, + _subscriptions, + }; + this.update_mode(cx); + this + } + fn update_mode(&mut self, cx: &mut ViewContext) { // Vim doesn't exist in some tests - let mode = cx - .has_global::() - .then(|| { - let vim = cx.global::(); - vim.enabled.then(|| vim.state().mode) - }) - .flatten(); + if !cx.has_global::() { + return; + } - Self { - mode, - // _subscription, + let vim = Vim::read(cx); + if vim.enabled { + self.mode = Some(vim.state().mode); + } else { + self.mode = None; } } diff --git a/crates/vim2/src/normal.rs b/crates/vim2/src/normal.rs index d717d651d8..375675317d 100644 --- a/crates/vim2/src/normal.rs +++ b/crates/vim2/src/normal.rs @@ -203,7 +203,6 @@ fn insert_after(_: &mut Workspace, _: &InsertAfter, cx: &mut ViewContext) { - dbg!("insert before!"); Vim::update(cx, |vim, cx| { vim.start_recording(cx); vim.switch_mode(Mode::Insert, false, cx); diff --git a/crates/vim2/src/test.rs b/crates/vim2/src/test.rs index 2c80452268..b233dcff83 100644 --- a/crates/vim2/src/test.rs +++ b/crates/vim2/src/test.rs @@ -1,759 +1,754 @@ -// mod neovim_backed_binding_test_context; -// mod neovim_backed_test_context; -// mod neovim_connection; -// mod vim_test_context; - -// use std::sync::Arc; - -// use command_palette::CommandPalette; -// use editor::DisplayPoint; -// pub use neovim_backed_binding_test_context::*; -// pub use neovim_backed_test_context::*; -// pub use vim_test_context::*; - -// use indoc::indoc; -// use search::BufferSearchBar; - -// use crate::{state::Mode, ModeIndicator}; - -// #[gpui::test] -// async fn test_initially_disabled(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, false).await; -// cx.simulate_keystrokes(["h", "j", "k", "l"]); -// cx.assert_editor_state("hjklˇ"); -// } - -// #[gpui::test] -// async fn test_neovim(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; - -// cx.simulate_shared_keystroke("i").await; -// cx.assert_state_matches().await; -// cx.simulate_shared_keystrokes([ -// "shift-T", "e", "s", "t", " ", "t", "e", "s", "t", "escape", "0", "d", "w", -// ]) -// .await; -// cx.assert_state_matches().await; -// cx.assert_editor_state("ˇtest"); -// } - -// #[gpui::test] -// async fn test_toggle_through_settings(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// cx.simulate_keystroke("i"); -// assert_eq!(cx.mode(), Mode::Insert); - -// // Editor acts as though vim is disabled -// cx.disable_vim(); -// cx.simulate_keystrokes(["h", "j", "k", "l"]); -// cx.assert_editor_state("hjklˇ"); - -// // Selections aren't changed if editor is blurred but vim-mode is still disabled. -// cx.set_state("«hjklˇ»", Mode::Normal); -// cx.assert_editor_state("«hjklˇ»"); -// cx.update_editor(|_, cx| cx.blur()); -// cx.assert_editor_state("«hjklˇ»"); -// cx.update_editor(|_, cx| cx.focus_self()); -// cx.assert_editor_state("«hjklˇ»"); - -// // Enabling dynamically sets vim mode again and restores normal mode -// cx.enable_vim(); -// assert_eq!(cx.mode(), Mode::Normal); -// cx.simulate_keystrokes(["h", "h", "h", "l"]); -// assert_eq!(cx.buffer_text(), "hjkl".to_owned()); -// cx.assert_editor_state("hˇjkl"); -// cx.simulate_keystrokes(["i", "T", "e", "s", "t"]); -// cx.assert_editor_state("hTestˇjkl"); - -// // Disabling and enabling resets to normal mode -// assert_eq!(cx.mode(), Mode::Insert); -// cx.disable_vim(); -// cx.enable_vim(); -// assert_eq!(cx.mode(), Mode::Normal); -// } - -// #[gpui::test] -// async fn test_buffer_search(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// cx.set_state( -// indoc! {" -// The quick brown -// fox juˇmps over -// the lazy dog"}, -// Mode::Normal, -// ); -// cx.simulate_keystroke("/"); - -// let search_bar = cx.workspace(|workspace, cx| { -// workspace -// .active_pane() -// .read(cx) -// .toolbar() -// .read(cx) -// .item_of_type::() -// .expect("Buffer search bar should be deployed") -// }); - -// cx.update_view(search_bar, |bar, cx| { -// assert_eq!(bar.query(cx), ""); -// }) -// } - -// #[gpui::test] -// async fn test_count_down(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// cx.set_state(indoc! {"aˇa\nbb\ncc\ndd\nee"}, Mode::Normal); -// cx.simulate_keystrokes(["2", "down"]); -// cx.assert_editor_state("aa\nbb\ncˇc\ndd\nee"); -// cx.simulate_keystrokes(["9", "down"]); -// cx.assert_editor_state("aa\nbb\ncc\ndd\neˇe"); -// } - -// #[gpui::test] -// async fn test_end_of_document_710(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// // goes to end by default -// cx.set_state(indoc! {"aˇa\nbb\ncc"}, Mode::Normal); -// cx.simulate_keystrokes(["shift-g"]); -// cx.assert_editor_state("aa\nbb\ncˇc"); - -// // can go to line 1 (https://github.com/zed-industries/community/issues/710) -// cx.simulate_keystrokes(["1", "shift-g"]); -// cx.assert_editor_state("aˇa\nbb\ncc"); -// } - -// #[gpui::test] -// async fn test_indent_outdent(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// // works in normal mode -// cx.set_state(indoc! {"aa\nbˇb\ncc"}, Mode::Normal); -// cx.simulate_keystrokes([">", ">"]); -// cx.assert_editor_state("aa\n bˇb\ncc"); -// cx.simulate_keystrokes(["<", "<"]); -// cx.assert_editor_state("aa\nbˇb\ncc"); - -// // works in visuial mode -// cx.simulate_keystrokes(["shift-v", "down", ">"]); -// cx.assert_editor_state("aa\n b«b\n ccˇ»"); -// } - -// #[gpui::test] -// async fn test_escape_command_palette(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// cx.set_state("aˇbc\n", Mode::Normal); -// cx.simulate_keystrokes(["i", "cmd-shift-p"]); - -// assert!(cx.workspace(|workspace, _| workspace.modal::().is_some())); -// cx.simulate_keystroke("escape"); -// assert!(!cx.workspace(|workspace, _| workspace.modal::().is_some())); -// cx.assert_state("aˇbc\n", Mode::Insert); -// } - -// #[gpui::test] -// async fn test_escape_cancels(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// cx.set_state("aˇbˇc", Mode::Normal); -// cx.simulate_keystrokes(["escape"]); - -// cx.assert_state("aˇbc", Mode::Normal); -// } - -// #[gpui::test] -// async fn test_selection_on_search(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// cx.set_state(indoc! {"aa\nbˇb\ncc\ncc\ncc\n"}, Mode::Normal); -// cx.simulate_keystrokes(["/", "c", "c"]); - -// let search_bar = cx.workspace(|workspace, cx| { -// workspace -// .active_pane() -// .read(cx) -// .toolbar() -// .read(cx) -// .item_of_type::() -// .expect("Buffer search bar should be deployed") -// }); - -// search_bar.read_with(cx.cx, |bar, cx| { -// assert_eq!(bar.query(cx), "cc"); -// }); - -// cx.update_editor(|editor, cx| { -// let highlights = editor.all_text_background_highlights(cx); -// assert_eq!(3, highlights.len()); -// assert_eq!( -// DisplayPoint::new(2, 0)..DisplayPoint::new(2, 2), -// highlights[0].0 -// ) -// }); -// cx.simulate_keystrokes(["enter"]); - -// cx.assert_state(indoc! {"aa\nbb\nˇcc\ncc\ncc\n"}, Mode::Normal); -// cx.simulate_keystrokes(["n"]); -// cx.assert_state(indoc! {"aa\nbb\ncc\nˇcc\ncc\n"}, Mode::Normal); -// cx.simulate_keystrokes(["shift-n"]); -// cx.assert_state(indoc! {"aa\nbb\nˇcc\ncc\ncc\n"}, Mode::Normal); -// } - -// #[gpui::test] -// async fn test_status_indicator( -// cx: &mut gpui::TestAppContext, -// deterministic: Arc, -// ) { -// let mut cx = VimTestContext::new(cx, true).await; -// deterministic.run_until_parked(); - -// let mode_indicator = cx.workspace(|workspace, cx| { -// let status_bar = workspace.status_bar().read(cx); -// let mode_indicator = status_bar.item_of_type::(); -// assert!(mode_indicator.is_some()); -// mode_indicator.unwrap() -// }); - -// assert_eq!( -// cx.workspace(|_, cx| mode_indicator.read(cx).mode), -// Some(Mode::Normal) -// ); - -// // shows the correct mode -// cx.simulate_keystrokes(["i"]); -// deterministic.run_until_parked(); -// assert_eq!( -// cx.workspace(|_, cx| mode_indicator.read(cx).mode), -// Some(Mode::Insert) -// ); - -// // shows even in search -// cx.simulate_keystrokes(["escape", "v", "/"]); -// deterministic.run_until_parked(); -// assert_eq!( -// cx.workspace(|_, cx| mode_indicator.read(cx).mode), -// Some(Mode::Visual) -// ); - -// // hides if vim mode is disabled -// cx.disable_vim(); -// deterministic.run_until_parked(); -// cx.workspace(|workspace, cx| { -// let status_bar = workspace.status_bar().read(cx); -// let mode_indicator = status_bar.item_of_type::().unwrap(); -// assert!(mode_indicator.read(cx).mode.is_none()); -// }); - -// cx.enable_vim(); -// deterministic.run_until_parked(); -// cx.workspace(|workspace, cx| { -// let status_bar = workspace.status_bar().read(cx); -// let mode_indicator = status_bar.item_of_type::().unwrap(); -// assert!(mode_indicator.read(cx).mode.is_some()); -// }); -// } - -// #[gpui::test] -// async fn test_word_characters(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new_typescript(cx).await; -// cx.set_state( -// indoc! { " -// class A { -// #ˇgoop = 99; -// $ˇgoop () { return this.#gˇoop }; -// }; -// console.log(new A().$gooˇp()) -// "}, -// Mode::Normal, -// ); -// cx.simulate_keystrokes(["v", "i", "w"]); -// cx.assert_state( -// indoc! {" -// class A { -// «#goopˇ» = 99; -// «$goopˇ» () { return this.«#goopˇ» }; -// }; -// console.log(new A().«$goopˇ»()) -// "}, -// Mode::Visual, -// ) -// } - -// #[gpui::test] -// async fn test_join_lines(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; - -// cx.set_shared_state(indoc! {" -// ˇone -// two -// three -// four -// five -// six -// "}) -// .await; -// cx.simulate_shared_keystrokes(["shift-j"]).await; -// cx.assert_shared_state(indoc! {" -// oneˇ two -// three -// four -// five -// six -// "}) -// .await; -// cx.simulate_shared_keystrokes(["3", "shift-j"]).await; -// cx.assert_shared_state(indoc! {" -// one two threeˇ four -// five -// six -// "}) -// .await; - -// cx.set_shared_state(indoc! {" -// ˇone -// two -// three -// four -// five -// six -// "}) -// .await; -// cx.simulate_shared_keystrokes(["j", "v", "3", "j", "shift-j"]) -// .await; -// cx.assert_shared_state(indoc! {" -// one -// two three fourˇ five -// six -// "}) -// .await; -// } - -// #[gpui::test] -// async fn test_wrapped_lines(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; - -// cx.set_shared_wrap(12).await; -// // tests line wrap as follows: -// // 1: twelve char -// // twelve char -// // 2: twelve char -// cx.set_shared_state(indoc! { " -// tˇwelve char twelve char -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["j"]).await; -// cx.assert_shared_state(indoc! { " -// twelve char twelve char -// tˇwelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["k"]).await; -// cx.assert_shared_state(indoc! { " -// tˇwelve char twelve char -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["g", "j"]).await; -// cx.assert_shared_state(indoc! { " -// twelve char tˇwelve char -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["g", "j"]).await; -// cx.assert_shared_state(indoc! { " -// twelve char twelve char -// tˇwelve char -// "}) -// .await; - -// cx.simulate_shared_keystrokes(["g", "k"]).await; -// cx.assert_shared_state(indoc! { " -// twelve char tˇwelve char -// twelve char -// "}) -// .await; - -// cx.simulate_shared_keystrokes(["g", "^"]).await; -// cx.assert_shared_state(indoc! { " -// twelve char ˇtwelve char -// twelve char -// "}) -// .await; - -// cx.simulate_shared_keystrokes(["^"]).await; -// cx.assert_shared_state(indoc! { " -// ˇtwelve char twelve char -// twelve char -// "}) -// .await; - -// cx.simulate_shared_keystrokes(["g", "$"]).await; -// cx.assert_shared_state(indoc! { " -// twelve charˇ twelve char -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["$"]).await; -// cx.assert_shared_state(indoc! { " -// twelve char twelve chaˇr -// twelve char -// "}) -// .await; - -// cx.set_shared_state(indoc! { " -// tˇwelve char twelve char -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["enter"]).await; -// cx.assert_shared_state(indoc! { " -// twelve char twelve char -// ˇtwelve char -// "}) -// .await; - -// cx.set_shared_state(indoc! { " -// twelve char -// tˇwelve char twelve char -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["o", "o", "escape"]).await; -// cx.assert_shared_state(indoc! { " -// twelve char -// twelve char twelve char -// ˇo -// twelve char -// "}) -// .await; - -// cx.set_shared_state(indoc! { " -// twelve char -// tˇwelve char twelve char -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["shift-a", "a", "escape"]) -// .await; -// cx.assert_shared_state(indoc! { " -// twelve char -// twelve char twelve charˇa -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["shift-i", "i", "escape"]) -// .await; -// cx.assert_shared_state(indoc! { " -// twelve char -// ˇitwelve char twelve chara -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["shift-d"]).await; -// cx.assert_shared_state(indoc! { " -// twelve char -// ˇ -// twelve char -// "}) -// .await; - -// cx.set_shared_state(indoc! { " -// twelve char -// twelve char tˇwelve char -// twelve char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["shift-o", "o", "escape"]) -// .await; -// cx.assert_shared_state(indoc! { " -// twelve char -// ˇo -// twelve char twelve char -// twelve char -// "}) -// .await; - -// // line wraps as: -// // fourteen ch -// // ar -// // fourteen ch -// // ar -// cx.set_shared_state(indoc! { " -// fourteen chaˇr -// fourteen char -// "}) -// .await; - -// cx.simulate_shared_keystrokes(["d", "i", "w"]).await; -// cx.assert_shared_state(indoc! {" -// fourteenˇ• -// fourteen char -// "}) -// .await; -// cx.simulate_shared_keystrokes(["j", "shift-f", "e", "f", "r"]) -// .await; -// cx.assert_shared_state(indoc! {" -// fourteen• -// fourteen chaˇr -// "}) -// .await; -// } - -// #[gpui::test] -// async fn test_folds(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; -// cx.set_neovim_option("foldmethod=manual").await; - -// cx.set_shared_state(indoc! { " -// fn boop() { -// ˇbarp() -// bazp() -// } -// "}) -// .await; -// cx.simulate_shared_keystrokes(["shift-v", "j", "z", "f"]) -// .await; - -// // visual display is now: -// // fn boop () { -// // [FOLDED] -// // } - -// // TODO: this should not be needed but currently zf does not -// // return to normal mode. -// cx.simulate_shared_keystrokes(["escape"]).await; - -// // skip over fold downward -// cx.simulate_shared_keystrokes(["g", "g"]).await; -// cx.assert_shared_state(indoc! { " -// ˇfn boop() { -// barp() -// bazp() -// } -// "}) -// .await; - -// cx.simulate_shared_keystrokes(["j", "j"]).await; -// cx.assert_shared_state(indoc! { " -// fn boop() { -// barp() -// bazp() -// ˇ} -// "}) -// .await; - -// // skip over fold upward -// cx.simulate_shared_keystrokes(["2", "k"]).await; -// cx.assert_shared_state(indoc! { " -// ˇfn boop() { -// barp() -// bazp() -// } -// "}) -// .await; - -// // yank the fold -// cx.simulate_shared_keystrokes(["down", "y", "y"]).await; -// cx.assert_shared_clipboard(" barp()\n bazp()\n").await; - -// // re-open -// cx.simulate_shared_keystrokes(["z", "o"]).await; -// cx.assert_shared_state(indoc! { " -// fn boop() { -// ˇ barp() -// bazp() -// } -// "}) -// .await; -// } - -// #[gpui::test] -// async fn test_folds_panic(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; -// cx.set_neovim_option("foldmethod=manual").await; - -// cx.set_shared_state(indoc! { " -// fn boop() { -// ˇbarp() -// bazp() -// } -// "}) -// .await; -// cx.simulate_shared_keystrokes(["shift-v", "j", "z", "f"]) -// .await; -// cx.simulate_shared_keystrokes(["escape"]).await; -// cx.simulate_shared_keystrokes(["g", "g"]).await; -// cx.simulate_shared_keystrokes(["5", "d", "j"]).await; -// cx.assert_shared_state(indoc! { "ˇ"}).await; -// } - -// #[gpui::test] -// async fn test_clear_counts(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; - -// cx.set_shared_state(indoc! {" -// The quick brown -// fox juˇmps over -// the lazy dog"}) -// .await; - -// cx.simulate_shared_keystrokes(["4", "escape", "3", "d", "l"]) -// .await; -// cx.assert_shared_state(indoc! {" -// The quick brown -// fox juˇ over -// the lazy dog"}) -// .await; -// } - -// #[gpui::test] -// async fn test_zero(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; - -// cx.set_shared_state(indoc! {" -// The quˇick brown -// fox jumps over -// the lazy dog"}) -// .await; - -// cx.simulate_shared_keystrokes(["0"]).await; -// cx.assert_shared_state(indoc! {" -// ˇThe quick brown -// fox jumps over -// the lazy dog"}) -// .await; - -// cx.simulate_shared_keystrokes(["1", "0", "l"]).await; -// cx.assert_shared_state(indoc! {" -// The quick ˇbrown -// fox jumps over -// the lazy dog"}) -// .await; -// } - -// #[gpui::test] -// async fn test_selection_goal(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; - -// cx.set_shared_state(indoc! {" -// ;;ˇ; -// Lorem Ipsum"}) -// .await; - -// cx.simulate_shared_keystrokes(["a", "down", "up", ";", "down", "up"]) -// .await; -// cx.assert_shared_state(indoc! {" -// ;;;;ˇ -// Lorem Ipsum"}) -// .await; -// } - -// #[gpui::test] -// async fn test_wrapped_motions(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; - -// cx.set_shared_wrap(12).await; - -// cx.set_shared_state(indoc! {" -// aaˇaa -// 😃😃" -// }) -// .await; -// cx.simulate_shared_keystrokes(["j"]).await; -// cx.assert_shared_state(indoc! {" -// aaaa -// 😃ˇ😃" -// }) -// .await; - -// cx.set_shared_state(indoc! {" -// 123456789012aaˇaa -// 123456789012😃😃" -// }) -// .await; -// cx.simulate_shared_keystrokes(["j"]).await; -// cx.assert_shared_state(indoc! {" -// 123456789012aaaa -// 123456789012😃ˇ😃" -// }) -// .await; - -// cx.set_shared_state(indoc! {" -// 123456789012aaˇaa -// 123456789012😃😃" -// }) -// .await; -// cx.simulate_shared_keystrokes(["j"]).await; -// cx.assert_shared_state(indoc! {" -// 123456789012aaaa -// 123456789012😃ˇ😃" -// }) -// .await; - -// cx.set_shared_state(indoc! {" -// 123456789012aaaaˇaaaaaaaa123456789012 -// wow -// 123456789012😃😃😃😃😃😃123456789012" -// }) -// .await; -// cx.simulate_shared_keystrokes(["j", "j"]).await; -// cx.assert_shared_state(indoc! {" -// 123456789012aaaaaaaaaaaa123456789012 -// wow -// 123456789012😃😃ˇ😃😃😃😃123456789012" -// }) -// .await; -// } - -// #[gpui::test] -// async fn test_paragraphs_dont_wrap(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; - -// cx.set_shared_state(indoc! {" -// one -// ˇ -// two"}) -// .await; - -// cx.simulate_shared_keystrokes(["}", "}"]).await; -// cx.assert_shared_state(indoc! {" -// one - -// twˇo"}) -// .await; - -// cx.simulate_shared_keystrokes(["{", "{", "{"]).await; -// cx.assert_shared_state(indoc! {" -// ˇone - -// two"}) -// .await; -// } - -// #[gpui::test] -// async fn test_select_all_issue_2170(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// cx.set_state( -// indoc! {" -// defmodule Test do -// def test(a, ˇ[_, _] = b), do: IO.puts('hi') -// end -// "}, -// Mode::Normal, -// ); -// cx.simulate_keystrokes(["g", "a"]); -// cx.assert_state( -// indoc! {" -// defmodule Test do -// def test(a, «[ˇ»_, _] = b), do: IO.puts('hi') -// end -// "}, -// Mode::Visual, -// ); -// } +mod neovim_backed_binding_test_context; +mod neovim_backed_test_context; +mod neovim_connection; +mod vim_test_context; + +use std::sync::Arc; + +use command_palette::CommandPalette; +use editor::DisplayPoint; +pub use neovim_backed_binding_test_context::*; +pub use neovim_backed_test_context::*; +pub use vim_test_context::*; + +use indoc::indoc; +use search::BufferSearchBar; + +use crate::{state::Mode, ModeIndicator}; + +#[gpui::test] +async fn test_initially_disabled(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, false).await; + cx.simulate_keystrokes(["h", "j", "k", "l"]); + cx.assert_editor_state("hjklˇ"); +} + +#[gpui::test] +async fn test_neovim(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.simulate_shared_keystroke("i").await; + cx.assert_state_matches().await; + cx.simulate_shared_keystrokes([ + "shift-T", "e", "s", "t", " ", "t", "e", "s", "t", "escape", "0", "d", "w", + ]) + .await; + cx.assert_state_matches().await; + cx.assert_editor_state("ˇtest"); +} + +#[gpui::test] +async fn test_toggle_through_settings(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.simulate_keystroke("i"); + assert_eq!(cx.mode(), Mode::Insert); + + // Editor acts as though vim is disabled + cx.disable_vim(); + cx.simulate_keystrokes(["h", "j", "k", "l"]); + cx.assert_editor_state("hjklˇ"); + + // Selections aren't changed if editor is blurred but vim-mode is still disabled. + cx.set_state("«hjklˇ»", Mode::Normal); + cx.assert_editor_state("«hjklˇ»"); + cx.update_editor(|_, cx| cx.blur()); + cx.assert_editor_state("«hjklˇ»"); + cx.update_editor(|_, cx| cx.focus_self()); + cx.assert_editor_state("«hjklˇ»"); + + // Enabling dynamically sets vim mode again and restores normal mode + cx.enable_vim(); + assert_eq!(cx.mode(), Mode::Normal); + cx.simulate_keystrokes(["h", "h", "h", "l"]); + assert_eq!(cx.buffer_text(), "hjkl".to_owned()); + cx.assert_editor_state("hˇjkl"); + cx.simulate_keystrokes(["i", "T", "e", "s", "t"]); + cx.assert_editor_state("hTestˇjkl"); + + // Disabling and enabling resets to normal mode + assert_eq!(cx.mode(), Mode::Insert); + cx.disable_vim(); + cx.enable_vim(); + assert_eq!(cx.mode(), Mode::Normal); +} + +#[gpui::test] +async fn test_buffer_search(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state( + indoc! {" + The quick brown + fox juˇmps over + the lazy dog"}, + Mode::Normal, + ); + cx.simulate_keystroke("/"); + + let search_bar = cx.workspace(|workspace, cx| { + workspace + .active_pane() + .read(cx) + .toolbar() + .read(cx) + .item_of_type::() + .expect("Buffer search bar should be deployed") + }); + + cx.update_view(search_bar, |bar, cx| { + assert_eq!(bar.query(cx), ""); + }) +} + +#[gpui::test] +async fn test_count_down(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state(indoc! {"aˇa\nbb\ncc\ndd\nee"}, Mode::Normal); + cx.simulate_keystrokes(["2", "down"]); + cx.assert_editor_state("aa\nbb\ncˇc\ndd\nee"); + cx.simulate_keystrokes(["9", "down"]); + cx.assert_editor_state("aa\nbb\ncc\ndd\neˇe"); +} + +#[gpui::test] +async fn test_end_of_document_710(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + // goes to end by default + cx.set_state(indoc! {"aˇa\nbb\ncc"}, Mode::Normal); + cx.simulate_keystrokes(["shift-g"]); + cx.assert_editor_state("aa\nbb\ncˇc"); + + // can go to line 1 (https://github.com/zed-industries/community/issues/710) + cx.simulate_keystrokes(["1", "shift-g"]); + cx.assert_editor_state("aˇa\nbb\ncc"); +} + +#[gpui::test] +async fn test_indent_outdent(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + // works in normal mode + cx.set_state(indoc! {"aa\nbˇb\ncc"}, Mode::Normal); + cx.simulate_keystrokes([">", ">"]); + cx.assert_editor_state("aa\n bˇb\ncc"); + cx.simulate_keystrokes(["<", "<"]); + cx.assert_editor_state("aa\nbˇb\ncc"); + + // works in visuial mode + cx.simulate_keystrokes(["shift-v", "down", ">"]); + cx.assert_editor_state("aa\n b«b\n ccˇ»"); +} + +#[gpui::test] +async fn test_escape_command_palette(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state("aˇbc\n", Mode::Normal); + cx.simulate_keystrokes(["i", "cmd-shift-p"]); + + assert!(cx.workspace(|workspace, cx| workspace.active_modal::(cx).is_some())); + cx.simulate_keystroke("escape"); + cx.run_until_parked(); + assert!(!cx.workspace(|workspace, cx| workspace.active_modal::(cx).is_some())); + cx.assert_state("aˇbc\n", Mode::Insert); +} + +#[gpui::test] +async fn test_escape_cancels(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state("aˇbˇc", Mode::Normal); + cx.simulate_keystrokes(["escape"]); + + cx.assert_state("aˇbc", Mode::Normal); +} + +#[gpui::test] +async fn test_selection_on_search(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state(indoc! {"aa\nbˇb\ncc\ncc\ncc\n"}, Mode::Normal); + cx.simulate_keystrokes(["/", "c", "c"]); + + let search_bar = cx.workspace(|workspace, cx| { + workspace + .active_pane() + .read(cx) + .toolbar() + .read(cx) + .item_of_type::() + .expect("Buffer search bar should be deployed") + }); + + cx.update_view(search_bar, |bar, cx| { + assert_eq!(bar.query(cx), "cc"); + }); + + cx.update_editor(|editor, cx| { + let highlights = editor.all_text_background_highlights(cx); + assert_eq!(3, highlights.len()); + assert_eq!( + DisplayPoint::new(2, 0)..DisplayPoint::new(2, 2), + highlights[0].0 + ) + }); + cx.simulate_keystrokes(["enter"]); + + cx.assert_state(indoc! {"aa\nbb\nˇcc\ncc\ncc\n"}, Mode::Normal); + cx.simulate_keystrokes(["n"]); + cx.assert_state(indoc! {"aa\nbb\ncc\nˇcc\ncc\n"}, Mode::Normal); + cx.simulate_keystrokes(["shift-n"]); + cx.assert_state(indoc! {"aa\nbb\nˇcc\ncc\ncc\n"}, Mode::Normal); +} + +#[gpui::test] +async fn test_status_indicator(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + let mode_indicator = cx.workspace(|workspace, cx| { + let status_bar = workspace.status_bar().read(cx); + let mode_indicator = status_bar.item_of_type::(); + assert!(mode_indicator.is_some()); + mode_indicator.unwrap() + }); + + assert_eq!( + cx.workspace(|_, cx| mode_indicator.read(cx).mode), + Some(Mode::Normal) + ); + + // shows the correct mode + cx.simulate_keystrokes(["i"]); + assert_eq!( + cx.workspace(|_, cx| mode_indicator.read(cx).mode), + Some(Mode::Insert) + ); + + // shows even in search + cx.simulate_keystrokes(["escape", "v", "/"]); + assert_eq!( + cx.workspace(|_, cx| mode_indicator.read(cx).mode), + Some(Mode::Visual) + ); + + // hides if vim mode is disabled + cx.disable_vim(); + cx.run_until_parked(); + cx.workspace(|workspace, cx| { + let status_bar = workspace.status_bar().read(cx); + let mode_indicator = status_bar.item_of_type::().unwrap(); + assert!(mode_indicator.read(cx).mode.is_none()); + }); + + cx.enable_vim(); + cx.run_until_parked(); + cx.workspace(|workspace, cx| { + let status_bar = workspace.status_bar().read(cx); + let mode_indicator = status_bar.item_of_type::().unwrap(); + assert!(mode_indicator.read(cx).mode.is_some()); + }); +} + +#[gpui::test] +async fn test_word_characters(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new_typescript(cx).await; + cx.set_state( + indoc! { " + class A { + #ˇgoop = 99; + $ˇgoop () { return this.#gˇoop }; + }; + console.log(new A().$gooˇp()) + "}, + Mode::Normal, + ); + cx.simulate_keystrokes(["v", "i", "w"]); + cx.assert_state( + indoc! {" + class A { + «#goopˇ» = 99; + «$goopˇ» () { return this.«#goopˇ» }; + }; + console.log(new A().«$goopˇ»()) + "}, + Mode::Visual, + ) +} + +#[gpui::test] +async fn test_join_lines(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state(indoc! {" + ˇone + two + three + four + five + six + "}) + .await; + cx.simulate_shared_keystrokes(["shift-j"]).await; + cx.assert_shared_state(indoc! {" + oneˇ two + three + four + five + six + "}) + .await; + cx.simulate_shared_keystrokes(["3", "shift-j"]).await; + cx.assert_shared_state(indoc! {" + one two threeˇ four + five + six + "}) + .await; + + cx.set_shared_state(indoc! {" + ˇone + two + three + four + five + six + "}) + .await; + cx.simulate_shared_keystrokes(["j", "v", "3", "j", "shift-j"]) + .await; + cx.assert_shared_state(indoc! {" + one + two three fourˇ five + six + "}) + .await; +} + +#[gpui::test] +async fn test_wrapped_lines(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_wrap(12).await; + // tests line wrap as follows: + // 1: twelve char + // twelve char + // 2: twelve char + cx.set_shared_state(indoc! { " + tˇwelve char twelve char + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["j"]).await; + cx.assert_shared_state(indoc! { " + twelve char twelve char + tˇwelve char + "}) + .await; + cx.simulate_shared_keystrokes(["k"]).await; + cx.assert_shared_state(indoc! { " + tˇwelve char twelve char + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["g", "j"]).await; + cx.assert_shared_state(indoc! { " + twelve char tˇwelve char + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["g", "j"]).await; + cx.assert_shared_state(indoc! { " + twelve char twelve char + tˇwelve char + "}) + .await; + + cx.simulate_shared_keystrokes(["g", "k"]).await; + cx.assert_shared_state(indoc! { " + twelve char tˇwelve char + twelve char + "}) + .await; + + cx.simulate_shared_keystrokes(["g", "^"]).await; + cx.assert_shared_state(indoc! { " + twelve char ˇtwelve char + twelve char + "}) + .await; + + cx.simulate_shared_keystrokes(["^"]).await; + cx.assert_shared_state(indoc! { " + ˇtwelve char twelve char + twelve char + "}) + .await; + + cx.simulate_shared_keystrokes(["g", "$"]).await; + cx.assert_shared_state(indoc! { " + twelve charˇ twelve char + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["$"]).await; + cx.assert_shared_state(indoc! { " + twelve char twelve chaˇr + twelve char + "}) + .await; + + cx.set_shared_state(indoc! { " + tˇwelve char twelve char + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["enter"]).await; + cx.assert_shared_state(indoc! { " + twelve char twelve char + ˇtwelve char + "}) + .await; + + cx.set_shared_state(indoc! { " + twelve char + tˇwelve char twelve char + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["o", "o", "escape"]).await; + cx.assert_shared_state(indoc! { " + twelve char + twelve char twelve char + ˇo + twelve char + "}) + .await; + + cx.set_shared_state(indoc! { " + twelve char + tˇwelve char twelve char + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["shift-a", "a", "escape"]) + .await; + cx.assert_shared_state(indoc! { " + twelve char + twelve char twelve charˇa + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["shift-i", "i", "escape"]) + .await; + cx.assert_shared_state(indoc! { " + twelve char + ˇitwelve char twelve chara + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["shift-d"]).await; + cx.assert_shared_state(indoc! { " + twelve char + ˇ + twelve char + "}) + .await; + + cx.set_shared_state(indoc! { " + twelve char + twelve char tˇwelve char + twelve char + "}) + .await; + cx.simulate_shared_keystrokes(["shift-o", "o", "escape"]) + .await; + cx.assert_shared_state(indoc! { " + twelve char + ˇo + twelve char twelve char + twelve char + "}) + .await; + + // line wraps as: + // fourteen ch + // ar + // fourteen ch + // ar + cx.set_shared_state(indoc! { " + fourteen chaˇr + fourteen char + "}) + .await; + + cx.simulate_shared_keystrokes(["d", "i", "w"]).await; + cx.assert_shared_state(indoc! {" + fourteenˇ• + fourteen char + "}) + .await; + cx.simulate_shared_keystrokes(["j", "shift-f", "e", "f", "r"]) + .await; + cx.assert_shared_state(indoc! {" + fourteen• + fourteen chaˇr + "}) + .await; +} + +#[gpui::test] +async fn test_folds(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + cx.set_neovim_option("foldmethod=manual").await; + + cx.set_shared_state(indoc! { " + fn boop() { + ˇbarp() + bazp() + } + "}) + .await; + cx.simulate_shared_keystrokes(["shift-v", "j", "z", "f"]) + .await; + + // visual display is now: + // fn boop () { + // [FOLDED] + // } + + // TODO: this should not be needed but currently zf does not + // return to normal mode. + cx.simulate_shared_keystrokes(["escape"]).await; + + // skip over fold downward + cx.simulate_shared_keystrokes(["g", "g"]).await; + cx.assert_shared_state(indoc! { " + ˇfn boop() { + barp() + bazp() + } + "}) + .await; + + cx.simulate_shared_keystrokes(["j", "j"]).await; + cx.assert_shared_state(indoc! { " + fn boop() { + barp() + bazp() + ˇ} + "}) + .await; + + // skip over fold upward + cx.simulate_shared_keystrokes(["2", "k"]).await; + cx.assert_shared_state(indoc! { " + ˇfn boop() { + barp() + bazp() + } + "}) + .await; + + // yank the fold + cx.simulate_shared_keystrokes(["down", "y", "y"]).await; + cx.assert_shared_clipboard(" barp()\n bazp()\n").await; + + // re-open + cx.simulate_shared_keystrokes(["z", "o"]).await; + cx.assert_shared_state(indoc! { " + fn boop() { + ˇ barp() + bazp() + } + "}) + .await; +} + +#[gpui::test] +async fn test_folds_panic(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + cx.set_neovim_option("foldmethod=manual").await; + + cx.set_shared_state(indoc! { " + fn boop() { + ˇbarp() + bazp() + } + "}) + .await; + cx.simulate_shared_keystrokes(["shift-v", "j", "z", "f"]) + .await; + cx.simulate_shared_keystrokes(["escape"]).await; + cx.simulate_shared_keystrokes(["g", "g"]).await; + cx.simulate_shared_keystrokes(["5", "d", "j"]).await; + cx.assert_shared_state(indoc! { "ˇ"}).await; +} + +#[gpui::test] +async fn test_clear_counts(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state(indoc! {" + The quick brown + fox juˇmps over + the lazy dog"}) + .await; + + cx.simulate_shared_keystrokes(["4", "escape", "3", "d", "l"]) + .await; + cx.assert_shared_state(indoc! {" + The quick brown + fox juˇ over + the lazy dog"}) + .await; +} + +#[gpui::test] +async fn test_zero(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state(indoc! {" + The quˇick brown + fox jumps over + the lazy dog"}) + .await; + + cx.simulate_shared_keystrokes(["0"]).await; + cx.assert_shared_state(indoc! {" + ˇThe quick brown + fox jumps over + the lazy dog"}) + .await; + + cx.simulate_shared_keystrokes(["1", "0", "l"]).await; + cx.assert_shared_state(indoc! {" + The quick ˇbrown + fox jumps over + the lazy dog"}) + .await; +} + +#[gpui::test] +async fn test_selection_goal(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state(indoc! {" + ;;ˇ; + Lorem Ipsum"}) + .await; + + cx.simulate_shared_keystrokes(["a", "down", "up", ";", "down", "up"]) + .await; + cx.assert_shared_state(indoc! {" + ;;;;ˇ + Lorem Ipsum"}) + .await; +} + +#[gpui::test] +async fn test_wrapped_motions(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_wrap(12).await; + + cx.set_shared_state(indoc! {" + aaˇaa + 😃😃" + }) + .await; + cx.simulate_shared_keystrokes(["j"]).await; + cx.assert_shared_state(indoc! {" + aaaa + 😃ˇ😃" + }) + .await; + + cx.set_shared_state(indoc! {" + 123456789012aaˇaa + 123456789012😃😃" + }) + .await; + cx.simulate_shared_keystrokes(["j"]).await; + cx.assert_shared_state(indoc! {" + 123456789012aaaa + 123456789012😃ˇ😃" + }) + .await; + + cx.set_shared_state(indoc! {" + 123456789012aaˇaa + 123456789012😃😃" + }) + .await; + cx.simulate_shared_keystrokes(["j"]).await; + cx.assert_shared_state(indoc! {" + 123456789012aaaa + 123456789012😃ˇ😃" + }) + .await; + + cx.set_shared_state(indoc! {" + 123456789012aaaaˇaaaaaaaa123456789012 + wow + 123456789012😃😃😃😃😃😃123456789012" + }) + .await; + cx.simulate_shared_keystrokes(["j", "j"]).await; + cx.assert_shared_state(indoc! {" + 123456789012aaaaaaaaaaaa123456789012 + wow + 123456789012😃😃ˇ😃😃😃😃123456789012" + }) + .await; +} + +#[gpui::test] +async fn test_paragraphs_dont_wrap(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state(indoc! {" + one + ˇ + two"}) + .await; + + cx.simulate_shared_keystrokes(["}", "}"]).await; + cx.assert_shared_state(indoc! {" + one + + twˇo"}) + .await; + + cx.simulate_shared_keystrokes(["{", "{", "{"]).await; + cx.assert_shared_state(indoc! {" + ˇone + + two"}) + .await; +} + +#[gpui::test] +async fn test_select_all_issue_2170(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state( + indoc! {" + defmodule Test do + def test(a, ˇ[_, _] = b), do: IO.puts('hi') + end + "}, + Mode::Normal, + ); + cx.simulate_keystrokes(["g", "a"]); + cx.assert_state( + indoc! {" + defmodule Test do + def test(a, «[ˇ»_, _] = b), do: IO.puts('hi') + end + "}, + Mode::Visual, + ); +} diff --git a/crates/vim2/src/test/neovim_backed_test_context.rs b/crates/vim2/src/test/neovim_backed_test_context.rs index c4a7c52056..eb20b99b02 100644 --- a/crates/vim2/src/test/neovim_backed_test_context.rs +++ b/crates/vim2/src/test/neovim_backed_test_context.rs @@ -1,4 +1,4 @@ -use editor::scroll::VERTICAL_SCROLL_MARGIN; +use editor::{scroll::VERTICAL_SCROLL_MARGIN, test::editor_test_context::ContextHandle}; use indoc::indoc; use settings::SettingsStore; use std::{ @@ -7,7 +7,6 @@ use std::{ }; use collections::{HashMap, HashSet}; -use gpui::{geometry::vector::vec2f, ContextHandle}; use language::language_settings::{AllLanguageSettings, SoftWrap}; use util::test::marked_text_offsets; @@ -151,19 +150,20 @@ impl<'a> NeovimBackedTestContext<'a> { }) } - pub async fn set_scroll_height(&mut self, rows: u32) { - // match Zed's scrolling behavior - self.neovim - .set_option(&format!("scrolloff={}", VERTICAL_SCROLL_MARGIN)) - .await; - // +2 to account for the vim command UI at the bottom. - self.neovim.set_option(&format!("lines={}", rows + 2)).await; - let window = self.window; - let line_height = - self.editor(|editor, cx| editor.style().text.line_height(cx.font_cache())); + // todo!() + // pub async fn set_scroll_height(&mut self, rows: u32) { + // // match Zed's scrolling behavior + // self.neovim + // .set_option(&format!("scrolloff={}", VERTICAL_SCROLL_MARGIN)) + // .await; + // // +2 to account for the vim command UI at the bottom. + // self.neovim.set_option(&format!("lines={}", rows + 2)).await; + // let window = self.window; + // let line_height = + // self.editor(|editor, cx| editor.style().text.line_height(cx.font_cache())); - window.simulate_resize(vec2f(1000., (rows as f32) * line_height), &mut self.cx); - } + // window.simulate_resize(vec2f(1000., (rows as f32) * line_height), &mut self.cx); + // } pub async fn set_neovim_option(&mut self, option: &str) { self.neovim.set_option(option).await; @@ -211,12 +211,7 @@ impl<'a> NeovimBackedTestContext<'a> { pub async fn assert_shared_clipboard(&mut self, text: &str) { let neovim = self.neovim.read_register('"').await; - let editor = self - .platform() - .read_from_clipboard() - .unwrap() - .text() - .clone(); + let editor = self.read_from_clipboard().unwrap().text().clone(); if text == neovim && text == editor { return; diff --git a/crates/vim2/src/test/neovim_connection.rs b/crates/vim2/src/test/neovim_connection.rs index 16c718b857..363f6d43e3 100644 --- a/crates/vim2/src/test/neovim_connection.rs +++ b/crates/vim2/src/test/neovim_connection.rs @@ -10,7 +10,7 @@ use async_compat::Compat; #[cfg(feature = "neovim")] use async_trait::async_trait; #[cfg(feature = "neovim")] -use gpui::keymap_matcher::Keystroke; +use gpui::Keystroke; #[cfg(feature = "neovim")] use language::Point; @@ -116,16 +116,24 @@ impl NeovimConnection { keystroke.key = "lt".to_string() } - let special = keystroke.shift - || keystroke.ctrl - || keystroke.alt - || keystroke.cmd + let special = keystroke.modifiers.shift + || keystroke.modifiers.control + || keystroke.modifiers.alt + || keystroke.modifiers.command || keystroke.key.len() > 1; let start = if special { "<" } else { "" }; - let shift = if keystroke.shift { "S-" } else { "" }; - let ctrl = if keystroke.ctrl { "C-" } else { "" }; - let alt = if keystroke.alt { "M-" } else { "" }; - let cmd = if keystroke.cmd { "D-" } else { "" }; + let shift = if keystroke.modifiers.shift { "S-" } else { "" }; + let ctrl = if keystroke.modifiers.control { + "C-" + } else { + "" + }; + let alt = if keystroke.modifiers.alt { "M-" } else { "" }; + let cmd = if keystroke.modifiers.command { + "D-" + } else { + "" + }; let end = if special { ">" } else { "" }; let key = format!("{start}{shift}{ctrl}{alt}{cmd}{}{end}", keystroke.key); diff --git a/crates/vim2/src/test/vim_test_context.rs b/crates/vim2/src/test/vim_test_context.rs index bcd133f50b..35cb28dd51 100644 --- a/crates/vim2/src/test/vim_test_context.rs +++ b/crates/vim2/src/test/vim_test_context.rs @@ -16,11 +16,25 @@ pub struct VimTestContext<'a> { impl<'a> VimTestContext<'a> { pub async fn new(cx: &'a mut gpui::TestAppContext, enabled: bool) -> VimTestContext<'a> { + cx.update(|cx| { + search::init(cx); + let settings = SettingsStore::test(cx); + cx.set_global(settings); + command_palette::init(cx); + crate::init(cx); + }); let lsp = EditorLspTestContext::new_rust(Default::default(), cx).await; Self::new_with_lsp(lsp, enabled) } pub async fn new_typescript(cx: &'a mut gpui::TestAppContext) -> VimTestContext<'a> { + cx.update(|cx| { + search::init(cx); + let settings = SettingsStore::test(cx); + cx.set_global(settings); + command_palette::init(cx); + crate::init(cx); + }); Self::new_with_lsp( EditorLspTestContext::new_typescript(Default::default(), cx).await, true, @@ -28,12 +42,6 @@ impl<'a> VimTestContext<'a> { } pub fn new_with_lsp(mut cx: EditorLspTestContext<'a>, enabled: bool) -> VimTestContext<'a> { - cx.update(|cx| { - search::init(cx); - crate::init(cx); - command_palette::init(cx); - }); - cx.update(|cx| { cx.update_global(|store: &mut SettingsStore, cx| { store.update_user_settings::(cx, |s| *s = Some(enabled)); @@ -65,9 +73,11 @@ impl<'a> VimTestContext<'a> { pub fn update_view(&mut self, view: View, update: F) -> R where - F: FnOnce(&mut T, &mut ViewContext) -> R, + T: 'static, + F: FnOnce(&mut T, &mut ViewContext) -> R + 'static, { - self.update_window(self.window, |_, cx| view.update(cx, update)) + let window = self.window.clone(); + self.update_window(window, move |_, cx| view.update(cx, update)) .unwrap() } @@ -75,8 +85,7 @@ impl<'a> VimTestContext<'a> { where F: FnOnce(&mut Workspace, &mut ViewContext) -> T, { - self.update_window(self.window, |_, cx| self.cx.workspace.update(cx, update)) - .unwrap() + self.cx.update_workspace(update) } pub fn enable_vim(&mut self) { diff --git a/crates/vim2/src/vim.rs b/crates/vim2/src/vim.rs index d6bce1a976..9513dbb342 100644 --- a/crates/vim2/src/vim.rs +++ b/crates/vim2/src/vim.rs @@ -116,45 +116,43 @@ fn register(workspace: &mut Workspace, cx: &mut ViewContext) { visual::register(workspace, cx); } -pub fn observe_keystrokes(_: &mut WindowContext) { - // todo!() +pub fn observe_keystrokes(cx: &mut WindowContext) { + cx.observe_keystrokes(|keystroke_event, cx| { + if let Some(action) = keystroke_event + .action + .as_ref() + .map(|action| action.boxed_clone()) + { + Vim::update(cx, |vim, _| { + if vim.workspace_state.recording { + vim.workspace_state + .recorded_actions + .push(ReplayableAction::Action(action.boxed_clone())); - // cx.observe_keystrokes(|_keystroke, result, handled_by, cx| { - // if result == &MatchResult::Pending { - // return true; - // } - // if let Some(handled_by) = handled_by { - // Vim::update(cx, |vim, _| { - // if vim.workspace_state.recording { - // vim.workspace_state - // .recorded_actions - // .push(ReplayableAction::Action(handled_by.boxed_clone())); + if vim.workspace_state.stop_recording_after_next_action { + vim.workspace_state.recording = false; + vim.workspace_state.stop_recording_after_next_action = false; + } + } + }); - // if vim.workspace_state.stop_recording_after_next_action { - // vim.workspace_state.recording = false; - // vim.workspace_state.stop_recording_after_next_action = false; - // } - // } - // }); + // Keystroke is handled by the vim system, so continue forward + if action.name().starts_with("vim::") { + return; + } + } - // // Keystroke is handled by the vim system, so continue forward - // if handled_by.namespace() == "vim" { - // return true; - // } - // } - - // Vim::update(cx, |vim, cx| match vim.active_operator() { - // Some( - // Operator::FindForward { .. } | Operator::FindBackward { .. } | Operator::Replace, - // ) => {} - // Some(_) => { - // vim.clear_operator(cx); - // } - // _ => {} - // }); - // true - // }) - // .detach() + Vim::update(cx, |vim, cx| match vim.active_operator() { + Some( + Operator::FindForward { .. } | Operator::FindBackward { .. } | Operator::Replace, + ) => {} + Some(_) => { + vim.clear_operator(cx); + } + _ => {} + }); + }) + .detach() } #[derive(Default)] From 4942b1962b5894a5a9952ee0822b7c3bc529cbe2 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 11 Dec 2023 14:21:21 -0700 Subject: [PATCH 2/3] Moar tests --- crates/picker2/src/picker2.rs | 1 - crates/vim2/src/normal.rs | 964 ++++++++++++----------- crates/vim2/src/test/vim_test_context.rs | 3 +- 3 files changed, 486 insertions(+), 482 deletions(-) diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index f0f3f70e57..54df321cb1 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -114,7 +114,6 @@ impl Picker { } fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { - dbg!("picker cancel"); self.delegate.dismissed(cx); } diff --git a/crates/vim2/src/normal.rs b/crates/vim2/src/normal.rs index 375675317d..a8f2e5fa5a 100644 --- a/crates/vim2/src/normal.rs +++ b/crates/vim2/src/normal.rs @@ -371,536 +371,540 @@ pub(crate) fn normal_replace(text: Arc, cx: &mut WindowContext) { }); } -// #[cfg(test)] -// mod test { -// use gpui::TestAppContext; -// use indoc::indoc; +#[cfg(test)] +mod test { + use gpui::TestAppContext; + use indoc::indoc; -// use crate::{ -// state::Mode::{self}, -// test::NeovimBackedTestContext, -// }; + use crate::{ + state::Mode::{self}, + test::NeovimBackedTestContext, + }; -// #[gpui::test] -// async fn test_h(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["h"]); -// cx.assert_all(indoc! {" -// ˇThe qˇuick -// ˇbrown" -// }) -// .await; -// } + #[gpui::test] + async fn test_h(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["h"]); + cx.assert_all(indoc! {" + ˇThe qˇuick + ˇbrown" + }) + .await; + } -// #[gpui::test] -// async fn test_backspace(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx) -// .await -// .binding(["backspace"]); -// cx.assert_all(indoc! {" -// ˇThe qˇuick -// ˇbrown" -// }) -// .await; -// } + #[gpui::test] + async fn test_backspace(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx) + .await + .binding(["backspace"]); + cx.assert_all(indoc! {" + ˇThe qˇuick + ˇbrown" + }) + .await; + } -// #[gpui::test] -// async fn test_j(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; + #[gpui::test] + async fn test_j(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; -// cx.set_shared_state(indoc! {" -// aaˇaa -// 😃😃" -// }) -// .await; -// cx.simulate_shared_keystrokes(["j"]).await; -// cx.assert_shared_state(indoc! {" -// aaaa -// 😃ˇ😃" -// }) -// .await; + cx.set_shared_state(indoc! {" + aaˇaa + 😃😃" + }) + .await; + cx.simulate_shared_keystrokes(["j"]).await; + cx.assert_shared_state(indoc! {" + aaaa + 😃ˇ😃" + }) + .await; -// for marked_position in cx.each_marked_position(indoc! {" -// ˇThe qˇuick broˇwn -// ˇfox jumps" -// }) { -// cx.assert_neovim_compatible(&marked_position, ["j"]).await; -// } -// } + for marked_position in cx.each_marked_position(indoc! {" + ˇThe qˇuick broˇwn + ˇfox jumps" + }) { + cx.assert_neovim_compatible(&marked_position, ["j"]).await; + } + } -// #[gpui::test] -// async fn test_enter(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["enter"]); -// cx.assert_all(indoc! {" -// ˇThe qˇuick broˇwn -// ˇfox jumps" -// }) -// .await; -// } + #[gpui::test] + async fn test_enter(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["enter"]); + cx.assert_all(indoc! {" + ˇThe qˇuick broˇwn + ˇfox jumps" + }) + .await; + } -// #[gpui::test] -// async fn test_k(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["k"]); -// cx.assert_all(indoc! {" -// ˇThe qˇuick -// ˇbrown fˇox jumˇps" -// }) -// .await; -// } + #[gpui::test] + async fn test_k(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["k"]); + cx.assert_all(indoc! {" + ˇThe qˇuick + ˇbrown fˇox jumˇps" + }) + .await; + } -// #[gpui::test] -// async fn test_l(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["l"]); -// cx.assert_all(indoc! {" -// ˇThe qˇuicˇk -// ˇbrowˇn"}) -// .await; -// } + #[gpui::test] + async fn test_l(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["l"]); + cx.assert_all(indoc! {" + ˇThe qˇuicˇk + ˇbrowˇn"}) + .await; + } -// #[gpui::test] -// async fn test_jump_to_line_boundaries(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; -// cx.assert_binding_matches_all( -// ["$"], -// indoc! {" -// ˇThe qˇuicˇk -// ˇbrowˇn"}, -// ) -// .await; -// cx.assert_binding_matches_all( -// ["0"], -// indoc! {" -// ˇThe qˇuicˇk -// ˇbrowˇn"}, -// ) -// .await; -// } + #[gpui::test] + async fn test_jump_to_line_boundaries(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + cx.assert_binding_matches_all( + ["$"], + indoc! {" + ˇThe qˇuicˇk + ˇbrowˇn"}, + ) + .await; + cx.assert_binding_matches_all( + ["0"], + indoc! {" + ˇThe qˇuicˇk + ˇbrowˇn"}, + ) + .await; + } -// #[gpui::test] -// async fn test_jump_to_end(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-g"]); + #[gpui::test] + async fn test_jump_to_end(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-g"]); -// cx.assert_all(indoc! {" -// The ˇquick + cx.assert_all(indoc! {" + The ˇquick -// brown fox jumps -// overˇ the lazy doˇg"}) -// .await; -// cx.assert(indoc! {" -// The quiˇck + brown fox jumps + overˇ the lazy doˇg"}) + .await; + cx.assert(indoc! {" + The quiˇck -// brown"}) -// .await; -// cx.assert(indoc! {" -// The quiˇck + brown"}) + .await; + cx.assert(indoc! {" + The quiˇck -// "}) -// .await; -// } + "}) + .await; + } -// #[gpui::test] -// async fn test_w(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["w"]); -// cx.assert_all(indoc! {" -// The ˇquickˇ-ˇbrown -// ˇ -// ˇ -// ˇfox_jumps ˇover -// ˇthˇe"}) -// .await; -// let mut cx = cx.binding(["shift-w"]); -// cx.assert_all(indoc! {" -// The ˇquickˇ-ˇbrown -// ˇ -// ˇ -// ˇfox_jumps ˇover -// ˇthˇe"}) -// .await; -// } + #[gpui::test] + async fn test_w(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["w"]); + cx.assert_all(indoc! {" + The ˇquickˇ-ˇbrown + ˇ + ˇ + ˇfox_jumps ˇover + ˇthˇe"}) + .await; + let mut cx = cx.binding(["shift-w"]); + cx.assert_all(indoc! {" + The ˇquickˇ-ˇbrown + ˇ + ˇ + ˇfox_jumps ˇover + ˇthˇe"}) + .await; + } -// #[gpui::test] -// async fn test_end_of_word(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["e"]); -// cx.assert_all(indoc! {" -// Thˇe quicˇkˇ-browˇn + #[gpui::test] + async fn test_end_of_word(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["e"]); + cx.assert_all(indoc! {" + Thˇe quicˇkˇ-browˇn -// fox_jumpˇs oveˇr -// thˇe"}) -// .await; -// let mut cx = cx.binding(["shift-e"]); -// cx.assert_all(indoc! {" -// Thˇe quicˇkˇ-browˇn -// fox_jumpˇs oveˇr -// thˇe"}) -// .await; -// } + fox_jumpˇs oveˇr + thˇe"}) + .await; + let mut cx = cx.binding(["shift-e"]); + cx.assert_all(indoc! {" + Thˇe quicˇkˇ-browˇn -// #[gpui::test] -// async fn test_b(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["b"]); -// cx.assert_all(indoc! {" -// ˇThe ˇquickˇ-ˇbrown -// ˇ -// ˇ -// ˇfox_jumps ˇover -// ˇthe"}) -// .await; -// let mut cx = cx.binding(["shift-b"]); -// cx.assert_all(indoc! {" -// ˇThe ˇquickˇ-ˇbrown -// ˇ -// ˇ -// ˇfox_jumps ˇover -// ˇthe"}) -// .await; -// } -// #[gpui::test] -// async fn test_gg(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; -// cx.assert_binding_matches_all( -// ["g", "g"], -// indoc! {" -// The qˇuick + fox_jumpˇs oveˇr + thˇe"}) + .await; + } -// brown fox jumps -// over ˇthe laˇzy dog"}, -// ) -// .await; -// cx.assert_binding_matches( -// ["g", "g"], -// indoc! {" + #[gpui::test] + async fn test_b(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["b"]); + cx.assert_all(indoc! {" + ˇThe ˇquickˇ-ˇbrown + ˇ + ˇ + ˇfox_jumps ˇover + ˇthe"}) + .await; + let mut cx = cx.binding(["shift-b"]); + cx.assert_all(indoc! {" + ˇThe ˇquickˇ-ˇbrown + ˇ + ˇ + ˇfox_jumps ˇover + ˇthe"}) + .await; + } -// brown fox jumps -// over the laˇzy dog"}, -// ) -// .await; -// cx.assert_binding_matches( -// ["2", "g", "g"], -// indoc! {" -// ˇ + #[gpui::test] + async fn test_gg(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + cx.assert_binding_matches_all( + ["g", "g"], + indoc! {" + The qˇuick -// brown fox jumps -// over the lazydog"}, -// ) -// .await; -// } + brown fox jumps + over ˇthe laˇzy dog"}, + ) + .await; + cx.assert_binding_matches( + ["g", "g"], + indoc! {" -// #[gpui::test] -// async fn test_end_of_document(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; -// cx.assert_binding_matches_all( -// ["shift-g"], -// indoc! {" -// The qˇuick -// brown fox jumps -// over ˇthe laˇzy dog"}, -// ) -// .await; -// cx.assert_binding_matches( -// ["shift-g"], -// indoc! {" + brown fox jumps + over the laˇzy dog"}, + ) + .await; + cx.assert_binding_matches( + ["2", "g", "g"], + indoc! {" + ˇ -// brown fox jumps -// over the laˇzy dog"}, -// ) -// .await; -// cx.assert_binding_matches( -// ["2", "shift-g"], -// indoc! {" -// ˇ + brown fox jumps + over the lazydog"}, + ) + .await; + } -// brown fox jumps -// over the lazydog"}, -// ) -// .await; -// } + #[gpui::test] + async fn test_end_of_document(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + cx.assert_binding_matches_all( + ["shift-g"], + indoc! {" + The qˇuick -// #[gpui::test] -// async fn test_a(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["a"]); -// cx.assert_all("The qˇuicˇk").await; -// } + brown fox jumps + over ˇthe laˇzy dog"}, + ) + .await; + cx.assert_binding_matches( + ["shift-g"], + indoc! {" -// #[gpui::test] -// async fn test_insert_end_of_line(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-a"]); -// cx.assert_all(indoc! {" -// ˇ -// The qˇuick -// brown ˇfox "}) -// .await; -// } -// #[gpui::test] -// async fn test_jump_to_first_non_whitespace(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["^"]); -// cx.assert("The qˇuick").await; -// cx.assert(" The qˇuick").await; -// cx.assert("ˇ").await; -// cx.assert(indoc! {" -// The qˇuick -// brown fox"}) -// .await; -// cx.assert(indoc! {" -// ˇ -// The quick"}) -// .await; -// // Indoc disallows trailing whitespace. -// cx.assert(" ˇ \nThe quick").await; -// } + brown fox jumps + over the laˇzy dog"}, + ) + .await; + cx.assert_binding_matches( + ["2", "shift-g"], + indoc! {" + ˇ -// #[gpui::test] -// async fn test_insert_first_non_whitespace(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-i"]); -// cx.assert("The qˇuick").await; -// cx.assert(" The qˇuick").await; -// cx.assert("ˇ").await; -// cx.assert(indoc! {" -// The qˇuick -// brown fox"}) -// .await; -// cx.assert(indoc! {" -// ˇ -// The quick"}) -// .await; -// } + brown fox jumps + over the lazydog"}, + ) + .await; + } -// #[gpui::test] -// async fn test_delete_to_end_of_line(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-d"]); -// cx.assert(indoc! {" -// The qˇuick -// brown fox"}) -// .await; -// cx.assert(indoc! {" -// The quick -// ˇ -// brown fox"}) -// .await; -// } + #[gpui::test] + async fn test_a(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["a"]); + cx.assert_all("The qˇuicˇk").await; + } -// #[gpui::test] -// async fn test_x(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["x"]); -// cx.assert_all("ˇTeˇsˇt").await; -// cx.assert(indoc! {" -// Tesˇt -// test"}) -// .await; -// } + #[gpui::test] + async fn test_insert_end_of_line(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-a"]); + cx.assert_all(indoc! {" + ˇ + The qˇuick + brown ˇfox "}) + .await; + } -// #[gpui::test] -// async fn test_delete_left(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-x"]); -// cx.assert_all("ˇTˇeˇsˇt").await; -// cx.assert(indoc! {" -// Test -// ˇtest"}) -// .await; -// } + #[gpui::test] + async fn test_jump_to_first_non_whitespace(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["^"]); + cx.assert("The qˇuick").await; + cx.assert(" The qˇuick").await; + cx.assert("ˇ").await; + cx.assert(indoc! {" + The qˇuick + brown fox"}) + .await; + cx.assert(indoc! {" + ˇ + The quick"}) + .await; + // Indoc disallows trailing whitespace. + cx.assert(" ˇ \nThe quick").await; + } -// #[gpui::test] -// async fn test_o(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["o"]); -// cx.assert("ˇ").await; -// cx.assert("The ˇquick").await; -// cx.assert_all(indoc! {" -// The qˇuick -// brown ˇfox -// jumps ˇover"}) -// .await; -// cx.assert(indoc! {" -// The quick -// ˇ -// brown fox"}) -// .await; + #[gpui::test] + async fn test_insert_first_non_whitespace(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-i"]); + cx.assert("The qˇuick").await; + cx.assert(" The qˇuick").await; + cx.assert("ˇ").await; + cx.assert(indoc! {" + The qˇuick + brown fox"}) + .await; + cx.assert(indoc! {" + ˇ + The quick"}) + .await; + } -// cx.assert_manual( -// indoc! {" -// fn test() { -// println!(ˇ); -// }"}, -// Mode::Normal, -// indoc! {" -// fn test() { -// println!(); -// ˇ -// }"}, -// Mode::Insert, -// ); + #[gpui::test] + async fn test_delete_to_end_of_line(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-d"]); + cx.assert(indoc! {" + The qˇuick + brown fox"}) + .await; + cx.assert(indoc! {" + The quick + ˇ + brown fox"}) + .await; + } -// cx.assert_manual( -// indoc! {" -// fn test(ˇ) { -// println!(); -// }"}, -// Mode::Normal, -// indoc! {" -// fn test() { -// ˇ -// println!(); -// }"}, -// Mode::Insert, -// ); -// } + #[gpui::test] + async fn test_x(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["x"]); + cx.assert_all("ˇTeˇsˇt").await; + cx.assert(indoc! {" + Tesˇt + test"}) + .await; + } -// #[gpui::test] -// async fn test_insert_line_above(cx: &mut gpui::TestAppContext) { -// let cx = NeovimBackedTestContext::new(cx).await; -// let mut cx = cx.binding(["shift-o"]); -// cx.assert("ˇ").await; -// cx.assert("The ˇquick").await; -// cx.assert_all(indoc! {" -// The qˇuick -// brown ˇfox -// jumps ˇover"}) -// .await; -// cx.assert(indoc! {" -// The quick -// ˇ -// brown fox"}) -// .await; + #[gpui::test] + async fn test_delete_left(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-x"]); + cx.assert_all("ˇTˇeˇsˇt").await; + cx.assert(indoc! {" + Test + ˇtest"}) + .await; + } -// // Our indentation is smarter than vims. So we don't match here -// cx.assert_manual( -// indoc! {" -// fn test() { -// println!(ˇ); -// }"}, -// Mode::Normal, -// indoc! {" -// fn test() { -// ˇ -// println!(); -// }"}, -// Mode::Insert, -// ); -// cx.assert_manual( -// indoc! {" -// fn test(ˇ) { -// println!(); -// }"}, -// Mode::Normal, -// indoc! {" -// ˇ -// fn test() { -// println!(); -// }"}, -// Mode::Insert, -// ); -// } + #[gpui::test] + async fn test_o(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["o"]); + cx.assert("ˇ").await; + cx.assert("The ˇquick").await; + cx.assert_all(indoc! {" + The qˇuick + brown ˇfox + jumps ˇover"}) + .await; + cx.assert(indoc! {" + The quick + ˇ + brown fox"}) + .await; -// #[gpui::test] -// async fn test_dd(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; -// cx.assert_neovim_compatible("ˇ", ["d", "d"]).await; -// cx.assert_neovim_compatible("The ˇquick", ["d", "d"]).await; -// for marked_text in cx.each_marked_position(indoc! {" -// The qˇuick -// brown ˇfox -// jumps ˇover"}) -// { -// cx.assert_neovim_compatible(&marked_text, ["d", "d"]).await; -// } -// cx.assert_neovim_compatible( -// indoc! {" -// The quick -// ˇ -// brown fox"}, -// ["d", "d"], -// ) -// .await; -// } + cx.assert_manual( + indoc! {" + fn test() { + println!(ˇ); + }"}, + Mode::Normal, + indoc! {" + fn test() { + println!(); + ˇ + }"}, + Mode::Insert, + ); -// #[gpui::test] -// async fn test_cc(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "c"]); -// cx.assert("ˇ").await; -// cx.assert("The ˇquick").await; -// cx.assert_all(indoc! {" -// The quˇick -// brown ˇfox -// jumps ˇover"}) -// .await; -// cx.assert(indoc! {" -// The quick -// ˇ -// brown fox"}) -// .await; -// } + cx.assert_manual( + indoc! {" + fn test(ˇ) { + println!(); + }"}, + Mode::Normal, + indoc! {" + fn test() { + ˇ + println!(); + }"}, + Mode::Insert, + ); + } -// #[gpui::test] -// async fn test_repeated_word(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; + #[gpui::test] + async fn test_insert_line_above(cx: &mut gpui::TestAppContext) { + let cx = NeovimBackedTestContext::new(cx).await; + let mut cx = cx.binding(["shift-o"]); + cx.assert("ˇ").await; + cx.assert("The ˇquick").await; + cx.assert_all(indoc! {" + The qˇuick + brown ˇfox + jumps ˇover"}) + .await; + cx.assert(indoc! {" + The quick + ˇ + brown fox"}) + .await; -// for count in 1..=5 { -// cx.assert_binding_matches_all( -// [&count.to_string(), "w"], -// indoc! {" -// ˇThe quˇickˇ browˇn -// ˇ -// ˇfox ˇjumpsˇ-ˇoˇver -// ˇthe lazy dog -// "}, -// ) -// .await; -// } -// } + // Our indentation is smarter than vims. So we don't match here + cx.assert_manual( + indoc! {" + fn test() { + println!(ˇ); + }"}, + Mode::Normal, + indoc! {" + fn test() { + ˇ + println!(); + }"}, + Mode::Insert, + ); + cx.assert_manual( + indoc! {" + fn test(ˇ) { + println!(); + }"}, + Mode::Normal, + indoc! {" + ˇ + fn test() { + println!(); + }"}, + Mode::Insert, + ); + } -// #[gpui::test] -// async fn test_h_through_unicode(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["h"]); -// cx.assert_all("Testˇ├ˇ──ˇ┐ˇTest").await; -// } + #[gpui::test] + async fn test_dd(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + cx.assert_neovim_compatible("ˇ", ["d", "d"]).await; + cx.assert_neovim_compatible("The ˇquick", ["d", "d"]).await; + for marked_text in cx.each_marked_position(indoc! {" + The qˇuick + brown ˇfox + jumps ˇover"}) + { + cx.assert_neovim_compatible(&marked_text, ["d", "d"]).await; + } + cx.assert_neovim_compatible( + indoc! {" + The quick + ˇ + brown fox"}, + ["d", "d"], + ) + .await; + } -// #[gpui::test] -// async fn test_f_and_t(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; + #[gpui::test] + async fn test_cc(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "c"]); + cx.assert("ˇ").await; + cx.assert("The ˇquick").await; + cx.assert_all(indoc! {" + The quˇick + brown ˇfox + jumps ˇover"}) + .await; + cx.assert(indoc! {" + The quick + ˇ + brown fox"}) + .await; + } -// for count in 1..=3 { -// let test_case = indoc! {" -// ˇaaaˇbˇ ˇbˇ ˇbˇbˇ aˇaaˇbaaa -// ˇ ˇbˇaaˇa ˇbˇbˇb -// ˇ -// ˇb -// "}; + #[gpui::test] + async fn test_repeated_word(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; -// cx.assert_binding_matches_all([&count.to_string(), "f", "b"], test_case) -// .await; + for count in 1..=5 { + cx.assert_binding_matches_all( + [&count.to_string(), "w"], + indoc! {" + ˇThe quˇickˇ browˇn + ˇ + ˇfox ˇjumpsˇ-ˇoˇver + ˇthe lazy dog + "}, + ) + .await; + } + } -// cx.assert_binding_matches_all([&count.to_string(), "t", "b"], test_case) -// .await; -// } -// } + #[gpui::test] + async fn test_h_through_unicode(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["h"]); + cx.assert_all("Testˇ├ˇ──ˇ┐ˇTest").await; + } -// #[gpui::test] -// async fn test_capital_f_and_capital_t(cx: &mut gpui::TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await; -// let test_case = indoc! {" -// ˇaaaˇbˇ ˇbˇ ˇbˇbˇ aˇaaˇbaaa -// ˇ ˇbˇaaˇa ˇbˇbˇb -// ˇ••• -// ˇb -// " -// }; + #[gpui::test] + async fn test_f_and_t(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; -// for count in 1..=3 { -// cx.assert_binding_matches_all([&count.to_string(), "shift-f", "b"], test_case) -// .await; + for count in 1..=3 { + let test_case = indoc! {" + ˇaaaˇbˇ ˇbˇ ˇbˇbˇ aˇaaˇbaaa + ˇ ˇbˇaaˇa ˇbˇbˇb + ˇ + ˇb + "}; -// cx.assert_binding_matches_all([&count.to_string(), "shift-t", "b"], test_case) -// .await; -// } -// } + cx.assert_binding_matches_all([&count.to_string(), "f", "b"], test_case) + .await; -// #[gpui::test] -// async fn test_percent(cx: &mut TestAppContext) { -// let mut cx = NeovimBackedTestContext::new(cx).await.binding(["%"]); -// cx.assert_all("ˇconsole.logˇ(ˇvaˇrˇ)ˇ;").await; -// cx.assert_all("ˇconsole.logˇ(ˇ'var', ˇ[ˇ1, ˇ2, 3ˇ]ˇ)ˇ;") -// .await; -// cx.assert_all("let result = curried_funˇ(ˇ)ˇ(ˇ)ˇ;").await; -// } -// } + cx.assert_binding_matches_all([&count.to_string(), "t", "b"], test_case) + .await; + } + } + + #[gpui::test] + async fn test_capital_f_and_capital_t(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + let test_case = indoc! {" + ˇaaaˇbˇ ˇbˇ ˇbˇbˇ aˇaaˇbaaa + ˇ ˇbˇaaˇa ˇbˇbˇb + ˇ••• + ˇb + " + }; + + for count in 1..=3 { + cx.assert_binding_matches_all([&count.to_string(), "shift-f", "b"], test_case) + .await; + + cx.assert_binding_matches_all([&count.to_string(), "shift-t", "b"], test_case) + .await; + } + } + + #[gpui::test] + async fn test_percent(cx: &mut TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await.binding(["%"]); + cx.assert_all("ˇconsole.logˇ(ˇvaˇrˇ)ˇ;").await; + cx.assert_all("ˇconsole.logˇ(ˇ'var', ˇ[ˇ1, ˇ2, 3ˇ]ˇ)ˇ;") + .await; + cx.assert_all("let result = curried_funˇ(ˇ)ˇ(ˇ)ˇ;").await; + } +} diff --git a/crates/vim2/src/test/vim_test_context.rs b/crates/vim2/src/test/vim_test_context.rs index 35cb28dd51..e9d018ca6d 100644 --- a/crates/vim2/src/test/vim_test_context.rs +++ b/crates/vim2/src/test/vim_test_context.rs @@ -120,7 +120,8 @@ impl<'a> VimTestContext<'a> { Vim::update(cx, |vim, cx| { vim.switch_mode(mode, true, cx); }) - }); + }) + .unwrap(); self.cx.cx.cx.run_until_parked(); } From 303189e086990b51c7f2edbd1ae9ce8e5afdc1dc Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Mon, 11 Dec 2023 14:54:58 -0700 Subject: [PATCH 3/3] Fix warnings --- crates/vim2/src/test.rs | 2 -- crates/vim2/src/test/neovim_backed_binding_test_context.rs | 3 +++ crates/vim2/src/test/neovim_backed_test_context.rs | 3 +++ crates/vim2/src/test/vim_test_context.rs | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/vim2/src/test.rs b/crates/vim2/src/test.rs index b233dcff83..b23c49c9a3 100644 --- a/crates/vim2/src/test.rs +++ b/crates/vim2/src/test.rs @@ -3,8 +3,6 @@ mod neovim_backed_test_context; mod neovim_connection; mod vim_test_context; -use std::sync::Arc; - use command_palette::CommandPalette; use editor::DisplayPoint; pub use neovim_backed_binding_test_context::*; diff --git a/crates/vim2/src/test/neovim_backed_binding_test_context.rs b/crates/vim2/src/test/neovim_backed_binding_test_context.rs index 15fce99aad..3b97cb2b16 100644 --- a/crates/vim2/src/test/neovim_backed_binding_test_context.rs +++ b/crates/vim2/src/test/neovim_backed_binding_test_context.rs @@ -1,3 +1,6 @@ +#![allow(unused)] +// todo!() + use std::ops::{Deref, DerefMut}; use crate::state::Mode; diff --git a/crates/vim2/src/test/neovim_backed_test_context.rs b/crates/vim2/src/test/neovim_backed_test_context.rs index eb20b99b02..0648b9169e 100644 --- a/crates/vim2/src/test/neovim_backed_test_context.rs +++ b/crates/vim2/src/test/neovim_backed_test_context.rs @@ -1,3 +1,6 @@ +#![allow(unused)] +// todo!() + use editor::{scroll::VERTICAL_SCROLL_MARGIN, test::editor_test_context::ContextHandle}; use indoc::indoc; use settings::SettingsStore; diff --git a/crates/vim2/src/test/vim_test_context.rs b/crates/vim2/src/test/vim_test_context.rs index e9d018ca6d..7b9d71ffca 100644 --- a/crates/vim2/src/test/vim_test_context.rs +++ b/crates/vim2/src/test/vim_test_context.rs @@ -1,3 +1,6 @@ +#![allow(unused)] +// todo!() + use std::ops::{Deref, DerefMut}; use editor::test::{