1use gpui::{div, AnyElement, Element, IntoElement, Render, ViewContext};
2use settings::{Settings, SettingsStore};
3use workspace::{item::ItemHandle, ui::Label, StatusItemView};
4
5use crate::{state::Mode, Vim, VimModeSetting};
6
7pub struct ModeIndicator {
8 pub mode: Option<Mode>,
9 // _subscription: Subscription,
10}
11
12impl ModeIndicator {
13 pub fn new(cx: &mut ViewContext<Self>) -> Self {
14 cx.observe_global::<Vim>(|this, cx| this.set_mode(Vim::read(cx).state().mode, cx))
15 .detach();
16
17 cx.observe_global::<SettingsStore>(move |mode_indicator, cx| {
18 if VimModeSetting::get_global(cx).0 {
19 mode_indicator.mode = cx
20 .has_global::<Vim>()
21 .then(|| cx.global::<Vim>().state().mode);
22 } else {
23 mode_indicator.mode.take();
24 }
25 })
26 .detach();
27
28 // Vim doesn't exist in some tests
29 let mode = cx
30 .has_global::<Vim>()
31 .then(|| {
32 let vim = cx.global::<Vim>();
33 vim.enabled.then(|| vim.state().mode)
34 })
35 .flatten();
36
37 Self {
38 mode,
39 // _subscription,
40 }
41 }
42
43 pub fn set_mode(&mut self, mode: Mode, cx: &mut ViewContext<Self>) {
44 if self.mode != Some(mode) {
45 self.mode = Some(mode);
46 cx.notify();
47 }
48 }
49}
50
51impl Render for ModeIndicator {
52 type Element = AnyElement;
53
54 fn render(&mut self, _: &mut ViewContext<Self>) -> AnyElement {
55 let Some(mode) = self.mode.as_ref() else {
56 return div().into_any();
57 };
58
59 let text = match mode {
60 Mode::Normal => "-- NORMAL --",
61 Mode::Insert => "-- INSERT --",
62 Mode::Visual => "-- VISUAL --",
63 Mode::VisualLine => "-- VISUAL LINE --",
64 Mode::VisualBlock => "-- VISUAL BLOCK --",
65 };
66 Label::new(text).into_any_element()
67 }
68}
69
70impl StatusItemView for ModeIndicator {
71 fn set_active_pane_item(
72 &mut self,
73 _active_pane_item: Option<&dyn ItemHandle>,
74 _cx: &mut ViewContext<Self>,
75 ) {
76 // nothing to do.
77 }
78}