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 empty_selections_only(&self) -> bool {
50 self.mode != Mode::Visual && self.mode != Mode::VisualLine
51 }
52
53 pub fn keymap_context_layer(&self) -> Context {
54 let mut context = Context::default();
55 context.map.insert(
56 "vim_mode".to_string(),
57 match self.mode {
58 Mode::Normal => "normal",
59 Mode::Visual => "visual",
60 Mode::VisualLine => "visual_line",
61 Mode::Insert => "insert",
62 }
63 .to_string(),
64 );
65
66 if self.vim_controlled() {
67 context.set.insert("VimControl".to_string());
68 }
69
70 if let Some(operator) = &self.operator_stack.last() {
71 operator.set_context(&mut context);
72 }
73 context
74 }
75}
76
77impl Operator {
78 pub fn set_context(&self, context: &mut Context) {
79 let operator_context = match self {
80 Operator::Namespace(Namespace::G) => "g",
81 Operator::Change => "c",
82 Operator::Delete => "d",
83 }
84 .to_owned();
85
86 context
87 .map
88 .insert("vim_operator".to_string(), operator_context.to_string());
89 }
90}