Struct Model

Source
pub struct Model {
    pub show_all: bool,
    pub width: usize,
    pub short_separator: String,
    pub full_separator: String,
    pub ellipsis: String,
    pub styles: Styles,
}
Expand description

The help model that manages help view state and rendering.

This is the main component for displaying help information in terminal applications. It can show either a compact single-line view or an expanded multi-column view based on the show_all toggle. The component handles automatic styling, width constraints, and proper alignment of key bindings.

§View Modes

§Short Help Mode (show_all = false)

Displays key bindings in a horizontal line with bullet separators:

↑/k up • ↓/j down • / filter • q quit • ? more

§Full Help Mode (show_all = true)

Displays key bindings in organized columns:

↑/k      up             / filter         q quit
↓/j      down           esc clear filter ? close help
→/l/pgdn next page      enter apply
←/h/pgup prev page

§Configuration

  • Width Constraints: Set maximum width to enable truncation with ellipsis
  • Custom Separators: Configure bullet separators and column spacing
  • Styling: Full control over colors and text formatting
  • State Management: Toggle between compact and detailed views

§Examples

§Basic Usage

use bubbletea_widgets::help::{Model, KeyMap};
use bubbletea_widgets::key::Binding;
use crossterm::event::KeyCode;

// Create key bindings
let quit_binding = Binding::new(vec![KeyCode::Char('q')])
    .with_help("q", "quit");

// Implement KeyMap for your application
struct MyApp {
    quit_binding: Binding,
}

impl KeyMap for MyApp {
    fn short_help(&self) -> Vec<&bubbletea_widgets::key::Binding> {
        vec![&self.quit_binding]
    }
    fn full_help(&self) -> Vec<Vec<&bubbletea_widgets::key::Binding>> {
        vec![vec![&self.quit_binding]]
    }
}

// Create and configure help model
let app = MyApp { quit_binding };
let help = Model::new().with_width(80);
let help_text = help.view(&app);

§Advanced Configuration

let help = Model {
    show_all: false,
    width: 120,
    short_separator: " | ".to_string(),
    full_separator: "      ".to_string(),
    ellipsis: "...".to_string(),
    styles: Default::default(),
};

§Integration with BubbleTea

// Toggle help view with '?' key
self.help.show_all = !self.help.show_all;
None
// Render help at bottom of your application view
let help_view = self.help.view(self);
format!("{}\n{}", "Your app content here", help_view)

Fields§

§show_all: bool

Toggles between short (single-line) and full (multi-column) help view. When false, shows compact help; when true, shows detailed help.

§width: usize

The maximum width of the help view in characters. When set to 0, no width limit is enforced.

§short_separator: String

The separator string used between items in the short help view. Default is “ • “ (bullet with spaces).

§full_separator: String

The separator string used between columns in the full help view. Default is “ “ (four spaces).

§ellipsis: String

The character displayed when help content is truncated due to width constraints. Default is “…” (horizontal ellipsis).

§styles: Styles

The styling configuration for all visual elements of the help view.

Implementations§

Source§

impl Model

Source

pub fn new() -> Self

Creates a new help model with default settings.

This is equivalent to calling Model::default() but provides a more conventional constructor-style API. The model is created in compact mode with no width limits and default styling.

§Default Configuration
  • show_all: false (compact view)
  • width: 0 (no width limit)
  • short_separator: " • " (bullet with spaces)
  • full_separator: " " (four spaces)
  • ellipsis: "…" (horizontal ellipsis)
  • styles: Adaptive color scheme
§Examples
use bubbletea_widgets::help::Model;

let help = Model::new();
assert_eq!(help.show_all, false);
assert_eq!(help.width, 0);
assert_eq!(help.short_separator, " • ");
Source

pub fn with_width(self, width: usize) -> Self

Sets the maximum width of the help view.

When a width is set, the help view will truncate content that exceeds this limit, showing an ellipsis to indicate truncation. This is useful for ensuring help text doesn’t overflow in constrained terminal windows or when embedding help in specific layout areas.

§Truncation Behavior
  • Short Help: Truncates items from right to left, showing ellipsis when possible
  • Full Help: Truncates columns from right to left, maintaining column integrity
  • Smart Ellipsis: Only shows ellipsis if it fits within the width constraint
§Arguments
  • width - Maximum width in characters. Use 0 for no limit.
§Examples
§Setting Width Constraints
use bubbletea_widgets::help::Model;

let help = Model::new().with_width(80);
assert_eq!(help.width, 80);

