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
impl Model
Sourcepub fn new() -> Self
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, " • ");
Sourcepub fn with_width(self, width: usize) -> Self
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;
Sourcepub fn update(self, _msg: Msg) -> (Self, Option<Cmd>)
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
Sourcepub fn view<K: KeyMap>(&self, keymap: &K) -> String
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
- Mode Selection: Choose between short or full help based on
show_all
- Key Filtering: Automatically skip disabled key bindings
- Styling Application: Apply configured colors and formatting
- Layout: Arrange keys and descriptions with proper spacing
- 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 theKeyMap
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());
Sourcepub fn short_help_view(&self, bindings: Vec<&Binding>) -> String
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:
- Items are added from left to right
- If an item would exceed the width, it’s skipped
- An ellipsis (“…”) is added if there’s space
- 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
Sourcepub fn full_help_view(&self, groups: Vec<Vec<&Binding>>) -> String
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
- Filtering: Skip empty groups and groups with all disabled bindings
- Row Building: Create “key description” pairs for each enabled binding
- Vertical Joining: Combine rows within each column with newlines
- Horizontal Joining: Align columns side-by-side with separators
- 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
Sourcepub fn new_model() -> Self
👎Deprecated since 0.1.11: Use Model::new() instead
pub fn new_model() -> Self
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 Default for Model
impl Default for Model
Source§fn default() -> Self
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 Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
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) -> Dwhere
M: TransformMatrix<T>,
fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
Source§fn adapt_into(self) -> D
fn adapt_into(self) -> D
Source§impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
Source§fn arrays_from(colors: C) -> T
fn arrays_from(colors: C) -> T
Source§impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
Source§fn arrays_into(self) -> C
fn arrays_into(self) -> C
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
Source§type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn cam16_into_unclamped(
self,
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> T
fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
Source§fn components_from(colors: C) -> T
fn components_from(colors: C) -> T
Source§impl<T> FromAngle<T> for T
impl<T> FromAngle<T> for T
Source§fn from_angle(angle: T) -> T
fn from_angle(angle: T) -> T
angle
.Source§impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
Source§fn from_stimulus(other: U) -> T
fn from_stimulus(other: U) -> T
other
into Self
, while performing the appropriate scaling,
rounding and clamping.Source§impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
Source§fn into_angle(self) -> U
fn into_angle(self) -> U
T
.Source§impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
Source§type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn into_cam16_unclamped(
self,
parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>,
) -> T
fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
Source§fn into_color(self) -> U
fn into_color(self) -> U
Source§impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
Source§fn into_color_unclamped(self) -> U
fn into_color_unclamped(self) -> U
Source§impl<T> IntoStimulus<T> for T
impl<T> IntoStimulus<T> for T
Source§fn into_stimulus(self) -> T
fn into_stimulus(self) -> T
self
into T
, while performing the appropriate scaling,
rounding and clamping.Source§impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
Source§type Error = <C as TryFromComponents<T>>::Error
type Error = <C as TryFromComponents<T>>::Error
try_into_colors
fails to cast.Source§fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
Source§impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
Source§fn try_into_color(self) -> Result<U, OutOfBounds<U>>
fn try_into_color(self) -> Result<U, OutOfBounds<U>>
OutOfBounds
error is returned which contains
the unclamped color. Read more