Core Concepts
This guide explains the core concepts and patterns available in ratatui_ruby for structuring your terminal applications.
1. Lifecycle Management
Managing the terminal state is critical. You must enter “alternate screen” and “raw mode” on startup, and always restore the terminal on exit (even on errors), otherwise the user’s terminal will be left in a broken state.
RatatuiRuby.run (Recommended)
The run method acts as a Context Manager. It handles the initialization and restoration for you, ensuring the terminal is always restored even if your code raises an exception. We recommend using run for all applications, as it provides a safe sandbox for your TUI.
RatatuiRuby.run do |tui| loop do # Your code here tui.draw(...) end end # Terminal is restored here
Manual Management (Advanced)
You can manage this manually if you need granular control, but use ensure blocks!
RatatuiRuby.init_terminal begin # Your code here RatatuiRuby.draw(...) ensure RatatuiRuby.restore_terminal end
2. API Convenience
Session API (Recommended)
The block yielded by run is a RatatuiRuby::Session instance (tui). It provides factory methods for every widget class (converting snake_case to CamelCase) and aliases for module functions.
Why use it? It significantly reduces verbosity and repeated RatatuiRuby:: namespacing, making the UI tree structure easier to read.
RatatuiRuby.run do |tui| loop do layout = tui.layout( direction: :horizontal, constraints: [ RatatuiRuby::Constraint.length(20), RatatuiRuby::Constraint.min(0) ], children: [ tui.paragraph( text: tui.text_line(spans: [ tui.text_span(content: "Side", style: tui.style(fg: :blue)), tui.text_span(content: "bar") ]), block: tui.block(borders: [:all], title: "Nav") ), tui.paragraph( text: "Main Content", style: tui.style(fg: :green), block: tui.block(borders: [:all], title: "Content") ) ] ) tui.draw(layout) event = tui.poll_event break if event == "q" || event == :ctrl_c end end
Raw API
You can always use the raw module methods and classes directly. This is useful if you are building your own abstractions or prefer explicit class instantiation.
Comparison: Notice how much more verbose the same UI definition is.
RatatuiRuby.run do loop do layout = RatatuiRuby::Layout.new( direction: :horizontal, constraints: [ RatatuiRuby::Constraint.length(20), RatatuiRuby::Constraint.min(0) ], children: [ RatatuiRuby::Paragraph.new( text: RatatuiRuby::Text::Line.new(spans: [ RatatuiRuby::Text::Span.new(content: "Side", style: RatatuiRuby::Style.new(fg: :blue)), RatatuiRuby::Text::Span.new(content: "bar") ]), block: RatatuiRuby::Block.new(borders: [:all], title: "Nav") ), RatatuiRuby::Paragraph.new( text: "Main Content", style: RatatuiRuby::Style.new(fg: :green), block: RatatuiRuby::Block.new(borders: [:all], title: "Content") ) ] ) RatatuiRuby.draw(layout) event = RatatuiRuby.poll_event break if event == "q" || event == :ctrl_c end end