API Reference - tui-pages

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# API Reference

A map of the public surface, with the signatures you'll actually call. Full generated docs live on docs.rs. Signatures here are abbreviated (bounds elided) for readability.

## Prelude

    #![allow(unused)]
    fn main() {
    use tui_pages::prelude::*;
    }

Pulls in the runtime types, the focus types, `modes::*`, `parse_binding`, and — importantly — the traits `TuiActionHandler`, `FocusController`, and `PageProvider`. With the `dialog` feature it also brings in `DialogData`, `DialogResult`, `DialogTheme`, `render_dialog`, and the `dialog::*` helpers.

## Building the app

    #![allow(unused)]
    fn main() {
    TuiPages::builder(initial_view: V) -> TuiPagesBuilder<...>

    impl TuiPagesBuilder {
        // pages + handler (both required)
        fn page_fn(self, f: PageFn<V, S, O>) -> Self;     // page provider as a fn
        fn pages(self, provider: P) -> Self;              // or a custom PageProvider
        fn handler(self, h: Handler) -> Self;

        // bindings & commands
        fn bind(self, mode: impl Into<ModeId>, binding: &str, action: A) -> Self;
        fn keymap(self, mode: impl Into<ModeId>, f: impl FnOnce(&mut KeyMap<A>)) -> Self;
        fn command(self, name: impl Into<String>, aliases, action: A) -> Self;

        // canvas feature
        fn canvas_defaults(self) -> Self;      // keymaps + typed CanvasAction routing
        fn canvas_keymaps(self) -> Self;       // keymaps only
        fn canvas_text_actions(self) -> Self;  // typed chars -> CanvasAction::InsertChar
        fn canvas_form_editor(self, id: usize) -> Self;
        fn canvas_textarea_widget(self, focus_index: usize) -> Self;
        fn canvas_textinput_widget(self, focus_index: usize) -> Self; // optional inline suffix via CanvasWidgetState

        // tuning (all optional)
        fn fallback_view(self, view: V) -> Self;          // view to fall back to on close
        fn focus_wrap(self, wrap: FocusWrap) -> Self;     // Clamp (default) or Wrap
        fn input_timeout_ms(self, ms: u64) -> Self;       // chord-sequence timeout
        fn command_timeout_ms(self, ms: u64) -> Self;

        fn build(self) -> TuiPages<...>;
    }
    }

`PageFn<V, S, O>` is `fn(&V, &S, Option<&FocusTarget<O>>) -> PageSpec<O>`.

## The runtime: `TuiPages`

