Skip to main content

Mode

Trait Mode 

Source
pub trait Mode:
    Copy
    + Clone
    + PartialEq
    + Eq
    + Hash
    + Send
    + Sync
    + 'static {
    // Required methods
    fn module() -> ModuleId
       where Self: Sized;
    fn discriminant(&self) -> u16;
    fn display_name(&self) -> &'static str;
    fn cursor_style(&self) -> CursorStyle;
    fn accepts_char_input(&self) -> bool;

    // Provided methods
    fn id(&self) -> ModeId
       where Self: Sized { ... }
    fn has_selection(&self) -> bool { ... }
    fn inherits_from(&self) -> Option<Self>
       where Self: Sized { ... }
    fn is_entry(&self) -> bool { ... }
}
Expand description

Mode trait for type-safe, compile-time enforced mode ownership.

Policy modules (e.g., vim, emacs) define their own Mode enums and implement this trait. The trait provides both identity and behavior information, allowing the kernel and drivers to query mode properties without knowing the concrete type.

§Type Safety

The trait requires Copy + Clone + PartialEq + Eq + Hash to ensure modes are lightweight value types that can be efficiently compared and stored. This also makes the trait not object-safe, which is intentional: runtime storage uses ModeId, not dyn Mode.

§Blanket Implementation

All Mode types automatically implement From<M> for ModeId, allowing ergonomic conversion when storing modes in ModeStack or ModeRegistry.

§Example

use reovim_kernel::api::v1::{Mode, ModeId, ModuleId, CursorStyle};

const VIM_MODULE: ModuleId = ModuleId::new("vim");

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u16)]
enum VimMode {
    Normal = 0,
    Insert = 1,
    Visual = 2,
}

impl Mode for VimMode {
    fn module() -> ModuleId { VIM_MODULE }

    fn discriminant(&self) -> u16 { *self as u16 }

    fn display_name(&self) -> &'static str {
        match self {
            Self::Normal => "NORMAL",
            Self::Insert => "INSERT",
            Self::Visual => "VISUAL",
        }
    }

    fn cursor_style(&self) -> CursorStyle {
        match self {
            Self::Insert => CursorStyle::Bar,
            _ => CursorStyle::Block,
        }
    }

    fn accepts_char_input(&self) -> bool {
        matches!(self, Self::Insert)
    }
}

Required Methods§

Source

fn module() -> ModuleId
where Self: Sized,

The module that owns this mode type.

This is a type-level constant, not an instance method.

Source

fn discriminant(&self) -> u16

Get the unique discriminant for this mode variant.

For #[repr(u16)] enums, this is typically *self as u16. Discriminants must be stable across versions for serialization.

Source

fn display_name(&self) -> &'static str

Get the display name for this mode.

This is shown in the statusline (e.g., “NORMAL”, “INSERT”, “VISUAL”).

Source

fn cursor_style(&self) -> CursorStyle

Get the cursor style for this mode.

Different modes typically use different cursor styles:

  • Normal mode: Block cursor
  • Insert mode: Bar cursor
  • Replace mode: Underline cursor
Source

fn accepts_char_input(&self) -> bool

Whether this mode accepts direct character input.

Returns true for modes like Insert, CommandLine, Replace. Returns false for Normal, Visual, OperatorPending.

Provided Methods§

Source

fn id(&self) -> ModeId
where Self: Sized,

Convert to the runtime storage type.

Default implementation creates a ModeId from module, display_name, and discriminant. Override only if custom behavior is needed.

Source

fn has_selection(&self) -> bool

Whether this mode has an active selection.

Returns true for Visual, Select modes. Default is false.

Source

fn inherits_from(&self) -> Option<Self>
where Self: Sized,

Get the parent mode for keybinding inheritance.

For example, VisualLine might inherit from Visual, which inherits from Normal. Returns None for root modes.

Source

fn is_entry(&self) -> bool

Whether this is the entry/default mode for new sessions.

Only one mode per module should return true. The first mode registered with is_entry() = true becomes the session’s initial mode.

Default is false.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§