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 => {
 41                if self.operator_stack.is_empty() {
 42                    CursorShape::Block
 43                } else {
 44                    CursorShape::Underscore
 45                }
 46            }
 47            Mode::Visual { .. } => CursorShape::Block,
 48            Mode::Insert => CursorShape::Bar,
 49        }
 50    }
 51
 52    pub fn vim_controlled(&self) -> bool {
 53        !matches!(self.mode, Mode::Insert)
 54    }
 55
 56    pub fn clip_at_line_end(&self) -> bool {
 57        !matches!(self.mode, Mode::Insert | Mode::Visual { .. })
 58    }
 59
 60    pub fn empty_selections_only(&self) -> bool {
 61        !matches!(self.mode, Mode::Visual { .. })
 62    }
 63
 64    pub fn keymap_context_layer(&self) -> Context {
 65        let mut context = Context::default();
 66        context.map.insert(
 67            "vim_mode".to_string(),
 68            match self.mode {
 69                Mode::Normal => "normal",
 70                Mode::Visual { .. } => "visual",
 71                Mode::Insert => "insert",
 72            }
 73            .to_string(),
 74        );
 75
 76        if self.vim_controlled() {
 77            context.set.insert("VimControl".to_string());
 78        }
 79
 80        Operator::set_context(self.operator_stack.last(), &mut context);
 81
 82        context
 83    }
 84}
 85
 86impl Operator {
 87    pub fn set_context(operator: Option<&Operator>, context: &mut Context) {
 88        let operator_context = match operator {
 89            Some(Operator::Namespace(Namespace::G)) => "g",
 90            Some(Operator::Change) => "c",
 91            Some(Operator::Delete) => "d",
 92            Some(Operator::Yank) => "y",
 93            None => "none",
 94        }
 95        .to_owned();
 96
 97        context
 98            .map
 99            .insert("vim_operator".to_string(), operator_context);
100    }
101}