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}