//! Types that flow between the menu engine and frontends. //! //! - [`Action`]: commands sent into the menu (keypresses, //! script actions). //! - [`MenuEvent`]: notifications sent out to subscribers //! (state changes, terminal events). //! - [`ViewState`]: snapshot of what the frontend should //! render right now. use std::sync::Arc; use serde_json::Value; /// Input mode. Insert mode sends keystrokes to the filter, /// normal mode uses vim-style navigation keybinds. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum Mode { #[default] Insert, Normal, } /// A command the menu should process. Frontends and headless /// scripts both produce these. The menu loop consumes them /// sequentially. #[derive(Debug, Clone, PartialEq)] pub enum Action { UpdateFilter(String), MoveUp(usize), MoveDown(usize), MoveToTop, MoveToBottom, PageUp(usize), PageDown(usize), HalfPageUp(usize), HalfPageDown(usize), SetMode(Mode), Confirm, Cancel, Resize { height: u16 }, AddItems(Vec), } /// Broadcast from the menu loop to all subscribers /// (frontends, tests). #[derive(Debug, Clone)] pub enum MenuEvent { StateChanged(ViewState), Selected(Value), Cancelled, } /// Snapshot of the menu's visible state. Sent on every state /// change so frontends can render without querying back into /// the engine. #[must_use] #[derive(Debug, Clone)] pub struct ViewState { pub visible_items: Vec, /// Index of the cursor within `visible_items` /// (not the full list). pub cursor: usize, pub filter_text: Arc, pub total_items: usize, pub total_filtered: usize, pub mode: Mode, } /// A single item in the current viewport window. Has the /// display label pre-resolved and the position in the /// filtered list. #[must_use] #[derive(Debug, Clone)] pub struct VisibleItem { pub label: String, pub index: usize, } /// Final outcome of [`crate::menu::MenuRunner::run`]. The /// user either picked something or bailed. #[must_use] #[derive(Debug)] pub enum MenuResult { Selected(Value), Cancelled, }