use reovim_kernel::api::v1::{CursorStyle, Mode, ModeId, ModuleId};
pub const VIM_MODULE: ModuleId = ModuleId::new("vim");
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u16)]
pub enum VimMode {
Normal = 0,
Insert = 1,
Visual = 2,
VisualLine = 3,
VisualBlock = 4,
Replace = 5,
CommandLine = 6,
Window = 8,
Delete = 9,
Yank = 10,
Change = 11,
Lowercase = 12,
Uppercase = 13,
ToggleCase = 14,
}
impl VimMode {
pub const ALL: &'static [Self] = &[
Self::Normal,
Self::Insert,
Self::Visual,
Self::VisualLine,
Self::VisualBlock,
Self::Replace,
Self::CommandLine,
Self::Window,
Self::Delete,
Self::Yank,
Self::Change,
Self::Lowercase,
Self::Uppercase,
Self::ToggleCase,
];
pub const NORMAL_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "normal", 0);
pub const INSERT_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "insert", 1);
pub const VISUAL_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "visual", 2);
pub const VISUAL_LINE_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "visual-line", 3);
pub const VISUAL_BLOCK_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "visual-block", 4);
pub const REPLACE_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "replace", 5);
pub const COMMANDLINE_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "command", 6);
pub const WINDOW_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "window", 8);
pub const DELETE_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "delete", 9);
pub const YANK_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "yank", 10);
pub const CHANGE_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "change", 11);
pub const LOWERCASE_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "lowercase", 12);
pub const UPPERCASE_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "uppercase", 13);
pub const TOGGLE_CASE_ID: ModeId = ModeId::with_discriminant(VIM_MODULE, "toggle-case", 14);
}
impl Mode for VimMode {
fn module() -> ModuleId {
VIM_MODULE
}
fn discriminant(&self) -> u16 {
*self as u16
}
fn id(&self) -> ModeId {
let name = match self {
Self::Normal => "normal",
Self::Insert => "insert",
Self::Visual => "visual",
Self::VisualLine => "visual-line",
Self::VisualBlock => "visual-block",
Self::Replace => "replace",
Self::CommandLine => "command",
Self::Window => "window",
Self::Delete => "delete",
Self::Yank => "yank",
Self::Change => "change",
Self::Lowercase => "lowercase",
Self::Uppercase => "uppercase",
Self::ToggleCase => "toggle-case",
};
ModeId::with_discriminant(VIM_MODULE, name, self.discriminant())
}
fn display_name(&self) -> &'static str {
match self {
Self::Normal => "NORMAL",
Self::Insert => "INSERT",
Self::Visual => "VISUAL",
Self::VisualLine => "V-LINE",
Self::VisualBlock => "V-BLOCK",
Self::Replace => "REPLACE",
Self::CommandLine => "COMMAND",
Self::Window => "WINDOW",
Self::Delete => "DELETE",
Self::Yank => "YANK",
Self::Change => "CHANGE",
Self::Lowercase => "LOWERCASE",
Self::Uppercase => "UPPERCASE",
Self::ToggleCase => "TOGGLE-CASE",
}
}
fn cursor_style(&self) -> CursorStyle {
match self {
Self::Normal | Self::Visual | Self::VisualLine | Self::VisualBlock => {
CursorStyle::Block
}
Self::Insert | Self::CommandLine => CursorStyle::Bar,
Self::Replace => CursorStyle::Underline,
Self::Window
| Self::Delete
| Self::Yank
| Self::Change
| Self::Lowercase
| Self::Uppercase
| Self::ToggleCase => CursorStyle::Block,
}
}
fn accepts_char_input(&self) -> bool {
matches!(self, Self::Insert | Self::Replace | Self::CommandLine)
}
fn has_selection(&self) -> bool {
matches!(self, Self::Visual | Self::VisualLine | Self::VisualBlock)
}
fn inherits_from(&self) -> Option<Self> {
match self {
Self::Window
| Self::Delete
| Self::Yank
| Self::Change
| Self::Lowercase
| Self::Uppercase
| Self::ToggleCase
| Self::Visual => Some(Self::Normal),
Self::VisualLine | Self::VisualBlock => Some(Self::Visual),
Self::Replace => Some(Self::Insert),
Self::Normal | Self::Insert | Self::CommandLine => None,
}
}
fn is_entry(&self) -> bool {
matches!(self, Self::Normal)
}
}