7864 lines · 235.7 KB · Rust
RawDownload
use itertools::Itertools;use unindent::Unindent;use warpui::platform::WindowStyle;use warpui::{App, EntityIdSet, ViewHandle}; use super::*;use crate::editor::EditorView; /// Helper function for testing vim mode commands./// This creates an editor with the given content and enters Vim Normal mode,/// as opposed to the default Insert mode.fn add_editor_vim_normal_mode(buffer_content: &str, app: &mut App) -> ViewHandle<EditorView> {    let (_, editor) = app.add_window(WindowStyle::NotStealFocus, move |ctx| {        let options = EditorOptions {            supports_vim_mode: true,            ..Default::default()        };        let base_text = buffer_content.unindent();        let mut editor = EditorView::new_with_base_text(base_text.as_str(), options, ctx);        editor            .select_ranges(vec![DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], ctx)            .unwrap();        editor.vim_keystroke(&Keystroke::parse("escape").unwrap(), ctx);        assert_eq!(editor.vim_mode(ctx), Some(VimMode::Normal));        editor    });    editor} #[test]fn test_vim_ctrl_c_normal() {    App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode("some text", &mut app);         // Ctrl-c in normal mode should clear the buffer        // and stay in normal mode.        editor.update(&mut app, |view, view_ctx| {            view.handle_action(&EditorAction::CtrlC, view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(view.buffer_text(app_ctx), "");            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]            );            assert_eq!(view.vim_mode(app_ctx), Some(VimMode::Normal))        });    });} #[test]fn test_vim_ctrl_c_insert() {    App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode("", &mut app);         // Insert some text.        editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("i", view_ctx);            view.vim_user_insert("add text", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(view.buffer_text(app_ctx), "add text");            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(0, 8)..DisplayPoint::new(0, 8)]            );            assert_eq!(view.vim_mode(app_ctx), Some(VimMode::Insert))        });         // Ctrl-c in insert mode should clear the buffer        // and stay in insert mode.        //        // Why not switch to normal mode?        // Terminal vi mode implementations typically use insert mode as the default mode,        // because inserting text is generally more common in the terminal than editing text.        // To be consistent with those, we're not changing to normal mode on ctrl-c.        editor.update(&mut app, |view, view_ctx| {            view.handle_action(&EditorAction::CtrlC, view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(view.buffer_text(app_ctx), "");            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]            );            assert_eq!(view.vim_mode(app_ctx), Some(VimMode::Insert))        });    });} #[test]fn test_vim_ctrl_c_replace() {    App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode("some text", &mut app);         // Ctrl-c in replace mode should cancel the replacement.        editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("r", view_ctx);            view.handle_action(&EditorAction::CtrlC, view_ctx);            view.vim_user_insert("~", view_ctx);        });         // Instead of replacing "s" with "~", the "~" should be interpreted        // on its own.        editor.read(&app, |view, app_ctx| {            assert_eq!(view.buffer_text(app_ctx), "Some text");            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]            );            assert_eq!(view.vim_mode(app_ctx), Some(VimMode::Normal))        });    });} #[test]fn test_vim_ctrl_c_visual() {    App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode("some text", &mut app);         // Ctrl-c in replace mode should exit visual mode.        editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("vw", view_ctx);            view.handle_action(&EditorAction::CtrlC, view_ctx);            view.vim_user_insert("d", view_ctx);        });         // Instead of deleting the word, the "d" should be a pending operator.        editor.read(&app, |view, app_ctx| {            assert_eq!(view.buffer_text(app_ctx), "some text");            assert_eq!(view.vim_mode(app_ctx), Some(VimMode::Normal));            assert_eq!(view.vim_model.as_ref(app_ctx).state().showcmd, "d");        });    });} #[test]fn test_vim_enter() {    App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode("letters", &mut app);         // Go into insert mode, then enter.        editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("A", view_ctx);            view.enter(view_ctx);        });         // Vim FSA should stay in insert mode.        editor.read(&app, |view, app_ctx| {            assert_eq!(view.vim_mode(app_ctx), Some(VimMode::Insert))        });         // Go into normal mode, then enter.        editor.update(&mut app, |view, view_ctx| {            view.vim_keystroke(&Keystroke::parse("escape").unwrap(), view_ctx);            view.enter(view_ctx);        });         // Vim FSA should switch back to insert mode.        editor.read(&app, |view, app_ctx| {            assert_eq!(view.vim_mode(app_ctx), Some(VimMode::Insert))        });    });} #[test]fn test_vim_number_repeat_action() {    App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode(            "line 1            line 2            line 3            line 4",            &mut app,        );         editor.update(&mut app, |view, view_ctx| {            view.select_ranges(                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)],                view_ctx,            )            .unwrap();            view.vim_user_insert("3dd", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]            );            assert_eq!(view.buffer_text(app_ctx), "line 4");            assert_eq!(view.vim_mode(app_ctx), Some(VimMode::Normal))        });    });} #[test]fn test_vim_number_repeat_word_motion() {    App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode(            "abc de f            gh ijkl m nop"                .unindent()                .as_str(),            &mut app,        );         editor.update(&mut app, |view, view_ctx| {            view.select_ranges(                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)],                view_ctx,            )            .unwrap();            view.vim_user_insert("3w", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]            );        });         // Try to go past the end of the buffer.        editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("4w", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(1, 12)..DisplayPoint::new(1, 12)]            );        });         editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("2b", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(1, 8)..DisplayPoint::new(1, 8)]            );        });         editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("2b2e", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6)]            );        });    });} #[test]fn test_vim_number_repeat_line_motion() {    // TODO: make sure to test line motions where number-repeat does nothing     App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode(            "aa            bbbbb            ccc            dddd"                .unindent()                .as_str(),            &mut app,        );         // Lay out the window so that up and down motions work.        // Layout code starts here.        let window_id = app.read(|ctx| editor.window_id(ctx));        let mut presenter = warpui::presenter::Presenter::new(window_id);         let mut updated = EntityIdSet::default();        updated.insert(app.root_view_id(window_id).unwrap());        let invalidation = warpui::WindowInvalidation {            updated,            ..Default::default()        };         app.update(move |ctx| {            presenter.invalidate(invalidation, ctx);            presenter.build_scene(                pathfinder_geometry::vector::vec2f(1000., 1000.),                1.,                None,                ctx,            );        });        // Layout code ends here.         // #$        editor.update(&mut app, |view, view_ctx| {            view.select_ranges(                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)],                view_ctx,            )            .unwrap();            view.vim_user_insert("2$", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]            );        });         editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("3$", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3)]            );        });         // #^ ignores the repetition count.        editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("3^", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]            );        });    });} #[test]fn test_vim_number_repeat_character_motion() {    App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode(            "aa            bbbbb            ccc            dddd"                .unindent()                .as_str(),            &mut app,        );         // Lay out the window so that up and down motions work.        // Layout code starts here.        let window_id = app.read(|ctx| editor.window_id(ctx));        let mut presenter = warpui::presenter::Presenter::new(window_id);         let mut updated = EntityIdSet::default();        updated.insert(app.root_view_id(window_id).unwrap());        let invalidation = warpui::WindowInvalidation {            updated,            ..Default::default()        };         app.update(move |ctx| {            presenter.invalidate(invalidation, ctx);            presenter.build_scene(                pathfinder_geometry::vector::vec2f(1000., 1000.),                1.,                None,                ctx,            );        });        // Layout code ends here.         // #j        editor.update(&mut app, |view, view_ctx| {            view.select_ranges(                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)],                view_ctx,            )            .unwrap();            view.vim_user_insert("3j", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]            );        });         // #l        editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("3l", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3)]            );        });         // #k        editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("2k", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]            );        });         // #h (and attempt to go past the start of the line)        editor.update(&mut app, |view, view_ctx| {            view.vim_user_insert("4h", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]            );        });    });} #[test]fn test_vim_number_repeat_op_word_motion() {    App::test((), |mut app| async move {        initialize_app(&mut app);         let editor = add_editor_vim_normal_mode(            "line 1            line 2            line 3            line 4",            &mut app,        );         editor.update(&mut app, |view, view_ctx| {            view.select_ranges(                vec![DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)],                view_ctx,            )            .unwrap();            view.vim_user_insert("d3w", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(                view.selected_ranges(app_ctx),                vec![DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]            );            assert_eq!(                view.buffer_text(app_ctx),                "line 1                3                line 4"                    .unindent()                    .as_str()            );            assert_eq!(view.vim_mode(app_ctx), Some(VimMode::Normal))        });         editor.update(&mut app, |view, view_ctx| {            view.select_ranges(                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)],                view_ctx,            )            .unwrap();            view.vim_user_insert("c2w", view_ctx);        });         editor.read(&app, |view, app_ctx| {            assert_eq!(

Lines 1–500 of 7864.