// No width limit
let unlimited = Model::new().with_width(0);
assert_eq!(unlimited.width, 0);
§Chaining with Other Configuration
let help = Model::new()
    .with_width(120);
     
// Further customize if needed
let mut customized = help;
customized.show_all = true;
Source

pub fn update(self, _msg: Msg) -> (Self, Option<Cmd>)

Updates the help model in response to a message.

This method provides compatibility with the bubbletea-rs architecture, matching the Go implementation’s Update method. Since the help component is primarily a view component that doesn’t handle user input directly, this is a no-op method that simply returns the model unchanged.

§Design Rationale

The help component is stateless from a user interaction perspective:

  • It doesn’t respond to keyboard input
  • It doesn’t maintain internal state that changes over time
  • Its display is controlled by the parent application

Parent applications typically control help display by:

  • Toggling show_all based on key presses (e.g., ‘?’ key)
  • Adjusting width in response to terminal resize events
  • Updating styling based on theme changes
§Arguments
  • _msg - The message to handle (unused for help component)
§Returns

A tuple containing:

  • The unchanged model
  • None for the command (no side effects needed)
§Examples
use bubbletea_widgets::help::Model;
use bubbletea_rs::Msg;

let help = Model::new();
// Any message can be passed, the help component ignores all messages
let msg = Box::new(42); // Example message
let (updated_help, cmd) = help.update(msg);
assert!(cmd.is_none()); // Help component doesn't generate commands
§Integration Pattern
// Parent application handles help toggling
if let Some(key_msg) = msg.downcast_ref::<KeyMsg>() {
    if key_msg.key == KeyCode::Char('?') {
        self.help.show_all = !self.help.show_all;
    }
}

// Help component itself doesn't need to process messages
let (_unchanged_help, _no_cmd) = self.help.clone().update(msg);
None
Source

pub fn view<K: KeyMap>(&self, keymap: &K) -> String

Renders the help view based on the current model state.

This is the main rendering function that switches between short and full help views based on the show_all flag. The method applies styling, handles width constraints, and formats the output appropriately for terminal display.

§Rendering Process
  1. Mode Selection: Choose between short or full help based on show_all
  2. Key Filtering: Automatically skip disabled key bindings
  3. Styling Application: Apply configured colors and formatting
  4. Layout: Arrange keys and descriptions with proper spacing
  5. Width Handling: Truncate with ellipsis if width constraints are set
§Output Formats
§Short Help (show_all = false)
↑/k up • ↓/j down • / filter • q quit
§Full Help (show_all = true)
↑/k      up         / filter    q quit
↓/j      down       esc clear   ? help
→/pgdn   next
§Arguments
  • keymap - An object implementing the KeyMap trait that provides the key bindings to display. Typically your main application model.
§Returns

A formatted string ready for display in the terminal, including ANSI color codes if styling is configured.

§Examples
§Basic Rendering
use bubbletea_widgets::help::{Model, KeyMap};
use bubbletea_widgets::key::Binding;
use crossterm::event::KeyCode;

struct MyApp {
    quit_key: Binding,
}

impl KeyMap for MyApp {
    fn short_help(&self) -> Vec<&bubbletea_widgets::key::Binding> {
        vec![&self.quit_key]
    }
    fn full_help(&self) -> Vec<Vec<&bubbletea_widgets::key::Binding>> {
        vec![vec![&self.quit_key]]
    }
}

let app = MyApp {
    quit_key: Binding::new(vec![KeyCode::Char('q')]).with_help("q", "quit")
};
let help = Model::new();
let output = help.view(&app);
§Toggling Between Modes
let mut help = Model::new();

// Render compact help
help.show_all = false;
let short = help.view(&app);

// Render detailed help
help.show_all = true;
let full = help.view(&app);

// Both modes produce valid output
assert!(!short.is_empty());
assert!(!full.is_empty());
Source

pub fn short_help_view(&self, bindings: Vec<&Binding>) -> String

Renders a compact single-line help view.

This view displays key bindings in a horizontal layout, separated by the configured separator (default: “ • “). If the content exceeds the specified width, it will be truncated with an ellipsis. This format is ideal for status bars or when screen space is limited.

§Layout Format
key1 desc1 • key2 desc2 • key3 desc3
§Truncation Behavior

When width constraints are active:

  1. Items are added from left to right
  2. If an item would exceed the width, it’s skipped
  3. An ellipsis (“…”) is added if there’s space
  4. Disabled key bindings are automatically excluded