Public fields (you read these to render; you don't drive them):

    #![allow(unused)]
    fn main() {
    pub input:    InputPipeline<A>
    pub commands: CommandResolver<A>      // resolve typed commands
    pub focus:    FocusManager<O, M>      // focus.current(), focus.has_overlay(), ...
    pub buffer:   BufferState<V>          // buffer.panes(), buffer.is_split(), ...
    }

Methods you call:

    #![allow(unused)]
    fn main() {
    fn handle_key(&mut self, key: KeyEvent, state: &mut S)
        -> Result<TuiPagesOutput<A>, TuiPagesError<E>>;
    fn submit_command(&mut self, input: &str, state: &mut S)
        -> Result<TuiPagesOutput<A>, TuiPagesError<E>>;
    fn refresh_page(&mut self, state: &S);   // re-read the current page spec
    fn current_view(&self) -> &V;            // active buffer's view
    fn apply_effect(&mut self, effect: TuiEffect<V, O, M>, state: &S) -> bool;
    }

    #![allow(unused)]
    fn main() {
    pub struct TuiPagesOutput<A> {
        pub status: TuiPagesStatus<A>,
        pub quit_requested: bool,
    }

    pub enum TuiPagesStatus<A> {
        ActionHandled, TextHandled,
        Waiting(Vec<InputHint<A>>), Cancelled,
        CommandIncomplete(Vec<CommandHint>), CommandUnknown, CommandEmpty,
    }
    }

## Your handler

    #![allow(unused)]
    fn main() {
    pub trait TuiActionHandler<V, A, S, O = (), M = ()> {
        type Error;

        fn handle_action(&mut self, action: A, ctx: ActionContext<V, O>, state: &mut S)
            -> Result<ActionOutcome<V, O, M>, Self::Error>;

        // default returns ActionOutcome::none(); override for text-input pages
        fn handle_text(&mut self, chord: KeyChord, ctx: ActionContext<V, O>, state: &mut S)
            -> Result<ActionOutcome<V, O, M>, Self::Error>;
    }

    pub struct ActionContext<V, O = ()> {
        pub current_view: V,
        pub focus: Option<FocusTarget<O>>,
        pub has_overlay: bool,
    }
    }

## Effects & outcomes

    #![allow(unused)]
    fn main() {
    pub enum TuiEffect<V, O = (), M = ()> {
        None, Focus(FocusIntent<O, M>), Navigate(V),
        NextBuffer, PreviousBuffer, CloseBuffer,
        SplitPane(PaneSplit), ClosePane, NextPane, PreviousPane,
        RefreshPage, Quit,
    }

    impl ActionOutcome<V, O, M> {
        fn none() -> Self;
        fn effect(e: TuiEffect<V, O, M>) -> Self;
        fn effects(iter: impl IntoIterator<Item = TuiEffect<V, O, M>>) -> Self;
    }
    }

## Pages & focus

    #![allow(unused)]
    fn main() {
    pub struct PageSpec<O = ()> { /* see Core Concepts */ }
    impl PageSpec<O> {
        fn new() -> Self;
        fn focus(self, builder: PageFocusBuilder<O>) -> Self;   // prefer this
        fn focus_targets(self, targets: Vec<FocusTarget<O>>) -> Self;
        fn modes(self, modes: impl IntoIterator<Item = ModeId>) -> Self;
        fn accepts_text_input(self, yes: bool) -> Self;
    }

    impl PageFocusBuilder<O> {
        fn new() -> Self;
        fn button(self, index: usize) -> Self;
        fn buttons(self, indices: &[usize]) -> Self;
        fn section(self, id: usize) -> Self;
        fn section_with_items(self, id: usize, item_count: usize) -> Self;
        fn canvas_field(self, index: usize) -> Self;
        fn canvas_fields(self, count: usize) -> Self;
        fn internal_canvas_field(self, index: usize) -> Self;
        fn target(self, t: FocusTarget<O>) -> Self;
        fn build(self) -> Vec<FocusTarget<O>>;
    }

    pub enum FocusTarget<O = ()> {
        Button(usize), Section(usize), SectionItem { section: usize, item: usize },
        CanvasField(usize), InternalCanvasField(usize),
        Overlay(O), ModalItem(usize), Custom(String),
    }

    pub enum FocusIntent<O = (), M = ()> {
        Next, Prev, Activate, LeaveSection,
        Set(FocusTarget<O>), Open(FocusTarget<O>), Close(FocusTarget<O>),
        Toggle(FocusTarget<O>), ClearOverlay,
        EnterSection { item_count: usize },
        ExitCanvasForward, ExitCanvasBackward,
        ShowModal { data: M, count: usize }, UpdateModal { data: M, count: usize },
        RegisterPage(Vec<FocusTarget<O>>),
        RegisterPageAndEnterSection { targets: Vec<FocusTarget<O>>, section: usize, item_count: usize, item: usize },
    }

    pub enum FocusWrap { Clamp, Wrap }
    }

`FocusManager` — read-only from your side:

    #![allow(unused)]
    fn main() {
    fn current(&self) -> Option<FocusTarget<O>>;
    fn is_focused(&self, target: &FocusTarget<O>) -> bool;
    fn has_overlay(&self) -> bool;
    fn focus_wrap(&self) -> FocusWrap;
    fn clear_overlay(&mut self);    // used when closing an app-owned palette
    }

## Input

    #![allow(unused)]
    fn main() {
    fn parse_binding(s: &str) -> Vec<KeyChord>;                 // lenient, drops bad tokens
    fn parse_key(s: &str) -> Option<KeyChord>;
    fn try_parse_binding(s: &str) -> Result<Vec<KeyChord>, ParseKeyError>;  // strict
    fn try_parse_key(s: &str) -> Result<KeyChord, ParseKeyError>;

    impl KeyChord {
        fn from_event(event: &KeyEvent) -> Self;
        fn display_string(&self) -> String;
        pub code: KeyCode,
        pub modifiers: KeyModifiers,
    }
    }

There is no `FromStr`/`parse()` on `KeyChord` — use the functions above.

## Commands

    #![allow(unused)]
    fn main() {
    pub enum CommandResponse<A> { Execute(A), Incomplete(Vec<CommandHint>), Unknown, Empty }
    pub struct CommandHint { pub alias: String, pub action_name: String }

    impl CommandResolver<A> {           // available as tui.commands
        fn process(&self, input: &str) -> CommandResponse<A>;
        fn get_feedback(&self, input: &str) -> Option<String>;
    }
    }

## Navigation

    #![allow(unused)]
    fn main() {
    pub enum PaneSplit { Horizontal, Vertical }

    impl BufferState<V> {               // available as tui.buffer (read-only use)
        fn get_active_view(&self) -> Option<&V>;
        fn is_split(&self) -> bool;
        fn split_direction(&self) -> Option<PaneSplit>;
        fn panes(&self) -> &[PaneSession<V>];
        fn active_pane_index(&self) -> usize;
    }
    }

You drive buffers and panes through `TuiEffect`, not through these mutators.

## Dialog (feature `dialog`)

    #![allow(unused)]
    fn main() {
    pub struct DialogData<D = ()> {
        pub title: String, pub message: String,
        pub buttons: Vec<String>, pub purpose: Option<D>, pub is_loading: bool,
    }
    impl DialogData<D> {
        fn new(title, message, buttons, purpose: D) -> Self;
        fn loading(title, message) -> Self;
        fn show_intent<O>(self) -> FocusIntent<O, DialogData<D>>;
    }

    pub enum DialogResult<D> { Selected { purpose: Option<D>, index: usize }, Dismissed }
    pub enum DialogKey<D>    { Ignored, Consumed, Resolved(DialogResult<D>) }

    // helpers
    fn dialog::handle_key<O, D>(focus: &mut FocusManager<O, DialogData<D>>, key: KeyEvent) -> DialogKey<D>;
    fn dialog::current_dialog<O, D>(focus: &FocusManager<O, DialogData<D>>) -> Option<&DialogData<D>>;
    fn dialog::active_button<O, D>(focus: &FocusManager<O, DialogData<D>>) -> Option<usize>;
    fn render_dialog<D>(f: &mut Frame, area: Rect, data: &DialogData<D>, active_button: usize, theme: &DialogTheme);
    }

## Terminal

    #![allow(unused)]
    fn main() {
    fn tui_pages::terminal::enter() -> io::Result<TerminalGuard>;
    }

Enables raw mode + the alternate screen and returns a guard that restores the terminal when it drops — including on a panic.