Expand description
intuiTUIve: a reactive, retained terminal UI framework built on rs-rich.
You describe the screen once, as a tree of nodes, and keep your state in signals. When a signal changes, the nodes that read it draw again, and only the cells that changed are sent to the terminal. There is no draw loop to write, no layout pass to call, and no “what changed” to track.
use intuituive::prelude::*;
fn main() -> std::io::Result<()> {
App::new(|| {
let count = signal(0);
column([
text!("[b]Count:[/] {count}").panel("Counter"),
label("[dim]+ adds one · q quits"),
])
.on_key("+", move |_| count.update(|c| *c += 1))
.on_key("q", |cx| cx.quit())
})
.run()
}- Nodes (
text,label,renderable,column,row,grid,each,switch,Node::panel) are built once and kept. Any rich renderable is a node: aTable,Markdown,Syntax, a chart. - Layout sizes children by
Size(fixed, percentage, flexible or their content), within minimums and maximums, with gaps and padding. - State is
signals andmemos. Reading one while drawing subscribes the node; writing one redraws exactly its readers. - Input:
Node::on_keybindings bubble from the focused node up; Tab moves the focus;Node::on_clickgets clicks, routed by the layout the last frame kept. - Screens:
Ctx::push,Ctx::modalandCtx::popkeep a stack of screens, each with its own state and focus. - Background work:
spawn,spawn_futureandresourcerun slow work off the app’s thread and write signals with the result; aProxylets any thread do the same. - Themes:
Themestyles the framework’s parts and names styles for markup;Ctx::set_themeswitches at run time. - Inline:
App::inlineruns in a few rows below the prompt instead of the alternate screen. - Responsive:
Node::hide_belowand a stylesheet’s@mediarules follow the terminal’s size;viewportreads it. - The outside world, behind off-by-default features (plugins: the
core stays generic):
audio::pcmreads raw PCM a buffer at a time,audio::playplays it at its rate andaudio::Capture::simulatedstands in for a sound card in tests (pcm),audio::inputcaptures a sound card into a signal (audio, with PulseAudio sources underpulse),audio::wavreads and records WAV files (wav),watch_pathwakes the app when files change (watch),imagedraws an image file in half blocks (art),meter,sparkline,spectrogramandbar_spectrumshow levels and spectra (viz), andfileshas a file manager’s components: Miller columns, file lists, previews, background file jobs and a streaming finder (files). - Generic building blocks:
miller_of(Miller columns over anyMillerSourcetree),jobsandjobs_panel(cancellable work with progress),fuzzy_listandfinder_of(a fuzzy list over any stream of items),preview_of(a value loaded off the app’s thread for the current key),multi_select(a selection by key with a visual range),list_search(find next and previous over a list),tab_set(tabs’ states with one active),facts(a description list),digits(big digits in any build), andstate’s files andFrecencyStore(an app’s state between sessions). The core is generic only; the domain plugins above build on these. - Sprites and pixels:
sprite::stagedrawssprite::Sprites (cell art with transparent cells, animated on the app’s clock) over a backdrop, with clicks, hovers and collisions by their cells;pixels::pixelsis an RGBA framebuffer drawn in half blocks, quadrants or Braille, with blits, rectangles and lines. Plugins cut an image into sprites (sprite_sheet, behindart) and make rs-rich-micro’s micro assets sprites (micro_sprite, behindmicro). - Tests:
App::render_withandApp::run_onwithrich-interact’s headless driver run an app without a terminal;App::driversteps one, andassert_screen!compares its screen with a snapshot (seetesting).
The design, and how it compares with ratatui, is in
docs/design/intuituive.md.
Re-exports§
pub use app::DEFAULT_MODE;pub use app::Anchor;pub use app::App;pub use app::Ctx;pub use app::Driver;pub use app::Easing;pub use app::FrameStats;pub use app::Handoff;pub use app::Holds;pub use app::ModalOptions;pub use app::Placement;pub use app::StatsHandle;pub use app::Theme;pub use app::Timer;pub use app::after;pub use app::every;pub use app::fixed_step;pub use app::held_keys;pub use app::plain_key;pub use app::rate;pub use border::Border;pub use border::BorderSet;pub use border::Edge;pub use border::Shadow;pub use border::Sides;pub use command_line::CommandLine;pub use command_line::CommandLineOptions;pub use command_line::command_line;pub use command_line::command_line_with;pub use complete::CompleteOptions;pub use complete::Completion;pub use complete::InputHistory;pub use complete::complete_words;pub use complete::history_file;pub use complete::history_in;pub use complete::history_session;pub use finder::FuzzyOptions;pub use finder::FuzzySource;pub use finder::finder_of;pub use finder::fuzzy_list;pub use finder::fuzzy_list_with;pub use focus::Direction;pub use fx::Fx;pub use jobs::Job;pub use jobs::JobOutcome;pub use jobs::JobProgress;pub use jobs::JobState;pub use jobs::Jobs;pub use jobs::JobsPanelOptions;pub use jobs::ProcessOutcome;pub use jobs::ProcessOutput;pub use jobs::jobs;pub use jobs::jobs_panel;pub use jobs::jobs_panel_with;pub use layout::Align;pub use layout::AlignContent;pub use layout::Justify;pub use layout::Size;pub use layout::StackLayout;pub use layout::TextAlign;pub use log::Log;pub use miller::MillerSource;pub use miller::miller_in;pub use miller::miller_of;pub use node::Node;pub use node::column;pub use node::component;pub use node::each;pub use node::fit_text;pub use node::grid;pub use node::keyed;pub use node::label;pub use node::layers;pub use node::leaf;pub use node::list;pub use node::renderable;pub use node::repeating;pub use node::row;pub use node::scroll;pub use node::scroll_both;pub use node::scroll_both_with;pub use node::scroll_with;pub use node::scroll_x;pub use node::switch;pub use node::text;pub use node::described;pub use node::drawn;pub use node::drawn_described;pub use preview::PreviewOfOptions;pub use preview::preview_of;pub use preview::preview_of_with;pub use reactive::Memo;pub use reactive::Proxy;pub use reactive::Signal;pub use reactive::memo;pub use reactive::on_write;pub use reactive::on_write_ref;pub use reactive::signal;pub use reactive::viewport;pub use reactive::watch;pub use select::ListSearch;pub use select::Mark;pub use select::MultiSelect;pub use select::list_search;pub use select::multi_select;pub use state::FrecencyStore;pub use state::frecency_in;pub use state::frecency_session;pub use state::frecency_store;pub use state::read_state;pub use state::state_dir;pub use state::state_file;pub use state::update_file;pub use state::update_state;pub use state::write_atomic;pub use state::write_state;pub use tab_set::Scoped;pub use tab_set::TabSet;pub use tab_set::tab_set;pub use tab_set::tabs_for;pub use tab_set::tabs_for_indexed;pub use task::Latest;pub use task::Load;pub use task::Notifier;pub use task::Resource;pub use task::Stream;pub use task::Task;pub use task::latest;pub use task::latest_every;pub use task::resource;pub use task::resource_for;pub use task::spawn;pub use task::spawn_future;pub use task::spawn_stream;pub use task::spawn_then;pub use text_edit::TextSearch;pub use text_edit::search_bar;pub use transport::Transport;pub use transport::transport;pub use widget::Widget;pub use widget::widget;pub use widgets::text_area;pub use rich;pub use rich_interact as interact;
Modules§
- a11y
- Accessibility: what each node is (its
Role) and is called, the tree a screen reader bridge or a browser reads (Driver::accessibility), announcements (Announcer), and the text mode an accessible app draws in. - app
- The app: the tree, its runtime, and the loop that runs them.
- audio
- Sound in and out: a sound card captured into a signal, raw PCM and WAV
files read a buffer at a time, and what is shown recorded to a WAV. A
plugin, not core: the module is there only with the off-by-default
pcmfeature, whichaudioandwavturn on. - banner
- An animated banner: rs-rich-art’s
AnimatedBannerplayed on the app’s clock. - border
- Borders: the kinds of box a panel draws, the sides it draws, titles on its edges and its shadow; and the table of glyphs that join lines where they meet, for collapsed borders.
- command_
line - A command line:
command_line, a bar of one or two rows that opens in aMode(vim’s:command, a/search, a filter that follows each key), asks yes or no in place (CommandLine::confirm), and says what went wrong in red. Its input completes and keeps a history as anyinput’s. Generic: taskwarrior-tui’s command bar, Yazi’s and lazygit’s prompts are modes of it. - complete
- Help for an
inputas it is typed: completion (a pop-up list of candidates and the top one’s rest as ghost text), fromNode::complete, and a history of what was entered (Up and Down), fromNode::history, kept for the session or in the app’s state between sessions. Generic: the candidates are the app’s (a command’s arguments, field names, dates, paths). - dates
- Dates as people type them (
tomorrow,eow,3d): rs-rich-interact’s. Dates as people type them:tomorrow,eow,monday,3d,2026-11-01, read relative to a given now. Generic: a todo list’s due dates, a log viewer’ssince, a calendar’s jump; the names are Taskwarrior’s, which most such tools share. - files
- A file manager’s components, behind the off-by-default
filesfeature: what rebuilding Yazi by hand (examples/files.rs) took a few hundred lines each to write. A plugin: each component with a generic shape underneath is that core component with a file system plugged in (milleronmiller_of,tasksonjobs,finderonfuzzy_list,previewonpreview_of,tabsontab_set,selectiononmulti_select,path_crumbonbreadcrumb). - finder
- A fuzzy list over any source of items, whose results stream in:
fuzzy_list, andfinder_ofon it over an iterator. - focus
- Where the focus is, as state, and where it goes next by geometry: the
reactive reads
focusedandhas_focus,DirectionforCtx::focus_direction, and the pureneighboursearch under it, for widgets that place parts of their own. - fx
- Ready-made effects, timed and composable: fades, dissolves, sweeps, slides, colour shifts, a glitch, digital rain, a shimmer over text and a pulsing skeleton for what is loading.
- inspect
- The inspector: a panel docked on the right of a running app that shows the node tree as it is, which nodes drew in the last frame, where the focus is, what each frame and each node cost, and what happened in the app.
- jobs
- Cancellable background jobs with progress, and a panel listing them: a task manager for any work (copies, downloads, builds, exports).
- layout
- Layout: how a container shares its space among its children.
- log
- A streaming log: lines arrive at the bottom, older ones scroll up.
- menu
- Menus: a
menu_bar, the drop-down menus it opens, and context menus (context_menu) at the mouse pointer. All are built on the publicWidgettrait and pop-ups. - micro_
sprite - rs-rich-micro’s micro assets as sprites: an emoji-sized image or
animation, fitted to its cells in half blocks, for a
stage. Behind the off-by-defaultmicrofeature. - miller
- Miller columns over any tree: the level above, the level the cursor is in and a preview of the hovered item, over one cursor.
- node
- Nodes: the retained tree an app is made of.
- pixels
- Pixel buffers: an RGBA framebuffer drawn in terminal cells.
- prelude
- Everything an app usually needs.
- preview
- A pane that loads a value off the app’s thread for whatever key is current, drops the results for keys left behind, and draws the value.
- query
- A query language over records: what a filter box, a search line or a
command bar reads.
parsereads a text by aGrammar(the field names, their aliases and value types, how bare words match) into aQuery, andQuery::matchestests anyRecord. Generic: a todo list’sproject:home +next due.before:eow, a process list’scpu > 5 and name:fire, a log’slevel:error or "timed out"are each a grammar, not core code. - reactive
- Reactive state: signals, memos, and the per-app runtime behind them.
- screen
- The cell screen: what the terminal shows, kept between frames.
- select
- Picking items of a list:
multi_select, a selection by key with a visual range, andlist_search, find next and previous over a list’s items. - source
- Rows from a source:
TableSource, what a table asks for its rows by index (a file indexed in the background, a database cursor, a log), asource_tableover one, andview_of, a source filtered, sorted and searched on a background task, whose result is a source itself. - sprite
- Sprites and stages: cell art placed, moved and animated over a backdrop.
- sprite_
sheet - Sprite sheets: an image cut into tiles, each a
PixelSprite(for aPixelBuf) or a half-blockSprite(for astage). Behind the off-by-defaultartfeature: the image is decoded by rs-rich-art’simage. - state
- State an app keeps between sessions, in small files of its own:
state_dir(where, by platform),write_stateandread_state(written whole and renamed into place, so a crash never leaves half of one),update_state(read, change and write under a lock, so two sessions do not clobber each other), and aFrecencyStoreof keys ranked by how often and how lately they were used. Generic: keyed by an app’s name and a file name, holding bytes or strings. - tab_set
- A set of tabs’ states with one active:
tab_set, the model atabsstrip shows. - task
- Background work: run something slow off the app’s thread, and write signals with its result when it is done.
- testing
- Snapshot assertions for headless app tests.
- text_
edit - The text editors’ editing options: rebindable keys and presets, a
modal preset’s hook, search with a find bar, word wrap, the cursor line,
the caret’s shape, tabs, the undo history and an input’s validation
message. Builders on
Nodefor atext_areaor aninput; on any other node they do nothing. - timedemo
- A timedemo: replay input against an app as fast as it can draw, and report what each frame cost.
- transport
- A play head on the app’s clock:
transport, what a media player, a slideshow, an animation’s timeline or a replay moves through. - vim
- Vim’s keys for the text editors (the off-by-default
vimfeature):Node::vimgives atext_areaor aninputrs-rich-interact’sVimpreset, a key mode with normal, insert and visual modes, motions, operators, counts and.. - widget
- Widgets: what every node is made of, and how to write your own with the same powers the built-in nodes have.
- widgets
- Ready-made widgets, built on the public
Widgettrait as an app’s own would be: atablewith a selectable row and sized columns, avirtual_listof any length, atabsstrip, atree,splitpanes, acalendar, atime_picker, adatetime_picker, ahex_viewand an interactivediff_view.
Macros§
- assert_
screen - Assert that a screen matches its snapshot:
tests/snapshots/<name>.txtunder the crate being tested, the screen’s plain rows. The screen is aDriver, aScreenor the rowsApp::render_withreturns. SetUPDATE_SNAPSHOTS=1to write the file instead. Seetesting. - assert_
screen_ styled assert_screen!, and the screen’s styled rows againsttests/snapshots/<name>.styled.txt: each row as console markup, so a change of colour or text style fails too. The screen is aDriveror aScreen.- assert_
screen_ svg - Assert that a screen’s styled rows match
tests/snapshots/<name>.styled.txt, keeping its SVG picture as<name>.svgbeside it; on a difference, an HTML report shows both pictures (seecheck_svg_snapshot). The screen is aDriveror aScreen. SetUPDATE_SNAPSHOTS=1to write both files. - text
- Console markup with
format!arguments, read again whenever a signal it names changes:text!("{count} items"). Signals format as their value.
Structs§
- Action
- An action an
action_overlaylists: what identifies it (id), what it says (label), the keys shown as its shortcut, and why it cannot run now, when it cannot. - Confirm
Options - How a
confirm_withdialog looks: its size (50 cells wide and as tall as its content by default) and its title’s style (the theme’spopup.titleby default). - Editor
Theme - A text area’s look: each part a style, or
Nonefor the app theme’s. - Feed
- A feed as one value: the newest value a thread sent
(
value) and how the thread is doing (state), aslatest_with_stategives them apart.Copy; made bylatest_feedorPlay::feed, or from the pair (Feed::from((value, state))). One type for every source an app switches between: a device, a file played, a generator, a socket. - Feed
Teller - Tells a feed’s state from its thread, in order with its values: the
second argument of a
latest_feedthread. - Help
Options - How
Ctx::help_withshows the help: its title, how it says keys (KeyFormat), and whether it lists every binding in one list under its search line (Yazi’s layout) rather than under a heading for each section. Rows too long for the help wrap, whatever the options. - History
- Back and forward through the values a signal has had, as a browser’s
history, a pager’s or a file manager’s:
historymakes one. ACopyhandle, as a signal is. - Hit
- One result of a palette search: what identifies it, what it says, its help line, its shortcut, its score (higher first) and the characters of its label that matched (highlighted), and what choosing it does.
- HitSink
- Where a
Providersends its hits for one search. It may be cloned and sent to another thread. - Image
View - How a picture is drawn in its cells.
- KeyHints
Options - How
key_hints_withshows the keys that work now: each hint’s text, how keys are said, whether bindings that do not apply now are shown greyed, the separator, and a “more” that expands the footer onto as many rows as it needs. - Lockstep
- How
stepped_worker_withpaces its worker. - Markdown
Heading - A heading of the document shown: its level (1 for
#), its text, its anchor (#install) and the block it starts. - Markdown
Stream - A handle that appends to a
markdownnode’s document from anywhere: a task, a thread reading an agent’s reply, aProxy.CloneandSend. Fragments that arrive faster than the app turns its loop are joined, and reach the document together, once a turn: the node then splits again only its last block, and renders and draws only the blocks that changed. - Markdown
Viewer - A Markdown viewer: build its node with
view, and steer it from anywhere on the app’s thread withgo,backandforward.Clone: each clone is the same viewer. - Offset
- How a pop-up is moved from its
Origin, and its size:xandycells (negative: left and up),wxhas a modal sizes itself (Size::Fixedcells, aSize::Percentof the screen,Size::Autothe content’s,Size::Flexthe whole screen). Whatever the offset, the pop-up stays on the screen: it is moved back inside, and made smaller if it is larger. - Paint
Stats - What the last
Painter::paintdid, counted as notcurses counts a render: the cells it looked at and wrote, and its bytes by kind. The bytes add up to the length of what it returned. - Palette
- The semantic colours of a theme, as Textual’s themes give them: from
these a
Themegenerates its shades (Theme::from_palette). Onlyprimaryis needed;secondary,warningandaccentdefault to it,errorandsuccesstosecondary,backgroundandsurfaceto Textual’s dark (#121212,#1e1e1e) or light (#efefef,#f5f5f5) ones, andforegroundto the background’s inverse. - Path
Change - One changed path in a
PathEvent. - Path
Event - The changes a watcher gathered over one debounce interval: each path
once, in the order it first changed, with what last happened to it (a
path created and then written is still
Created). - Path
Watch - A running watcher (see
watch_path). It runs as long as the app;stopends it sooner. Dropping the handle does not stop it, so an app may ignore the handle. Two handles are equal when they are handles of the same watcher, so they can be kept in a signal. - Pick
Options - The size and title style of a
pick_withmenu. - Picture
- A decoded picture, with the id terminal graphics know it by.
- Play
- An iterator to play onto a signal:
latest_itermakes it, andsignal,with_state,thenorthen_withstarts it;then_atadds a tail at a pace of its own. - Prompt
Options - Where a
prompt_withopens, its caret, its title’s style, and what hears each edit and Esc. - Rect
Handle - Where a node is on the screen, as the last frame laid it out:
Node::rect_handle, orRectHandle::newgiven to a node later withNode::rect_into. Reading it withgetsubscribes, so what reads it draws again when the node moves. Two handles are equal when they are the same handle, so one can be kept in a signal. - Select
Option - One option of a
select_field_keyedor aradio_keyed: what identifies it (key), what it says (label, console markup), and whether it may be chosen. A disabled option is shown, greyed, with itsreason, and keys, clicks and typing pass it by. - Sheet
Error - Where a stylesheet stopped parsing, and why.
- Steps
- The worker’s side of a
stepped_worker:waitfor ticks,publishoutput. Dropping it (the worker’s function returning, or panicking) tells the app the worker has ended. - Stylesheet
- A parsed stylesheet: give it to
App::stylesheet. - System
Commands - The commands the palette offers on its own, after Textual’s
App.get_system_commands: Theme (a picker ofThemes), Keys (shows or hides thekey_panel, or opens the help when there is none), Maximize or Minimize (the focused pane), Screenshot and Quit. All are on unless turned off: - Themes
- The built-in themes (
Theme::builtin_names) as a provider: choosing one switches the app to it. The palette’s Theme command opens a palette of it. - Treemap
Options - How a
treemap_withlays its tiles out: the smallest tile, a cell’s shape, and the node for the items too small for a tile of their own. - Watch
Options - How
watch_path_withwatches.
Enums§
- Button
Variant - A button’s look: which theme styles its face comes from.
- Caret
- Where the caret of an
inputor atext_areagoes when its text is set (when it is made, and when the signal is set from elsewhere):Node::caret. Positions count characters (grapheme clusters), a line break as one. - Change
Kind - What happened to a path.
- Check
State - A check box’s state: ticked, clear, or mixed, the state of a parent
whose children are partly ticked (a folder of files, a group of
permissions). Drawn
[x],[ ]and[-]; assistive technology reads checked, not checked and mixed (ARIA’saria-checked="mixed"). - Corner
- The corner of the screen toasts stack in, newest nearest the corner:
App::toasts_at. Bottom right by default; Yazi’s are top right. - Feed
State - How a thread feeding a signal is doing:
latest_with_state’s second signal. - Image
Anchor - Which part of the image to retain when using
ImageFit::Cover. - Image
Fit - How an image fills an explicit rectangle of terminal cells.
- Image
Mode - Which backend renders the image.
- KeyFormat
- How the help says a binding’s keys.
- Level
- How much a notification matters: its title and
border are in the theme’s
notify.info,notify.warnornotify.errorstyle, else itsaccent,warnorbad. - Origin
- The point of the screen a pop-up is placed
from, before its
Offsetmoves it: a corner, the middle of an edge, the centre, or a rectangle (a node’s, fromNode::rect_handle), below which it goes, or above when there is no room below. Yazi’sOrigin. - Overflow
- What a text does with what does not fit a line: rich’s.
What to do with text that is wider than the space available.
Mirrors
rich.console.OverflowMethod. - Pace
- How fast
latest_iterplays its values. - Paint
Strategy - How a
Painterturns a frame’s changes into bytes. - Pixels
- How a picture reaches the terminal.
- Placeholder
Variant - What a
placeholdershows. - Solver
- How a
columnorrowshares its length among its children:Node::solver. - Status
- What a
collapsibleshows beside its title, at the right of the header:Node::status.
Traits§
- Count
- How many: a number, or a signal or memo of one that may change.
- FeedEnd
- What a
latest_with_statethread’s end means:()(orOk(())) isFeedState::Ended, anErrFeedState::Failedwith its message. - Provider
- Something that offers the command palette
Hits: Textual’sProvider. Register one withApp::provider, or open a palette of it alone withCtx::palette_of. - Scaled
- A variant of a
bind_scaledbinding: the modifiers that make its keys, its value, and how the help says it.("shift", 10.0)is listedshift ×10;("alt", 0.2, "⅕")is listedalt ⅕. - Stepped
- A number
bind_stepcan move: the integer and float types.
Functions§
- action_
overlay - A palette of the actions
actionsreturns, read again whenever a signal it reads changes, so actions come, go and change their labels while it is open, the focus staying on the same id. Choosing one (Enter or a click) closes it and callsrunwith the action’s id, after readingactionsonce more: one gone, or unavailable, by then is not run. Escape closes it. Open it as a modal, asCtx::action_palettedoes, so the focus comes back where it was and no key reaches the screen beneath. - bar_
spectrum - A bar spectrum of
bands, a closure that may read signals: rs-rich-ext’sBarSpectrum, a column per band rising from the bottom, as tall as the node, as cava draws. Feed it rs-rich-ext’sdsp::bandsof a spectrum, through adsp::Fallofffor cava’s falling bars, or the core’ssmoothedfor each. Its accessible name says the bands’ range and the loudest. - bar_
spectrum_ with - A
bar_spectrumwhoseBarSpectrumconfiguresets up (.mirror(true),.range(1.0),.bar_width(2),.gap(1),.style("green")). For two channels, make the node withdescribedandBarSpectrum::stereo(left, right). - big_
text - Console markup in FIGlet letters (rs-rich-art’s bundled
standardfont, six rows a line), from a closure that may read signals: a large clock, a level readout, a title. Each run of the markup keeps its style ("[green]12[/]:[red]34"), so letters of different styles do not smush into each other as FIGlet’s do within a run; each line of the markup is a line of letters. What does not fit the width is cut. Its accessible name is the text itself. - button
- A button labelled
label(console markup) that runson_presswhen it is pressed: Enter or Space while it has the focus, or a click (a press let go over it). Its face is the theme’sbuttonstyle, or another variant’s (Node::variant); it looks picked while it has the focus or the pointer, and pressed ([Save]) while the mouse holds it. Three rows tall, it draws lit top and shaded bottom edges when the theme names their colours.Node::disabled_whengreys it out and stops it. Its role isButton, named by its label. - button_
of - A
buttonwhose label is read fromlabel, a closure that may read signals: Play that becomes Pause, a count, a job’s state. A change draws it again, and lays it out again when its width changes. It stays the same node: it keeps the focus, and a press the mouse holds, while its label changes, and its accessible name follows the label. - checkbox
- A check box labelled
label(console markup), ticked whileonholds:[x] Wrap lines. Space, Enter or a click ticks it or clears it. The tick is drawn in the theme’scheckbox.onstyle (elseaccent). Its role isCheckBox, named by its label, with its checked state.checkbox_trihas a third, mixed state, andcheckbox_ofa label that changes. - checkbox_
of - A
checkbox_triwhose label is read fromlabel, a closure that may read signals (3 of 5 chosen). The node, its focus and its state stay as the label changes, and its accessible name follows it. - checkbox_
tri - A check box of three states, labelled
label(console markup), in the statestateholds:[x]on,[ ]off,[-]mixed. Space, Enter or a click turn it off from on and on from off; from mixed they turn it on, or whatNode::on_mixedsays. Only code sets it mixed: a parent that sums up its children. Read as checked, not checked, or mixed. - collapsible
- A section titled
title(console markup) overchild, shown whileopenholds: a header with a disclosure marker,▾ Advancedopen and▸ Advancedclosed ([-]and[+]in text mode). Enter, Space or a click on the header opens or closes it; → opens it and ← closes it. Closed, the child takes no room and leaves the Tab order. The title is drawn in the theme’scollapsible.titlestyle (elsebold), withcontrol.focusover it while the header has the focus. The header’s role isButton, named by the title, with its expanded state. The section is as tall as what it shows.collapsible_withtakes a title that follows state; both take a status, a summary and their own markers. - collapsible_
with collapsible, titled bytitle, read again whenever a signal it reads changes: only the header draws again. With a status at the right of the header and a summary under it while it is closed, it is a tool call’s card: the tool and its argument, running then done or failed, and the output’s last line.- digits
- Console markup drawn three rows tall in box-drawing glyphs, from a
closure that may read signals: a clock, a counter, a readout, as
Textual’s
Digits. It has glyphs for0-9,A-G(anda-g: hex digits, and the notes with#),+ - = / % ( ) : . , #and the space; any other character is drawn as it is, on the middle row. Each run of the markup keeps its style ("[green]12[/]:[red]34"); each line of the markup is three rows. It needs no font, so it works in every build, wherebig_textneeds theartfeature. A glyph that does not fit the width is left out. Its accessible name is the text. - effect
- A node that shows
child, then runsfover what it drew: a highlight, a badge, a transition.fgets the canvas, which holds whatchilddrew (read it withCanvas::cell), and the drawing context, asWidget::draw_overdoes. It runs whenever the effect or anything inside it drew, and always over whatchilddrew afresh, so an effect that moves cells or changes them by what they are comes out the same each time. Signalsfreads draw the whole effect again when they change. - facts
- A description list: each key (console markup) in a column as wide as
the widest (at most half the width), its value (console markup) beside
it, wrapped under itself when it is long: a file’s details, a
process’s, a record’s fields (Yazi’s spotter, a
DataTableof two columns in Textual). The keys are in the theme’sfacts.keystyle (bold), orkey_style’s, under their own markup; the values in the theme’sfacts.value(none), orvalue_style’s, a row’s own fromvalue_style_forover it. SizedSize::Auto, it is as tall as its rows and as wide as its widest. Read aloud askey: valuepairs. - facts_
of factsfrom a closure, which may read signals: the details of whatever is hovered.- falling
- A number that follows
sourceup at once and falls back withgravity(in units a second, a second): it falls slowly at first and faster and faster, as a level meter’s bar or peak, cava’s bars, or a badge’s glow fading. It never falls belowsource, and stops once it is there. Steps a frame at a time on the app’s clock while it falls. - fill
- A node that fills its area with
symbol(one grapheme; a wide one is fine) instyle(a style or a theme style’s name): ratatui’sFill. It takes all the room it is given. - header
- The app’s title and the top screen’s
subtitle centred on a row, as Textual’s
Header:Title — subtitle, in the theme’sheaderstyle (reverseby default).clockadds the time (UTC,HH:MM:SS, moving with the app’s clock) on the right;tallmakes it three rows tall. A click toggles tall, as Textual’s does. - history
- Keep track of the values
sourcetakes, so aHistorycan gobackto an earlier one andforwardagain. Each change ofsource(as awatchsees it: an equal value is no change) after the one shown drops those after it, as a browser does after going back; a history’s own moves are not recorded. - image
- The image file at
path, drawn in half blocks to fit the node. Showsloading…while the file is decoded, and the error if it cannot be. Call it while the app is built or running. - image_
bytes - The image in
bytes(a PNG, a JPEG, any format rs-rich-art reads), drawn asviewsays: a cover embedded in a song, a picture from a network or an archive. Decoded on a worker thread, as a file is. - image_
bytes_ of - An image node following
bytes, a closure that may read signals (the cover of the track playing): a new picture is decoded when it returns other bytes (anotherArc),Nonedraws nothing. - image_
graphics - The graphics source that draws pictures’ pixels
(
ImageView::pixels): give it toApp::graphics. After each frame’s cells it finds the pictures’ tagged cells (image nodes’,picture_of’s, and any drawn withPicture::lines) and draws them over the cells (Sixel, iTerm2) or uploads them for their placeholders (Kitty), only when one is new, moved, a new frame, or had cells written under it. The Kitty pictures are freed when the app ends. - image_
of - An image node following
path, a closure that may read signals: when the path it returns changes, the new file is decoded in the background (a result for a path already left behind is dropped).Nonedraws nothing. - image_
with imagedrawn asviewsays: another cell mode, a fit, a background.- input
- A single-line text box bound to
text, both ways: what is typed is set on the signal, and text set on the signal from elsewhere replaces what the box holds. It is atext_areain a single-line mode: the same editing keys, undo, selection and mouse, but Enter submits rather than starting a line (toon_submit, else to the app’s bindings), Tab moves the focus on, pasted line breaks become spaces, and a long line scrolls sideways to the caret. - key_
panel - A panel of the keys that work now, one a row (
key description), following the focus askey_hintsdoes: each described binding of the focused node and its ancestors, innermost first, those whose condition does not hold greyed. They are grouped by the help’s sections (a binding’ssection, else its node’s name) under a heading each, in the theme’skey_panel.sectionstyle. Textual’sKeyPanel, for the right of a layout; 30 cells wide unless sized.Ctx::toggle_key_panelhides and shows it. - latest_
feed latest_with_stateas oneFeed, its thread also given aFeedTellerto say how it is doing before it ends:Endedwhen a file has run out but silence plays on,Failedon a read error it pads over,Runningagain once a device is back.- latest_
iter - Play
valuesonto a signal on a thread of its own, atpace: a recording played back, a demo’s script, frames of a file. Then something after: another iterator at the same pace (then: a fallback, silence forever) or at its own (then_at), or a closure with the thread’sLatest(then_with); or nothing (signal), and the signal keeps the last value.with_statealso says whenvaluesran out. - latest_
with_ state latest, with a second signal saying how its thread is doing (FeedState):Running;Stalledonce no value has come forstall_after(None: never), until the next comes;Endedwhenrunreturns()orOk(());Failedwhen it returns anErr(its message) or panics. Any thread: a sensor, a log’s tail, a socket, a capture. Stalls are timed on the app’s clock.- link
- Text that can take the focus and opens
url(through the system’s opener, rs-rich-ext’sopen::system_opener) on Enter or a click, as Textual’sLinkdoes. It is drawn in the theme’slinkstyle (underlined by default) and is an OSC 8 hyperlink where the terminal has them.on_activateruns an action instead;open_withopens the URL another way (a test’s stub). - list_of
- A list of
len()rows, each the nodebuild_row(i)makes (any nodes: a card, a row with a label and a button), with the cursor onselected. ↑/↓, Home/End and PgUp/PgDn move it, skipping disabled rows, and keep it in view (scroll_paddingrows either side); Enter or a click on a row selects it, unless a node inside the row took the click (a button in a card runs the button). The wheel scrolls the view. - list_
of_ virtual - A
list_ofthat builds only the rows near the view, onscroll_virtual: for long lists. Rowiis estimatedheight_of(i)lines tall (a separator adds one) until it is drawn and measured. It takes the same keys and options aslist_of(item_key,separator_after,item_disabled_when,on_select,on_highlight,on_context,scroll_padding); a row’s state goes with it once it leaves the view, as inscroll_virtual. - list_
optional - A
listwhose selection may be empty, as ratatui’sListState::select(None):Noneshows no highlight, ↓ (or Home) then selects the first item and ↑ (or End) the last. Setting the signal toNoneclears the selection. - markdown
- Markdown
docholds (CommonMark, as rs-rich’sMarkdownreads it), drawn at the node’s width and as tall as it needs: headings, paragraphs, lists, quotes, tables and fenced code, highlighted. Kept as blocks, so a document that grows at its end (an answer streaming in, through aMarkdownStream) renders and draws again only its last block. A block with links takes the focus: Tab and Shift+Tab go through its links (then on), the focused link is drawn reversed, and Enter or a click on one callson_linkwith its URL. - markdown_
viewer - A
MarkdownViewerwhose documentsloadreads: given a location (a path relative to the documents’ root, as links name them, without its#anchor), the text, or an error, which the viewer shows in place of the document. It runs off the app’s thread. Call it while the app is built or running. - masked_
input - A text box that keeps to
template, as Textual’sMaskedInput:9a digit,0an optional digit,A/aa letter (required, optional),N/na letter or digit,X/xany character,>and<upper or lower case for what follows (!neither),\a template character as it is, anything else a fixed separator, and;cat the end the blank shown in an empty slot (a space by default). The caret skips the separators, typing fills the next slot that takes the character, and Backspace clears the slot before it.valueholds the text as shown, separators included, up to the last slot typed. The node is in error (:invalid) while some but not all required slots are filled. - meter
- A level meter: rs-rich-ext’s
LevelMetershowinglevelwith a mark atpeak, both closures that may read signals, as a VU or peak meter per channel beside a scope. Across, one row: a bar green to red, the peak’s mark, and withholda second mark that keeps the highest peak for a while. Its accessible name says the level, the peaks and the band (Level meter L: 0.5, 50 percent, …). - meter_
with - A
meterwhoseLevelMeterconfiguresets up (.label("L"),.readout(true),.scale(MeterScale::Decibels { floor: -60.0 }),.orientation(Orientation::Vertical)): it is given one showing the level and peak, and returns it changed. - number_
input - A whole number in
range, bound tovalueboth ways. ↑ and ↓ (or+and-after a digit) step it bystep, PgUp and PgDn by ten steps, Home and End go to the ends, and the wheel steps it. Digits type a new number (a-first for a negative one), Backspace takes one off, and Esc puts back the value. What is typed is set on the signal at once, kept in the range, and shown as typed until Enter or the focus leaves, when it shows the value. - persistence
- A trace’s last frames drawn together, each older one fainter, as an
analogue scope’s phosphor (xoscope’s persistence): rs-rich-ext’s
Persistenceon aChart, fromframes, a closure that may read signals and returns the frames, oldest first, each a trace’s points. Keep them with the core’srecent(recent(trace, 8)) orrecent_of. The axes span the points (-1 to 1 up the side while they are all within it); the newest frame is drawn on top. - persistence_
with - A
persistencewhosePersistencetracesets up (.style(..),.fade(..),.background(..),.marker(..)) and whoseChartchartsets up (its axes’ bounds and labels, a legend), each given one made from the frames. - picture_
bytes - The bytes the terminal has been sent to draw picture
id(every frame of it) so far, as the painter counted them (count_picture_bytes): what a moving picture costs. A picture drawn in cells costs its cells, which the painter sends as text, and counts nothing here. - picture_
of - A node showing the picture
picturereturns, a closure that may read signals: each new frame (a video’s, an emulator’s screen) is drawn at once, with no worker and no “loading” step, and a frame of the same picture (Picture::next) keeps its id, so Kitty replaces the image it holds.Nonedraws nothing. - placeholder
- A block for laying out a prototype, as Textual’s
Placeholder: filled with the next of twelve colours (in the order placeholders are built on a thread), itslabelcentred on it.placeholder_variantshows its size or a paragraph instead, and a click moves to the next variant. - progress_
bar - A bar of
doneout oftotal, as Textual’sProgressBar: withshow_percentageits share (50%), withshow_etathe time left at the rate so far (counted from when it first drew, on the app’s clock). With no total it pulses, a block sweeping across on the app’s clock. The bar is in the theme’sprogress.barstyle (magentaby default) overprogress.track(grey23). One row tall. - radio
- A group of radio buttons, one per row:
options(console markup; may read signals), with the oneselectedholds chosen:(•) Medium. ↑/↓ (or ←/→) move the choice within the group, Home and End go to the first and the last, and a click chooses an option. The dot is drawn in the theme’sradio.onstyle (elseaccent). Its role isRadioGroup: name it withlabel; its value is the chosen option, checked, and its place among them.radio_keyedknows its options by key, and may disable some. - radio_
keyed - A
radiogroup whose options are known by key, asselect_field_keyed’s are:selectedholds the chosen option’s key (None: no dot), which stays with its option through a reorder and becomesNonewhen that option goes. A disabled option is drawn greyed with its reason; the arrows, Home, End, a click and typing pass it by. Typing letters jumps to the option they start, as in a select field. - recent
- The last
nvalues written tosource, oldest first: each write, an equal value too, ason_writesees them. An average over the last frames, a meter’s peak, an oscilloscope’s persistence.nmay be a signal (or memo): when it shrinks, the oldest go. - recent_
of recent, keepingkeepof each value written rather than a clone of it: a part (a channel of a frame, its peak), a summary, or a shared handle. Nothing else of the value is copied.- recent_
timed recent, each value with the time it was written on the app’s clock (Ctx::nowgives the time to measure its age against): a trace whose old frames fade by age, toasts or log lines that go after a while.- rule
- A line across, one row tall, in the theme’s
borderstyle: a divider between the parts of a column. Directly inside a panel whose sides it reaches, it is drawn in the panel’s border style and kind and joins its sides:├────┤. Padding between the two (the panel’s, or apaddinground the column) does not keep it from them: the rule runs across it.Node::borderpicks the kind of a rule on its own (Border::Rounded’s light line by default). - scroll_
virtual - A scroll view over
len()items that builds only those in view, plus a screen either side: itemiisrow(i), estimatedheight_of(i)rows tall (at least one) until it is drawn and measured (its fixed size, else its content’s height). A million items cost a screenful. Items are kept while they stay near the view, and dropped (their state with them) once they leave it. - scroll_
virtual_ with scroll_virtual, with the first row in view inoffset: read it, or set it to scroll from code (u64::MAXfor the end).- select_
field - A drop-down field showing the option
selectedholds, ofoptions(console markup; may read signals):Dark ▾. Enter, Space or a click opens a menu of the options under it, the chosen one selected: ↑/↓ move, Enter or a click chooses, Esc closes it. Closed, ↑/↓ choose the option before or after; in either, typing letters jumps to the option they start. The field is drawn in the theme’sselectstyle, withcontrol.focusover it while it has the focus; the menu is a menu’s. Its role isComboBox: name it withlabel; its value is the choice, with its place among the options and whether the menu is open.select_field_keyedknows its options by key, and may disable some. - select_
field_ keyed - A
select_fieldwhose options are known by key:selectedholds the chosen option’s key, so the choice stays with its option when the options are reordered or relabelled. When the chosen key goes from the options,selectedbecomesNoneand the field shows(none). A disabled option (SelectOption::disabled) is shown greyed in the menu with its reason, and cannot be chosen by the arrows, a click or typing. - slider
- A slider over
range, holdingvalue, moved in steps ofstep(none when 0): a track with a knob, filled up to it. ←/↓ and →/↑ move it a step, PageDown and PageUp a tenth of the range, Home and End to its ends; a click puts the knob under the pointer, and a drag moves it, as does the wheel. The filled side is in the theme’sslider.filledstyle (elseaccent), the rest inslider.track(elsemuted), the knob inslider.knob; with the focus the knob takescontrol.focus. Its role isSlider: name it withlabel; its value is the number. Twenty cells wide unless sized. - smoothed
- A number that follows
sourceon the app’s clock, rising with the time constantattackand falling withrelease(an exponential ease: after one time constant it has come about 63% of the way). A level meter’s needle, a progress bar that glides, a spectrum’s bars falling back slowly. A zero time constant follows at once. It moves a frame at a time while it eases, and stops once it is there. - sparkline
- A sparkline of
values, a closure that may read signals: rs-rich-ext’sSparkline(ratatui’s and Textual’s), one cell a value, as tall as the node. Given more values than cells it resamples them, so keep as many as should show (a history the width of the node, the newest last). Its accessible name says the values’ range and trend. - sparkline_
with - A
sparklinewhoseSparklineconfiguresets up (.range(0.0, 1.0),.style("green"),.min_max(true)). - spectrogram
- A spectrogram (a waterfall) of
spectra, a closure that may read signals and returns the spectra to show, oldest first, each the levels of its bins, lowest frequency first: rs-rich-ext’sSpectrogram, the newest at the top, as tall as the node. Keep the history with the core’srecent(recent(spectrum, rows)keeps the newestrows, oldest first). Its accessible name says the spectra’s range and where the newest peaks. - spectrogram_
with - A
spectrogramwhoseSpectrogramconfiguresets up (.resolution(rate / n),.scale(AxisScale::Log),.bounds(20.0, 20_000.0),.range(-60.0, 0.0),.charset(..)): it is given one holding the spectra, and returns it changed. - spinner
- A spinner: rich’s spinner
name(dots,line,arc,bouncingBar, … asrich::spinner::spinner_nameslists them;dotsfor a name it does not know), turning at its own speed on the app’s clock, in the theme’sspinnerstyle (elseaccent). It draws again only when its next frame is due, and only while it spins: always, or whilespinning_when’s condition holds (blank otherwise). Its glyph is decoration, hidden from assistive technology: say what is happening in text beside it, or mark what is loading busy. In text mode it is a still*. - stepped_
worker - Run
workon a thread of its own, stepped by the app’s clock: eachperiodthe app hands it the ticks due (at mostmax_catch_upafter a stall), waits up to 250 ms for it to finish them, and shows its newest output in the signal returned (Noneuntil the first).workcallsSteps::waitfor ticks andSteps::publishfor output, and returns whenwaitgivesNone(the app has gone). A worker that returns early makes each step return at once.stepped_worker_withtakes the timeout too. - stepped_
worker_ with stepped_workerpaced aspacesays, with its timer: to pause or cancel the stepping.- switch_
of - A
switch_togglewhose label is read fromlabel, a closure that may read signals. - switch_
toggle - A switch labelled
label(console markup), on whileonholds: a knob at the right of its track when on (──●), at the left when off (●──), the track in the theme’sswitch.onstyle (elsegood) orswitch.off(elsemuted). Space, Enter or a click flips it; → turns it on and ← off. Its role isSwitch, named by its label, with its checked state. - tiles_
of - A node over a whole frame cut into tiles (#818):
tilesreturns them (a closure that may read signals;rich_art::tiles::Tiler::tiles), each drawn at its place in cells throughpixels. A tile that did not change keeps its picture’s id and version, so withimage_graphicsonly the tiles that changed reach the terminal again (Kitty’s uploads for its placeholders). A tile that does not fit the node is left out. - treemap
- A treemap of
items, each(key, weight): a tile per item, its area in proportion to its weight, as near square as the weights let it be, each holding the nodebuildmakes for its key and its rectangle (on the screen).itemsmay read signals: the map lays out again when they change. A tile keeps its node while its key and size stay; a new key, or a tile of another size, is built afresh (what it shows may depend on its room), and the old one is dropped. What takes the room: a disk by folder, memory by process, a bundle by module. Tiles that take the focus move between each other by direction withbind_directional_focus. - treemap_
with treemaplaid out asoptionssay: the smallest tile, a cell’s shape, and a tile for the rest.- tuner
- A tuner’s readout of
reading, a closure that may read signals (an rs-rich-extTuner’s reading of the newest spectrum): the note in big glyphs (digits), a needle from flat to sharp across the width, its centre the note, and the frequency and cents. Green within 5 cents, yellow within 15, red beyond;--andno signalwith no reading. - watch_
path - Watch
path(a file, or a directory and its direct entries) and callon_changeon the app’s thread when it changes, with the changes gathered over 100 ms. Call it while the app is built or running. Seewatch_path_withfor a recursive watch and another interval. - watch_
path_ with watch_pathwithWatchOptions: recursive, or another debounce interval.
Type Aliases§
- Mode
Page - One mode of
Node::modes: its value, its help section, and what binds its keys.