editor_events.rs

 1use crate::Vim;
 2use editor::{Editor, EditorEvent};
 3use gpui::{AppContext, Entity, EntityId, View, ViewContext, WindowContext};
 4
 5pub fn init(cx: &mut AppContext) {
 6    cx.observe_new_views(|_, cx: &mut ViewContext<Editor>| {
 7        let editor = cx.view().clone();
 8        cx.subscribe(&editor, |_, editor, event: &EditorEvent, cx| match event {
 9            EditorEvent::Focused => cx.window_context().defer(|cx| focused(editor, cx)),
10            EditorEvent::Blurred => cx.window_context().defer(|cx| blurred(editor, cx)),
11            _ => {}
12        })
13        .detach();
14
15        let id = cx.view().entity_id();
16        cx.on_release(move |_, cx| released(id, cx)).detach();
17    })
18    .detach();
19}
20
21fn focused(editor: View<Editor>, cx: &mut WindowContext) {
22    if Vim::read(cx).active_editor.clone().is_some() {
23        Vim::update(cx, |vim, cx| {
24            vim.update_active_editor(cx, |previously_active_editor, cx| {
25                vim.unhook_vim_settings(previously_active_editor, cx)
26            });
27        });
28    }
29
30    Vim::update(cx, |vim, cx| {
31        vim.set_active_editor(editor.clone(), cx);
32    });
33}
34
35fn blurred(editor: View<Editor>, cx: &mut WindowContext) {
36    Vim::update(cx, |vim, cx| {
37        vim.workspace_state.recording = false;
38        vim.workspace_state.recorded_actions.clear();
39        if let Some(previous_editor) = vim.active_editor.clone() {
40            if previous_editor
41                .upgrade()
42                .is_some_and(|previous| previous == editor.clone())
43            {
44                vim.clear_operator(cx);
45                vim.active_editor = None;
46                vim.editor_subscription = None;
47            }
48        }
49
50        editor.update(cx, |editor, cx| vim.unhook_vim_settings(editor, cx))
51    });
52}
53
54fn released(entity_id: EntityId, cx: &mut WindowContext) {
55    Vim::update(cx, |vim, _| {
56        if vim
57            .active_editor
58            .as_ref()
59            .is_some_and(|previous| previous.entity_id() == entity_id)
60        {
61            vim.active_editor = None;
62            vim.editor_subscription = None;
63        }
64        vim.editor_states.remove(&entity_id)
65    });
66}
67
68// #[cfg(test)]
69// mod test {
70//     use crate::{test::VimTestContext, Vim};
71//     use editor::Editor;
72//     use gpui::{Context, Entity};
73//     use language::Buffer;
74
75//     // regression test for blur called with a different active editor
76//     #[gpui::test]
77//     async fn test_blur_focus(cx: &mut gpui::TestAppContext) {
78//         let mut cx = VimTestContext::new(cx, true).await;
79
80//         let buffer = cx.build_model(|_| Buffer::new(0, 0, "a = 1\nb = 2\n"));
81//         let window2 = cx.add_window(|cx| Editor::for_buffer(buffer, None, cx));
82//         let editor2 = cx
83//             .update(|cx| window2.update(cx, |editor, cx| cx.view()))
84//             .unwrap();
85
86//         cx.update(|cx| {
87//             let vim = Vim::read(cx);
88//             assert_eq!(
89//                 vim.active_editor.unwrap().entity_id().unwrap(),
90//                 editor2.entity_id()
91//             )
92//         });
93
94//         // no panic when blurring an editor in a different window.
95//         cx.update_editor(|editor1, cx| {
96//             editor1.focus_out(cx.handle().into_any(), cx);
97//         });
98//     }
99// }