vim_test_context.rs

  1#![allow(unused)]
  2// todo!()
  3
  4use std::ops::{Deref, DerefMut};
  5
  6use editor::test::{
  7    editor_lsp_test_context::EditorLspTestContext, editor_test_context::EditorTestContext,
  8};
  9use futures::Future;
 10use gpui::{Context, View, VisualContext};
 11use lsp::request;
 12use search::BufferSearchBar;
 13
 14use crate::{state::Operator, *};
 15
 16pub struct VimTestContext<'a> {
 17    cx: EditorLspTestContext<'a>,
 18}
 19
 20impl<'a> VimTestContext<'a> {
 21    pub fn init(cx: &mut gpui::TestAppContext) {
 22        if cx.has_global::<Vim>() {
 23            dbg!("OOPS");
 24            return;
 25        }
 26        cx.update(|cx| {
 27            search::init(cx);
 28            let settings = SettingsStore::test(cx);
 29            cx.set_global(settings);
 30            command_palette::init(cx);
 31            crate::init(cx);
 32        });
 33    }
 34
 35    pub async fn new(cx: &'a mut gpui::TestAppContext, enabled: bool) -> VimTestContext<'a> {
 36        Self::init(cx);
 37        let lsp = EditorLspTestContext::new_rust(Default::default(), cx).await;
 38        Self::new_with_lsp(lsp, enabled)
 39    }
 40
 41    pub async fn new_typescript(cx: &'a mut gpui::TestAppContext) -> VimTestContext<'a> {
 42        Self::init(cx);
 43        Self::new_with_lsp(
 44            EditorLspTestContext::new_typescript(Default::default(), cx).await,
 45            true,
 46        )
 47    }
 48
 49    pub fn new_with_lsp(mut cx: EditorLspTestContext<'a>, enabled: bool) -> VimTestContext<'a> {
 50        cx.update(|cx| {
 51            cx.update_global(|store: &mut SettingsStore, cx| {
 52                store.update_user_settings::<VimModeSetting>(cx, |s| *s = Some(enabled));
 53            });
 54            settings::KeymapFile::load_asset("keymaps/default.json", cx).unwrap();
 55            settings::KeymapFile::load_asset("keymaps/vim.json", cx).unwrap();
 56        });
 57
 58        // Setup search toolbars and keypress hook
 59        cx.update_workspace(|workspace, cx| {
 60            observe_keystrokes(cx);
 61            workspace.active_pane().update(cx, |pane, cx| {
 62                pane.toolbar().update(cx, |toolbar, cx| {
 63                    let buffer_search_bar = cx.build_view(BufferSearchBar::new);
 64                    toolbar.add_item(buffer_search_bar, cx);
 65                    // todo!();
 66                    // let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
 67                    // toolbar.add_item(project_search_bar, cx);
 68                })
 69            });
 70            workspace.status_bar().update(cx, |status_bar, cx| {
 71                let vim_mode_indicator = cx.build_view(ModeIndicator::new);
 72                status_bar.add_right_item(vim_mode_indicator, cx);
 73            });
 74        });
 75
 76        Self { cx }
 77    }
 78
 79    pub fn update_view<F, T, R>(&mut self, view: View<T>, update: F) -> R
 80    where
 81        T: 'static,
 82        F: FnOnce(&mut T, &mut ViewContext<T>) -> R + 'static,
 83    {
 84        let window = self.window.clone();
 85        self.update_window(window, move |_, cx| view.update(cx, update))
 86            .unwrap()
 87    }
 88
 89    pub fn workspace<F, T>(&mut self, update: F) -> T
 90    where
 91        F: FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
 92    {
 93        self.cx.update_workspace(update)
 94    }
 95
 96    pub fn enable_vim(&mut self) {
 97        self.cx.update(|cx| {
 98            cx.update_global(|store: &mut SettingsStore, cx| {
 99                store.update_user_settings::<VimModeSetting>(cx, |s| *s = Some(true));
100            });
101        })
102    }
103
104    pub fn disable_vim(&mut self) {
105        self.cx.update(|cx| {
106            cx.update_global(|store: &mut SettingsStore, cx| {
107                store.update_user_settings::<VimModeSetting>(cx, |s| *s = Some(false));
108            });
109        })
110    }
111
112    pub fn mode(&mut self) -> Mode {
113        self.cx.read(|cx| cx.global::<Vim>().state().mode)
114    }
115
116    pub fn active_operator(&mut self) -> Option<Operator> {
117        self.cx
118            .read(|cx| cx.global::<Vim>().state().operator_stack.last().copied())
119    }
120
121    pub fn set_state(&mut self, text: &str, mode: Mode) {
122        let window = self.window;
123        self.cx.set_state(text);
124        self.update_window(window, |_, cx| {
125            Vim::update(cx, |vim, cx| {
126                vim.switch_mode(mode, true, cx);
127            })
128        })
129        .unwrap();
130        self.cx.cx.cx.run_until_parked();
131    }
132
133    #[track_caller]
134    pub fn assert_state(&mut self, text: &str, mode: Mode) {
135        self.assert_editor_state(text);
136        assert_eq!(self.mode(), mode, "{}", self.assertion_context());
137    }
138
139    pub fn assert_binding<const COUNT: usize>(
140        &mut self,
141        keystrokes: [&str; COUNT],
142        initial_state: &str,
143        initial_mode: Mode,
144        state_after: &str,
145        mode_after: Mode,
146    ) {
147        self.set_state(initial_state, initial_mode);
148        self.cx.simulate_keystrokes(keystrokes);
149        self.cx.assert_editor_state(state_after);
150        assert_eq!(self.mode(), mode_after, "{}", self.assertion_context());
151        assert_eq!(self.active_operator(), None, "{}", self.assertion_context());
152    }
153
154    pub fn handle_request<T, F, Fut>(
155        &self,
156        handler: F,
157    ) -> futures::channel::mpsc::UnboundedReceiver<()>
158    where
159        T: 'static + request::Request,
160        T::Params: 'static + Send,
161        F: 'static + Send + FnMut(lsp::Url, T::Params, gpui::AsyncAppContext) -> Fut,
162        Fut: 'static + Send + Future<Output = Result<T::Result>>,
163    {
164        self.cx.handle_request::<T, F, Fut>(handler)
165    }
166}
167
168impl<'a> Deref for VimTestContext<'a> {
169    type Target = EditorTestContext<'a>;
170
171    fn deref(&self) -> &Self::Target {
172        &self.cx
173    }
174}
175
176impl<'a> DerefMut for VimTestContext<'a> {
177    fn deref_mut(&mut self) -> &mut Self::Target {
178        &mut self.cx
179    }
180}