Skip to main content

trail/app/
mode.rs

1//! Mode enum: Navigation, Visual, Search, and Command.
2//!
3//! Determines how keystrokes are dispatched and what the status bar displays.
4//! All three variants are defined here so the state shape is complete from
5//! Phase 1 onward; only `Navigation` is functionally wired this phase.
6
7/// The current interaction mode of the application.
8///
9/// - `Navigation` — default; `j`/`k`/`l`/`h` browse the directory tree.
10/// - `Search` — entered via `/`; keystrokes build a fuzzy query (Phase 2).
11/// - `Command` — entered via `:`; keystrokes build a command line (Phase 3).
12#[derive(Debug, Clone, PartialEq, Eq, Default)]
13pub enum Mode {
14    /// Default navigation mode — arrow keys / hjkl move the selection.
15    #[default]
16    Navigation,
17
18    /// Fuzzy-search mode. `query` is the current filter string; `matches`
19    /// holds indices into `AppState::entries` sorted by score.
20    ///
21    /// Functionally wired in Phase 2; the variant is defined here so
22    /// `AppState` carries the correct shape from the start.
23    Search {
24        /// Current filter query typed by the user.
25        query: String,
26        /// Indices into `AppState::entries`, ordered by match score.
27        matches: Vec<usize>,
28    },
29
30    /// Command-line mode. `buffer` is the text typed after `:` or `!`;
31    /// `cursor` is the byte offset of the insertion point.
32    ///
33    /// Functionally wired in Phase 3; the variant is defined here so
34    /// `AppState` carries the correct shape from the start.
35    Command {
36        /// Text content of the command line (excluding the leading `:` or `!`).
37        buffer: String,
38        /// Byte offset of the cursor within `buffer`.
39        cursor: usize,
40        /// Index into the command history when scrolling through past commands.
41        history_index: Option<usize>,
42    },
43
44    /// Visual mode, entered with `v`: moving the selection extends a range
45    /// from `anchor` to it, the way Vim's visual mode does. The range is
46    /// added to the marks (`Space`, `v`, `h`/`l`), deleted (`dd`) or
47    /// abandoned (`Esc`).
48    Visual {
49        /// The entry the range started on. A path, not a row, so a refresh
50        /// that re-orders the listing cannot move it.
51        anchor: std::path::PathBuf,
52    },
53}
54
55impl Mode {
56    /// Returns a short, human-readable label for the status bar.
57    pub fn label(&self) -> &'static str {
58        match self {
59            Mode::Navigation => "NORMAL",
60            Mode::Search { .. } => "SEARCH",
61            Mode::Command { .. } => "COMMAND",
62            Mode::Visual { .. } => "VISUAL",
63        }
64    }
65}