§Arguments
  • bindings - A vector of key bindings to display in order of priority. Higher priority items should appear first as they’re less likely to be truncated.
§Returns

A single-line string containing the formatted help text with ANSI styling applied.

§Examples
§Basic Usage
use bubbletea_widgets::help::Model;
use bubbletea_widgets::key::Binding;
use crossterm::event::KeyCode;

let help = Model::new();
let quit_binding = Binding::new(vec![KeyCode::Char('q')]).with_help("q", "quit");
let help_binding = Binding::new(vec![KeyCode::Char('?')]).with_help("?", "help");
let bindings = vec![&quit_binding, &help_binding];
let output = help.short_help_view(bindings);
// Output: "q quit • ? help"
§With Width Constraints
let help = Model::new().with_width(20); // Very narrow
let quit_binding = Binding::new(vec![KeyCode::Char('q')]).with_help("q", "quit");
let help_binding = Binding::new(vec![KeyCode::Char('?')]).with_help("?", "help");
let save_binding = Binding::new(vec![KeyCode::Char('s')]).with_help("s", "save");
let bindings = vec![&quit_binding, &help_binding, &save_binding];
let output = help.short_help_view(bindings);
// Might be truncated due to width constraints
Source

pub fn full_help_view(&self, groups: Vec<Vec<&Binding>>) -> String

Renders a detailed multi-column help view.

This view organizes key bindings into columns, with each group of bindings forming a separate column. Keys and descriptions are aligned vertically within each column, and columns are separated by configurable spacing. This format provides comprehensive help information in an organized layout.

§Layout Structure
Column 1          Column 2          Column 3
key1 desc1        key4 desc4        key7 desc7
key2 desc2        key5 desc5        key8 desc8  
key3 desc3        key6 desc6
§Column Processing
  1. Filtering: Skip empty groups and groups with all disabled bindings
  2. Row Building: Create “key description” pairs for each enabled binding
  3. Vertical Joining: Combine rows within each column with newlines
  4. Horizontal Joining: Align columns side-by-side with separators
  5. Width Management: Truncate columns if width constraints are active
§Truncation Behavior

When width limits are set:

  • Columns are added left to right until width would be exceeded
  • Remaining columns are dropped entirely (maintaining column integrity)
  • An ellipsis is added if there’s space to indicate truncation
§Arguments
  • groups - A vector of key binding groups, where each group becomes a column in the output. Order matters: earlier groups have higher priority and are less likely to be truncated.
§Returns

A multi-line string containing the formatted help text with proper column alignment and ANSI styling applied.

§Examples
§Basic Multi-Column Layout
use bubbletea_widgets::help::Model;
use bubbletea_widgets::key::Binding;
use crossterm::event::KeyCode;

let help = Model::new();

// Create bindings with proper lifetimes
let up_key = Binding::new(vec![KeyCode::Up]).with_help("↑/k", "up");
let down_key = Binding::new(vec![KeyCode::Down]).with_help("↓/j", "down");
let enter_key = Binding::new(vec![KeyCode::Enter]).with_help("enter", "select");
let delete_key = Binding::new(vec![KeyCode::Delete]).with_help("del", "delete");
let quit_key = Binding::new(vec![KeyCode::Char('q')]).with_help("q", "quit");
let help_key = Binding::new(vec![KeyCode::Char('?')]).with_help("?", "help");

let groups = vec![
    // Navigation column
    vec![&up_key, &down_key],
    // Action column  
    vec![&enter_key, &delete_key],
    // App control column
    vec![&quit_key, &help_key],
];
let output = help.full_help_view(groups);
// Creates aligned columns with proper spacing
§With Custom Separator
let help = Model {
    full_separator: "  |  ".to_string(), // Custom column separator
    ..Model::new()
};
let action_key = Binding::new(vec![KeyCode::Char('a')]).with_help("a", "action");
let quit_key = Binding::new(vec![KeyCode::Char('q')]).with_help("q", "quit");
let groups = vec![
    vec![&action_key],
    vec![&quit_key],
];
let output = help.full_help_view(groups);
// Columns will be separated by "  |  "
§Handling Width Constraints
let help = Model::new().with_width(40); // Narrow width
let first_key = Binding::new(vec![KeyCode::Char('1')]).with_help("1", "first");
let second_key = Binding::new(vec![KeyCode::Char('2')]).with_help("2", "second");
let third_key = Binding::new(vec![KeyCode::Char('3')]).with_help("3", "third");
let groups = vec![
    vec![&first_key],
    vec![&second_key],
    vec![&third_key],
];
let output = help.full_help_view(groups);
// May truncate rightmost columns if they don't fit
Source

