87 lines
3.4 KiB
Rust
87 lines
3.4 KiB
Rust
//! Trait abstractions for the menu data layer. [`Menu`]
|
|
//! is what the event loop drives. [`MenuItem`] is the display
|
|
//! contract for a single entry. Different backends (JSON,
|
|
//! CSV, Postgres, etc.) implement these.
|
|
|
|
/// Display contract for a single entry in a menu.
|
|
/// Provides a label for display and serialization for output.
|
|
pub trait MenuItem: Send + Sync + 'static {
|
|
/// Human-readable display text for this entry.
|
|
fn label(&self) -> &str;
|
|
|
|
/// Serialize this entry for structured output (stdout, hooks).
|
|
fn serialize(&self) -> serde_json::Value;
|
|
}
|
|
|
|
/// A filterable collection that the menu event loop drives.
|
|
/// Each implementation owns its data and handles filtering
|
|
/// internally. The event loop only needs labels (strings)
|
|
/// and serialized output (JSON values).
|
|
pub trait Menu: Send + 'static {
|
|
/// Total number of items before filtering.
|
|
fn total(&self) -> usize;
|
|
|
|
/// Apply a filter query. Implementations decide how to
|
|
/// match (fuzzy, regex, exact, SQL WHERE, etc.).
|
|
fn apply_filter(&mut self, query: &str);
|
|
|
|
/// Number of items that passed the current filter.
|
|
fn filtered_count(&self) -> usize;
|
|
|
|
/// Get the display label for a filtered item by its
|
|
/// position in the filtered results.
|
|
fn filtered_label(&self, filtered_index: usize) -> Option<&str>;
|
|
|
|
/// Get the JSON value of a filtered item for output.
|
|
/// Returns a reference to the stored value.
|
|
fn serialize_filtered(&self, filtered_index: usize) -> Option<&serde_json::Value>;
|
|
|
|
/// Get the original index of a filtered item. Used to
|
|
/// provide the item's position in the unfiltered list
|
|
/// for output and hook events.
|
|
fn original_index(&self, filtered_index: usize) -> Option<usize>;
|
|
|
|
/// Get the JSON value of an item by its original (pre-filter)
|
|
/// index. Used by multi-select to retrieve selected items
|
|
/// that may not be in the current filtered set.
|
|
fn serialize_original(&self, original_index: usize) -> Option<&serde_json::Value>;
|
|
|
|
/// Get the formatted display text for a filtered item,
|
|
/// if a format template is configured. Returns None if
|
|
/// no template is set, in which case the raw label is
|
|
/// used.
|
|
fn formatted_label(&self, _filtered_index: usize) -> Option<String> {
|
|
None
|
|
}
|
|
|
|
/// Collect all filtered items as (value, original_index) pairs.
|
|
/// Default implementation iterates filtered results using
|
|
/// existing trait methods.
|
|
fn collect_filtered(&self) -> Vec<(&serde_json::Value, usize)> {
|
|
(0..self.filtered_count())
|
|
.filter_map(|i| {
|
|
let value = self.serialize_filtered(i)?;
|
|
let orig = self.original_index(i)?;
|
|
Some((value, orig))
|
|
})
|
|
.collect()
|
|
}
|
|
}
|
|
|
|
/// Extension of [`Menu`] with mutation methods. Required by
|
|
/// [`MenuRunner`] which needs to add, replace, and remove
|
|
/// items. Embedders that only need read-only access can
|
|
/// depend on `Menu` alone.
|
|
pub trait MutableMenu: Menu {
|
|
/// Add raw values from streaming input or AddItems actions.
|
|
fn add_raw(&mut self, values: Vec<serde_json::Value>);
|
|
|
|
/// Replace all items with a new set of values. Used by
|
|
/// handler hook `replace_items` responses.
|
|
fn replace_all(&mut self, values: Vec<serde_json::Value>);
|
|
|
|
/// Remove items at the given original indices. Used by
|
|
/// handler hook `remove_items` responses.
|
|
fn remove_by_indices(&mut self, indices: Vec<usize>);
|
|
}
|