state.rs

 1use editor::CursorShape;
 2use gpui::keymap::Context;
 3use serde::Deserialize;
 4
 5#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
 6pub enum Mode {
 7    Normal,
 8    Insert,
 9    Visual { line: bool },
10}
11
12impl Default for Mode {
13    fn default() -> Self {
14        Self::Normal
15    }
16}
17
18#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)]
19pub enum Namespace {
20    G,
21}
22
23#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)]
24pub enum Operator {
25    Namespace(Namespace),
26    Change,
27    Delete,
28    Yank,
29}
30
31#[derive(Default)]
32pub struct VimState {
33    pub mode: Mode,
34    pub operator_stack: Vec<Operator>,
35}
36
37impl VimState {
38    pub fn cursor_shape(&self) -> CursorShape {
39        match self.mode {
40            Mode::Normal | Mode::Visual { .. } => CursorShape::Block,
41            Mode::Insert => CursorShape::Bar,
42        }
43    }
44
45    pub fn vim_controlled(&self) -> bool {
46        !matches!(self.mode, Mode::Insert)
47    }
48
49    pub fn clip_at_line_end(&self) -> bool {
50        match self.mode {
51            Mode::Insert | Mode::Visual { .. } => false,
52            _ => true,
53        }
54    }
55
56    pub fn empty_selections_only(&self) -> bool {
57        !matches!(self.mode, Mode::Visual { .. })
58    }
59
60    pub fn keymap_context_layer(&self) -> Context {
61        let mut context = Context::default();
62        context.map.insert(
63            "vim_mode".to_string(),
64            match self.mode {
65                Mode::Normal => "normal",
66                Mode::Visual { .. } => "visual",
67                Mode::Insert => "insert",
68            }
69            .to_string(),
70        );
71
72        if self.vim_controlled() {
73            context.set.insert("VimControl".to_string());
74        }
75
76        if let Some(operator) = &self.operator_stack.last() {
77            operator.set_context(&mut context);
78        }
79        context
80    }
81}
82
83impl Operator {
84    pub fn set_context(&self, context: &mut Context) {
85        let operator_context = match self {
86            Operator::Namespace(Namespace::G) => "g",
87            Operator::Change => "c",
88            Operator::Delete => "d",
89            Operator::Yank => "y",
90        }
91        .to_owned();
92
93        context
94            .map
95            .insert("vim_operator".to_string(), operator_context.to_string());
96    }
97}