pub fn new_model() -> Self

👎Deprecated since 0.1.11: Use Model::new() instead

Creates a new help model with default settings.

Deprecated: Use Model::new instead.

This function provides backwards compatibility with earlier versions of the library and matches the Go implementation’s deprecated NewModel variable.

§Examples
use bubbletea_widgets::help::Model;

let help = Model::new_model(); // Deprecated
let help = Model::new();       // Preferred

Trait Implementations§

Source§

impl Clone for Model

Source§

fn clone(&self) -> Model

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Model

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Model

Source§

fn default() -> Self

Creates a new help model with sensible defaults.

Default configuration:

  • show_all: false (shows short help)
  • width: 0 (no width limit)
  • short_separator: “ • “
  • full_separator: “ “ (4 spaces)
  • ellipsis: “…”
  • styles: Default styles
§Examples
use bubbletea_widgets::help::Model;

let help = Model::default();
assert_eq!(help.show_all, false);
assert_eq!(help.width, 0);

Auto Trait Implementations§

§

impl Freeze for Model

§

impl !RefUnwindSafe for Model

§

impl Send for Model

§

impl Sync for Model

§

impl Unpin for Model

§

impl !UnwindSafe for Model

Blanket Implementations§

Source§

impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for S
where T: Real + Zero + Arithmetics + Clone, Swp: WhitePoint<T>, Dwp: WhitePoint<T>, D: AdaptFrom<S, Swp, Dwp, T>,

Source§

fn adapt_into_using<M>(self, method: M) -> D
where M: TransformMatrix<T>,

Convert the source color to the destination color using the specified method.
Source§

fn adapt_into(self) -> D

Convert the source color to the destination color using the bradford method by default.
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, C> ArraysFrom<C> for T
where C: IntoArrays<T>,

Source§

fn arrays_from(colors: C) -> T

Cast a collection of colors into a collection of arrays.
Source§

impl<T, C> ArraysInto<C> for T
where C: FromArrays<T>,

Source§

fn arrays_into(self) -> C

Cast this collection of arrays into a collection of colors.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
where T: FromCam16Unclamped<WpParam, U>,

Source§

type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T, C> ComponentsFrom<C> for T
where C: IntoComponents<T>,

Source§

fn components_from(colors: C) -> T

Cast a collection of colors into a collection of color components.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromAngle<T> for T

Source§

fn from_angle(angle: T) -> T

Performs a conversion from angle.
Source§

impl<T, U> FromStimulus<U> for T
where U: IntoStimulus<T>,

Source§

fn from_stimulus(other: U) -> T

Converts other into Self, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> IntoAngle<U> for T
where U: FromAngle<T>,

Source§

fn into_angle(self) -> U

Performs a conversion into T.
Source§

impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
where T: Cam16FromUnclamped<WpParam, U>,

Source§

type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, U> IntoColor<U> for T
where U: FromColor<T>,

Source§

fn into_color(self) -> U

Convert into T with values clamped to the color defined bounds Read more
Source§

impl<T, U> IntoColorUnclamped<U> for T
where U: FromColorUnclamped<T>,

Source§

fn into_color_unclamped(self) -> U

Convert into T. The resulting color might be invalid in its color space Read more
Source§

impl<T> IntoStimulus<T> for T

Source§

fn into_stimulus(self) -> T

Converts self into T, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, C> TryComponentsInto<C> for T
where C: TryFromComponents<T>,

Source§

type Error = <C as TryFromComponents<T>>::Error

The error for when try_into_colors fails to cast.
Source§

fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>

Try to cast this collection of color components into a collection of colors. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, U> TryIntoColor<U> for T
where U: TryFromColor<T>,

Source§

fn try_into_color(self) -> Result<U, OutOfBounds<U>>

Convert into T, returning ok if the color is inside of its defined range, otherwise an OutOfBounds error is returned which contains the unclamped color. Read more
Source§

impl<C, U> UintsFrom<C> for U
where C: IntoUints<U>,

Source§

fn uints_from(colors: C) -> U

Cast a collection of colors into a collection of unsigned integers.
Source§

impl<C, U> UintsInto<C> for U
where C: FromUints<U>,

Source§

fn uints_into(self) -> C

Cast this collection of unsigned integers into a collection of colors.