Skip to main content

reovim_client_model/
direction.rs

1//! Direction types for navigation and layout.
2//!
3//! These types represent directions for cursor movement,
4//! focus navigation, and window splitting.
5
6use serde::{Deserialize, Serialize};
7
8/// Navigation direction for focus movement.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify))]
11#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
12pub enum Direction {
13    /// Move up (decrease y).
14    Up,
15    /// Move down (increase y).
16    Down,
17    /// Move left (decrease x).
18    Left,
19    /// Move right (increase x).
20    Right,
21}
22
23impl Direction {
24    /// Get the opposite direction.
25    #[must_use]
26    pub const fn opposite(self) -> Self {
27        match self {
28            Self::Up => Self::Down,
29            Self::Down => Self::Up,
30            Self::Left => Self::Right,
31            Self::Right => Self::Left,
32        }
33    }
34
35    /// Check if this is a horizontal direction (Left or Right).
36    #[must_use]
37    pub const fn is_horizontal(self) -> bool {
38        matches!(self, Self::Left | Self::Right)
39    }
40
41    /// Check if this is a vertical direction (Up or Down).
42    #[must_use]
43    pub const fn is_vertical(self) -> bool {
44        matches!(self, Self::Up | Self::Down)
45    }
46
47    /// Convert to a delta (dx, dy) for a single step.
48    #[must_use]
49    pub const fn as_delta(self) -> (i16, i16) {
50        match self {
51            Self::Up => (0, -1),
52            Self::Down => (0, 1),
53            Self::Left => (-1, 0),
54            Self::Right => (1, 0),
55        }
56    }
57}
58
59/// Split direction for window layout.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
61#[cfg_attr(feature = "wasm", derive(tsify_next::Tsify))]
62#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
63pub enum SplitDirection {
64    /// Split horizontally (windows stacked vertically, one above the other).
65    Horizontal,
66    /// Split vertically (windows side by side).
67    Vertical,
68}
69
70impl SplitDirection {
71    /// Get the opposite split direction.
72    #[must_use]
73    pub const fn opposite(self) -> Self {
74        match self {
75            Self::Horizontal => Self::Vertical,
76            Self::Vertical => Self::Horizontal,
77        }
78    }
79
80    /// Check if navigation direction is along this split.
81    ///
82    /// For horizontal splits (stacked vertically), Up/Down navigate between children.
83    /// For vertical splits (side by side), Left/Right navigate between children.
84    #[must_use]
85    pub const fn is_along(&self, direction: Direction) -> bool {
86        match self {
87            Self::Horizontal => direction.is_vertical(),
88            Self::Vertical => direction.is_horizontal(),
89        }
90    }
91}
92
93#[cfg(test)]
94#[path = "direction_tests.rs"]
95mod tests;