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        match self.mode {
 58            Mode::Insert | Mode::Visual { .. } => false,
 59            _ => true,
 60        }
 61    }
 62
 63    pub fn empty_selections_only(&self) -> bool {
 64        !matches!(self.mode, Mode::Visual { .. })
 65    }
 66
 67    pub fn keymap_context_layer(&self) -> Context {
 68        let mut context = Context::default();
 69        context.map.insert(
 70            "vim_mode".to_string(),
 71            match self.mode {
 72                Mode::Normal => "normal",
 73                Mode::Visual { .. } => "visual",
 74                Mode::Insert => "insert",
 75            }
 76            .to_string(),
 77        );
 78
 79        if self.vim_controlled() {
 80            context.set.insert("VimControl".to_string());
 81        }
 82
 83        Operator::set_context(self.operator_stack.last(), &mut context);
 84
 85        context
 86    }
 87}
 88
 89impl Operator {
 90    pub fn set_context(operator: Option<&Operator>, context: &mut Context) {
 91        let operator_context = match operator {
 92            Some(Operator::Namespace(Namespace::G)) => "g",
 93            Some(Operator::Change) => "c",
 94            Some(Operator::Delete) => "d",
 95            Some(Operator::Yank) => "y",
 96            None => "none",
 97        }
 98        .to_owned();
 99
100        context
101            .map
102            .insert("vim_operator".to_string(), operator_context.to_string());
103    }
104}