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,
10 VisualLine,
11}
12
13impl Default for Mode {
14 fn default() -> Self {
15 Self::Normal
16 }
17}
18
19#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)]
20pub enum Namespace {
21 G,
22}
23
24#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)]
25pub enum Operator {
26 Namespace(Namespace),
27 Change,
28 Delete,
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 | Mode::VisualLine => 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 keymap_context_layer(&self) -> Context {
50 let mut context = Context::default();
51 context.map.insert(
52 "vim_mode".to_string(),
53 match self.mode {
54 Mode::Normal => "normal",
55 Mode::Visual => "visual",
56 Mode::VisualLine => "visual_line",
57 Mode::Insert => "insert",
58 }
59 .to_string(),
60 );
61
62 if self.vim_controlled() {
63 context.set.insert("VimControl".to_string());
64 }
65
66 if let Some(operator) = &self.operator_stack.last() {
67 operator.set_context(&mut context);
68 }
69 context
70 }
71}
72
73impl Operator {
74 pub fn set_context(&self, context: &mut Context) {
75 let operator_context = match self {
76 Operator::Namespace(Namespace::G) => "g",
77 Operator::Change => "c",
78 Operator::Delete => "d",
79 }
80 .to_owned();
81
82 context
83 .map
84 .insert("vim_operator".to_string(), operator_context.to_string());
85 }
86}