mode_indicator.rs

 1use gpui::{div, Element, Render, Subscription, ViewContext};
 2use workspace::{item::ItemHandle, ui::prelude::*, StatusItemView};
 3
 4use crate::{state::Mode, Vim};
 5
 6/// The ModeIndicator displays the current mode in the status bar.
 7pub struct ModeIndicator {
 8    pub(crate) mode: Option<Mode>,
 9    pub(crate) operators: String,
10    _subscription: Subscription,
11}
12
13impl ModeIndicator {
14    /// Construct a new mode indicator in this window.
15    pub fn new(cx: &mut ViewContext<Self>) -> Self {
16        let _subscription = cx.observe_global::<Vim>(|this, cx| this.update_mode(cx));
17        let mut this = Self {
18            mode: None,
19            operators: "".to_string(),
20            _subscription,
21        };
22        this.update_mode(cx);
23        this
24    }
25
26    fn update_mode(&mut self, cx: &mut ViewContext<Self>) {
27        // Vim doesn't exist in some tests
28        let Some(vim) = cx.try_global::<Vim>() else {
29            return;
30        };
31
32        if vim.enabled {
33            self.mode = Some(vim.state().mode);
34            self.operators = self.current_operators_description(&vim);
35        } else {
36            self.mode = None;
37        }
38    }
39
40    fn current_operators_description(&self, vim: &Vim) -> String {
41        vim.state()
42            .operator_stack
43            .iter()
44            .map(|item| item.id())
45            .collect::<Vec<_>>()
46            .join("")
47    }
48}
49
50impl Render for ModeIndicator {
51    fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
52        let Some(mode) = self.mode.as_ref() else {
53            return div().into_any();
54        };
55
56        Label::new(format!("{} -- {} --", self.operators, mode))
57            .size(LabelSize::Small)
58            .line_height_style(LineHeightStyle::UiLabel)
59            .into_any_element()
60    }
61}
62
63impl StatusItemView for ModeIndicator {
64    fn set_active_pane_item(
65        &mut self,
66        _active_pane_item: Option<&dyn ItemHandle>,
67        _cx: &mut ViewContext<Self>,
68    ) {
69        // nothing to do.
70    }
71}