diff --git a/Cargo.lock b/Cargo.lock index f1013bf72d6843650cb0360604bd62f32679a347..311e4833aa133fecaab46cdc52bc35ec5d14cdf2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11423,6 +11423,7 @@ dependencies = [ "theme_selector2", "ui2", "util", + "vim2", "workspace2", ] diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index b2040aff5be16fecbd3a1c818dc78478601a0c19..76085aeca854be6dbfc5954052289ac810a3753b 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -2171,7 +2171,6 @@ impl Editor { self.blink_manager.update(cx, BlinkManager::pause_blinking); cx.emit(EditorEvent::SelectionsChanged { local }); - cx.emit(SearchEvent::MatchesInvalidated); if self.selections.disjoint_anchors().len() == 1 { cx.emit(SearchEvent::ActiveMatchChanged) diff --git a/crates/vim/src/editor_events.rs b/crates/vim/src/editor_events.rs index 5464952b56a8683a245bbd8366c5e854ce5c92e5..a6e0c4b801490b02ec0030b0b2a11eed14d2ac47 100644 --- a/crates/vim/src/editor_events.rs +++ b/crates/vim/src/editor_events.rs @@ -63,31 +63,30 @@ fn released(EditorReleased(editor): &EditorReleased, cx: &mut AppContext) { }); } -// #[cfg(test)] -// mod test { -// use crate::{test::VimTestContext, Vim}; -// use editor::Editor; -// use gpui::View; -// use language::Buffer; +#[cfg(test)] +mod test { + use crate::{test::VimTestContext, Vim}; + use editor::Editor; + use gpui::View; + use language::Buffer; -// // regression test for blur called with a different active editor -// #[gpui::test] -// async fn test_blur_focus(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; + // regression test for blur called with a different active editor + #[gpui::test] + async fn test_blur_focus(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; -// let buffer = cx.add_model(|_| Buffer::new(0, 0, "a = 1\nb = 2\n")); -// let window2 = cx.add_window(|cx| Editor::for_buffer(buffer, None, cx)); -// let editor2 = cx.read(|cx| window2.root(cx)).unwrap(); + let buffer = cx.add_model(|_| Buffer::new(0, 0, "a = 1\nb = 2\n")); + let window2 = cx.add_window(|cx| Editor::for_buffer(buffer, None, cx)); + let editor2 = cx.read(|cx| window2.root(cx)).unwrap(); -// cx.update(|cx| { -// let vim = Vim::read(cx); -// assert_eq!(vim.active_editor.unwrap().id(), editor2.id()) -// }); + cx.update(|cx| { + let vim = Vim::read(cx); + assert_eq!(vim.active_editor.unwrap().id(), editor2.id()) + }); -// // no panic when blurring an editor in a different window. -// cx.update_editor(|editor1, cx| { -// todo!() -// // editor1.focus_out(cx.handle().into_any(), cx); -// }); -// } -// } + // no panic when blurring an editor in a different window. + cx.update_editor(|editor1, cx| { + editor1.focus_out(cx.handle().into_any(), cx); + }); + } +} diff --git a/crates/vim2/src/editor_events.rs b/crates/vim2/src/editor_events.rs index b915bd779ec1df85624aab7c40551b3a353a6d55..0e2a1451fe06f145fc305f04f039eb0b62d17dcc 100644 --- a/crates/vim2/src/editor_events.rs +++ b/crates/vim2/src/editor_events.rs @@ -65,35 +65,40 @@ fn released(entity_id: EntityId, cx: &mut WindowContext) { }); } -// #[cfg(test)] -// mod test { -// use crate::{test::VimTestContext, Vim}; -// use editor::Editor; -// use gpui::{Context, Entity}; -// use language::Buffer; +#[cfg(test)] +mod test { + use crate::{test::VimTestContext, Vim}; + use editor::Editor; + use gpui::{Context, Entity}; + use language::Buffer; -// // regression test for blur called with a different active editor -// #[gpui::test] -// async fn test_blur_focus(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; + // regression test for blur called with a different active editor + #[gpui::test] + async fn test_blur_focus(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; -// let buffer = cx.build_model(|_| Buffer::new(0, 0, "a = 1\nb = 2\n")); -// let window2 = cx.add_window(|cx| Editor::for_buffer(buffer, None, cx)); -// let editor2 = cx -// .update(|cx| window2.update(cx, |editor, cx| cx.view())) -// .unwrap(); + let buffer = cx.build_model(|_| Buffer::new(0, 0, "a = 1\nb = 2\n")); + let window2 = cx.add_window(|cx| Editor::for_buffer(buffer, None, cx)); + let editor2 = cx + .update(|cx| { + window2.update(cx, |_, cx| { + cx.focus_self(); + cx.view().clone() + }) + }) + .unwrap(); -// cx.update(|cx| { -// let vim = Vim::read(cx); -// assert_eq!( -// vim.active_editor.unwrap().entity_id().unwrap(), -// editor2.entity_id() -// ) -// }); + cx.update(|cx| { + let vim = Vim::read(cx); + assert_eq!( + vim.active_editor.as_ref().unwrap().entity_id(), + editor2.entity_id(), + ) + }); -// // no panic when blurring an editor in a different window. -// cx.update_editor(|editor1, cx| { -// editor1.focus_out(cx.handle().into_any(), cx); -// }); -// } -// } + // no panic when blurring an editor in a different window. + cx.update_editor(|editor1, cx| { + editor1.handle_blur(cx); + }); + } +} diff --git a/crates/vim2/src/normal/search.rs b/crates/vim2/src/normal/search.rs index 3873c5b78b646aca83dfd825a9fec760d5f2ea7f..7b5f4d3e59a3362c807922ae12ffaba98fdfd8eb 100644 --- a/crates/vim2/src/normal/search.rs +++ b/crates/vim2/src/normal/search.rs @@ -345,133 +345,133 @@ fn parse_replace_all(query: &str) -> Replacement { replacement } -// #[cfg(test)] -// mod test { -// use editor::DisplayPoint; -// use search::BufferSearchBar; - -// use crate::{state::Mode, test::VimTestContext}; - -// #[gpui::test] -// async fn test_move_to_next(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; -// cx.set_state("ˇhi\nhigh\nhi\n", Mode::Normal); - -// cx.simulate_keystrokes(["*"]); -// cx.run_until_parked(); -// cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal); - -// cx.simulate_keystrokes(["*"]); -// cx.run_until_parked(); -// cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal); - -// cx.simulate_keystrokes(["#"]); -// cx.run_until_parked(); -// cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal); - -// cx.simulate_keystrokes(["#"]); -// cx.run_until_parked(); -// cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal); - -// cx.simulate_keystrokes(["2", "*"]); -// cx.run_until_parked(); -// cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal); - -// cx.simulate_keystrokes(["g", "*"]); -// cx.run_until_parked(); -// cx.assert_state("hi\nˇhigh\nhi\n", Mode::Normal); - -// cx.simulate_keystrokes(["n"]); -// cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal); - -// cx.simulate_keystrokes(["g", "#"]); -// cx.run_until_parked(); -// cx.assert_state("hi\nˇhigh\nhi\n", Mode::Normal); -// } - -// #[gpui::test] -// async fn test_search(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, true).await; - -// cx.set_state("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.run_until_parked(); - -// 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("aa\nbb\nˇcc\ncc\ncc\n", Mode::Normal); - -// // n to go to next/N to go to previous -// cx.simulate_keystrokes(["n"]); -// cx.assert_state("aa\nbb\ncc\nˇcc\ncc\n", Mode::Normal); -// cx.simulate_keystrokes(["shift-n"]); -// cx.assert_state("aa\nbb\nˇcc\ncc\ncc\n", Mode::Normal); - -// // ? to go to previous -// cx.simulate_keystrokes(["?", "enter"]); -// cx.assert_state("aa\nbb\ncc\ncc\nˇcc\n", Mode::Normal); -// cx.simulate_keystrokes(["?", "enter"]); -// cx.assert_state("aa\nbb\ncc\nˇcc\ncc\n", Mode::Normal); - -// // / to go to next -// cx.simulate_keystrokes(["/", "enter"]); -// cx.assert_state("aa\nbb\ncc\ncc\nˇcc\n", Mode::Normal); - -// // ?{search} to search backwards -// cx.simulate_keystrokes(["?", "b", "enter"]); -// cx.assert_state("aa\nbˇb\ncc\ncc\ncc\n", Mode::Normal); - -// // works with counts -// cx.simulate_keystrokes(["4", "/", "c"]); -// cx.simulate_keystrokes(["enter"]); -// cx.assert_state("aa\nbb\ncc\ncˇc\ncc\n", Mode::Normal); - -// // check that searching resumes from cursor, not previous match -// cx.set_state("ˇaa\nbb\ndd\ncc\nbb\n", Mode::Normal); -// cx.simulate_keystrokes(["/", "d"]); -// cx.simulate_keystrokes(["enter"]); -// cx.assert_state("aa\nbb\nˇdd\ncc\nbb\n", Mode::Normal); -// cx.update_editor(|editor, cx| editor.move_to_beginning(&Default::default(), cx)); -// cx.assert_state("ˇaa\nbb\ndd\ncc\nbb\n", Mode::Normal); -// cx.simulate_keystrokes(["/", "b"]); -// cx.simulate_keystrokes(["enter"]); -// cx.assert_state("aa\nˇbb\ndd\ncc\nbb\n", Mode::Normal); -// } - -// #[gpui::test] -// async fn test_non_vim_search(cx: &mut gpui::TestAppContext) { -// let mut cx = VimTestContext::new(cx, false).await; -// cx.set_state("ˇone one one one", Mode::Normal); -// cx.simulate_keystrokes(["cmd-f"]); -// cx.run_until_parked(); - -// cx.assert_editor_state("«oneˇ» one one one"); -// cx.simulate_keystrokes(["enter"]); -// cx.assert_editor_state("one «oneˇ» one one"); -// cx.simulate_keystrokes(["shift-enter"]); -// cx.assert_editor_state("«oneˇ» one one one"); -// } -// } +#[cfg(test)] +mod test { + use editor::DisplayPoint; + use search::BufferSearchBar; + + use crate::{state::Mode, test::VimTestContext}; + + #[gpui::test] + async fn test_move_to_next(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + cx.set_state("ˇhi\nhigh\nhi\n", Mode::Normal); + + cx.simulate_keystrokes(["*"]); + cx.run_until_parked(); + cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal); + + cx.simulate_keystrokes(["*"]); + cx.run_until_parked(); + cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal); + + cx.simulate_keystrokes(["#"]); + cx.run_until_parked(); + cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal); + + cx.simulate_keystrokes(["#"]); + cx.run_until_parked(); + cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal); + + cx.simulate_keystrokes(["2", "*"]); + cx.run_until_parked(); + cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal); + + cx.simulate_keystrokes(["g", "*"]); + cx.run_until_parked(); + cx.assert_state("hi\nˇhigh\nhi\n", Mode::Normal); + + cx.simulate_keystrokes(["n"]); + cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal); + + cx.simulate_keystrokes(["g", "#"]); + cx.run_until_parked(); + cx.assert_state("hi\nˇhigh\nhi\n", Mode::Normal); + } + + #[gpui::test] + async fn test_search(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true).await; + + cx.set_state("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.run_until_parked(); + + 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("aa\nbb\nˇcc\ncc\ncc\n", Mode::Normal); + + // n to go to next/N to go to previous + cx.simulate_keystrokes(["n"]); + cx.assert_state("aa\nbb\ncc\nˇcc\ncc\n", Mode::Normal); + cx.simulate_keystrokes(["shift-n"]); + cx.assert_state("aa\nbb\nˇcc\ncc\ncc\n", Mode::Normal); + + // ? to go to previous + cx.simulate_keystrokes(["?", "enter"]); + cx.assert_state("aa\nbb\ncc\ncc\nˇcc\n", Mode::Normal); + cx.simulate_keystrokes(["?", "enter"]); + cx.assert_state("aa\nbb\ncc\nˇcc\ncc\n", Mode::Normal); + + // / to go to next + cx.simulate_keystrokes(["/", "enter"]); + cx.assert_state("aa\nbb\ncc\ncc\nˇcc\n", Mode::Normal); + + // ?{search} to search backwards + cx.simulate_keystrokes(["?", "b", "enter"]); + cx.assert_state("aa\nbˇb\ncc\ncc\ncc\n", Mode::Normal); + + // works with counts + cx.simulate_keystrokes(["4", "/", "c"]); + cx.simulate_keystrokes(["enter"]); + cx.assert_state("aa\nbb\ncc\ncˇc\ncc\n", Mode::Normal); + + // check that searching resumes from cursor, not previous match + cx.set_state("ˇaa\nbb\ndd\ncc\nbb\n", Mode::Normal); + cx.simulate_keystrokes(["/", "d"]); + cx.simulate_keystrokes(["enter"]); + cx.assert_state("aa\nbb\nˇdd\ncc\nbb\n", Mode::Normal); + cx.update_editor(|editor, cx| editor.move_to_beginning(&Default::default(), cx)); + cx.assert_state("ˇaa\nbb\ndd\ncc\nbb\n", Mode::Normal); + cx.simulate_keystrokes(["/", "b"]); + cx.simulate_keystrokes(["enter"]); + cx.assert_state("aa\nˇbb\ndd\ncc\nbb\n", Mode::Normal); + } + + #[gpui::test] + async fn test_non_vim_search(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, false).await; + cx.set_state("ˇone one one one", Mode::Normal); + cx.simulate_keystrokes(["cmd-f"]); + cx.run_until_parked(); + + cx.assert_editor_state("«oneˇ» one one one"); + cx.simulate_keystrokes(["enter"]); + cx.assert_editor_state("one «oneˇ» one one"); + cx.simulate_keystrokes(["shift-enter"]); + cx.assert_editor_state("«oneˇ» one one one"); + } +} diff --git a/crates/welcome2/Cargo.toml b/crates/welcome2/Cargo.toml index ce2e102ca09d6efcb241f9a50157946822530c65..e45af11e02364d94f93af0365cf5b61bb7696b62 100644 --- a/crates/welcome2/Cargo.toml +++ b/crates/welcome2/Cargo.toml @@ -26,7 +26,7 @@ theme_selector = { package = "theme_selector2", path = "../theme_selector2" } util = { path = "../util" } picker = { package = "picker2", path = "../picker2" } workspace = { package = "workspace2", path = "../workspace2" } -# vim = { package = "vim2", path = "../vim2" } +vim = { package = "vim2", path = "../vim2" } anyhow.workspace = true log.workspace = true diff --git a/crates/welcome2/src/welcome.rs b/crates/welcome2/src/welcome.rs index 429f292edc886012a09f7b0f284bb236ef4376f1..c553a04fc7bcad5c7be3ca980a84581dacfa0d69 100644 --- a/crates/welcome2/src/welcome.rs +++ b/crates/welcome2/src/welcome.rs @@ -11,6 +11,7 @@ use gpui::{ use settings::{Settings, SettingsStore}; use std::sync::Arc; use ui::{prelude::*, Checkbox}; +use vim::VimModeSetting; use workspace::{ dock::DockPosition, item::{Item, ItemEvent}, @@ -128,29 +129,26 @@ impl Render for WelcomePage { .border_color(cx.theme().colors().border) .rounded_md() .child( - // todo!("vim setting") h_stack() .gap_2() .child( Checkbox::new( "enable-vim", - if false - /* VimSettings::get_global(cx).enabled */ - { + if VimModeSetting::get_global(cx).0 { ui::Selection::Selected } else { ui::Selection::Unselected }, - ), - // .on_click(cx.listener( - // move |this, selection, cx| { - // this.update_settings::( - // selection, - // cx, - // |settings, value| settings.enabled = value, - // ); - // }, - // )), + ) + .on_click(cx.listener( + move |this, selection, cx| { + this.update_settings::( + selection, + cx, + |setting, value| *setting = Some(value), + ); + }, + )), ) .child(Label::new("Enable vim mode")), )