Skip to main content

reovim_kernel/core/
direction.rs

1//! Direction and boundary types for motion calculations.
2//!
3//! This module provides the foundational enums used by both
4//! motion calculations and text object handling.
5
6/// Direction of cursor movement.
7///
8/// Used by character, line, word, paragraph, and find-char motions.
9///
10/// # Example
11///
12/// ```
13/// use reovim_kernel::api::v1::*;
14///
15/// let forward = Direction::Forward;  // h, j, w, }, f
16/// let backward = Direction::Backward; // l, k, b, {, F
17/// ```
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19pub enum Direction {
20    /// Move forward (right for chars, down for lines)
21    Forward,
22    /// Move backward (left for chars, up for lines)
23    Backward,
24}
25
26impl Direction {
27    /// Check if direction is forward.
28    #[must_use]
29    pub const fn is_forward(&self) -> bool {
30        matches!(self, Self::Forward)
31    }
32
33    /// Check if direction is backward.
34    #[must_use]
35    pub const fn is_backward(&self) -> bool {
36        matches!(self, Self::Backward)
37    }
38
39    /// Get the opposite direction.
40    #[must_use]
41    pub const fn opposite(&self) -> Self {
42        match self {
43            Self::Forward => Self::Backward,
44            Self::Backward => Self::Forward,
45        }
46    }
47}
48
49/// Word boundary type for word motions.
50///
51/// Vim distinguishes between "words" and "WORDS":
52/// - **Word**: Sequences of alphanumeric characters or underscores,
53///   separated by other non-whitespace characters or whitespace.
54/// - **`BigWord` (WORD)**: Sequences of non-whitespace characters,
55///   separated only by whitespace.
56///
57/// # Example
58///
59/// ```
60/// use reovim_kernel::api::v1::*;
61///
62/// // Given text: "hello-world foo"
63/// // Word boundaries: hello | - | world | foo
64/// // BigWord boundaries: hello-world | foo
65///
66/// let word = WordBoundary::Word;       // w, b, e, ge
67/// let big_word = WordBoundary::BigWord; // W, B, E, gE
68/// ```
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
70pub enum WordBoundary {
71    /// Word: alphanumeric + underscore sequences (w/b/e)
72    Word,
73    /// WORD: non-whitespace sequences (W/B/E)
74    BigWord,
75}
76
77impl WordBoundary {
78    /// Check if a character is a word character for this boundary type.
79    #[must_use]
80    pub fn is_word_char(&self, c: char) -> bool {
81        match self {
82            Self::Word => c.is_alphanumeric() || c == '_',
83            Self::BigWord => !c.is_whitespace(),
84        }
85    }
86}
87
88/// Line position types for line-based motions.
89///
90/// These correspond to vim's 0, ^, $, and g_ commands.
91///
92/// # Example
93///
94/// ```
95/// use reovim_kernel::api::v1::*;
96///
97/// // Given line: "  hello world  "
98/// //             ^  ^          ^ ^
99/// //             |  |          | |
100/// //             |  FirstNonBlank|
101/// //             Start           End
102/// //                         LastNonBlank
103///
104/// let start = LinePosition::Start;           // 0
105/// let first = LinePosition::FirstNonBlank;   // ^
106/// let end = LinePosition::End;               // $
107/// let last = LinePosition::LastNonBlank;     // g_
108/// ```
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
110pub enum LinePosition {
111    /// Start of line, column 0 (vim: 0)
112    Start,
113    /// First non-blank character (vim: ^)
114    FirstNonBlank,
115    /// End of line, last character (vim: $)
116    End,
117    /// Last non-blank character (vim: g_)
118    LastNonBlank,
119}