pub struct InputWidget<'a> { /* private fields */ }Expand description
A single-line text field that only draws — an ordinary ratatui Widget
with no focus, events, or state of its own.
A themed paint adapter for ratatui-textarea.
It paints the InputState it is given: the text, scrolled to keep the
cursor in view, the cursor when focused, and any
selection. Driving the editing is the caller’s business, from the editor
paint hands back; Input is the field that does it for
you, and paints through this widget.
Implementations§
Source§impl<'a> InputWidget<'a>
impl<'a> InputWidget<'a>
Sourcepub fn new(state: &InputState) -> Self
pub fn new(state: &InputState) -> Self
A field showing state.
Sourcepub const fn style(self, style: InputStyle) -> Self
pub const fn style(self, style: InputStyle) -> Self
Use these exact colors, ignoring any theme.
Sourcepub const fn placeholder(self, placeholder: &'a str) -> Self
pub const fn placeholder(self, placeholder: &'a str) -> Self
The muted text shown while the field is empty, focused or not, where the text would start. A focused field shows its cursor on its first character.
Sourcepub fn prefix(self, prefix: impl Into<Line<'a>>) -> Self
pub fn prefix(self, prefix: impl Into<Line<'a>>) -> Self
Muted text before the editable text, inside the field: https://
before a URL, an icon before a search. Never masked; a span’s own
style paints over the muted one.
Sourcepub fn suffix(self, suffix: impl Into<Line<'a>>) -> Self
pub fn suffix(self, suffix: impl Into<Line<'a>>) -> Self
Muted text after the editable text, inside the field: a unit, a domain. Never masked; a span’s own style paints over the muted one.
Sourcepub const fn title(self, title: &'a str) -> Self
pub const fn title(self, title: &'a str) -> Self
Draw a border around the field with title on it. The field then
takes three rows instead of one.
Sourcepub const fn mask_char(self, mask_char: char) -> Self
pub const fn mask_char(self, mask_char: char) -> Self
Paint every character as mask_char, for a secret. Only the paint
changes: the state keeps the text as typed. A masked field never
copies or cuts, so the secret cannot leave it that way.
Sourcepub const fn focused(self, focused: bool) -> Self
pub const fn focused(self, focused: bool) -> Self
Paint the focused background and show the cursor.
Sourcepub const fn invalid(self, invalid: bool) -> Self
pub const fn invalid(self, invalid: bool) -> Self
Paint the text, border, and title in the invalid color.
Sourcepub fn paint(self, area: Rect, buf: &mut Buffer) -> Editor<'static>
pub fn paint(self, area: Rect, buf: &mut Buffer) -> Editor<'static>
Paint the field and hand back the editor it was painted from, which now knows the view it was drawn in: how far it is scrolled.
Rendering as a Widget throws that editor away. A loop that drives
the editing itself edits this one instead, and stores the result with
InputState::from_editor, so the next paint scrolls from what is on
screen. Which keys reach the editor is the loop’s own policy; this is
the least of one, and Input has the whole of it.
use ratatui::{buffer::Buffer, layout::Rect};
use ratcn::{
InputState, InputWidget,
runtime::{KeyCode, KeyEvent},
text_edit::{Editor, editor_input, is_editor_binding},
};
// Beside the state, the editor the last paint handed back, with the
// version of the state it was painted from.
let mut state = InputState::new("Ada Lovelace");
let mut painted: Option<(u64, Editor<'static>)> = None;
// Each frame:
let area = Rect::new(0, 0, 8, 1);
let mut buf = Buffer::empty(area);
let editor = InputWidget::new(&state).focused(true).paint(area, &mut buf);
painted = Some((state.version(), editor));
// When a key arrives:
fn on_key(
key: KeyEvent,
state: &mut InputState,
painted: &mut Option<(u64, Editor<'static>)>,
) {
match key.code {
KeyCode::Enter => { /* submit */ }
// Focus traversal, the enclosing view, and keys with nowhere to
// go on one line.
KeyCode::Tab | KeyCode::BackTab | KeyCode::Esc | KeyCode::Up | KeyCode::Down => {}
// Line breaks, shifted or not: Ctrl+J is a terminal's line feed.
KeyCode::Char('j' | 'J' | 'm' | 'M') if key.modifiers.ctrl => {}
KeyCode::Char('\n' | '\r') => {}
_ => {
if let Some(input) = editor_input(&key).filter(is_editor_binding) {
// The painted editor, while the state is still the one
// it was painted from.
let mut editor = match painted.take() {
Some((version, editor)) if version == state.version() => editor,
_ => state.editor().clone(),
};
editor.input(input);
*state = InputState::from_editor(editor);
}
}
}
}
on_key(KeyEvent::new(KeyCode::Left), &mut state, &mut painted);
assert_eq!(state.cursor(), 11);Trait Implementations§
Source§impl<'a> Debug for InputWidget<'a>
impl<'a> Debug for InputWidget<'a>
Auto Trait Implementations§
impl<'a> !Freeze for InputWidget<'a>
impl<'a> !RefUnwindSafe for InputWidget<'a>
impl<'a> !Sync for InputWidget<'a>
impl<'a> Send for InputWidget<'a>
impl<'a> Unpin for InputWidget<'a>
impl<'a> UnsafeUnpin for InputWidget<'a>
impl<'a> UnwindSafe for InputWidget<'a>
Blanket Implementations§
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<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more