App All Events Example

App All Events

This example application captures and visualizes every event supported by ratatui_ruby. It serves as a comprehensive reference for event handling and a demonstration of the Model-View-Update architectural pattern.

Architecture: Model-View-Update

This application demonstrates unidirectional data flow inspired by The Elm Architecture. This separation ensures that state management is predictable and easy to test.

1. Model (model/app_model.rb)

A single immutable Data.define object holding all application state: * Event log entries * Focus state * Window size * Highlight timestamps * Color cycle index

State changes use .with(...) to return a new Model instance.

2. Msg (model/msg.rb)

Semantic value objects that decouple raw terminal events from business logic: * Msg::Input β€” keyboard, mouse, or paste events * Msg::Resize β€” terminal size changes * Msg::Focus β€” focus gained/lost * Msg::Quit β€” exit signal

3. Update (update.rb)

A pure function that computes the next state:

Update.call(msg, model) -> Model

All logic previously in Events.record now lives here. The function never mutates, never draws, never performs IO.

4. View (view/)

Pure rendering logic. Views accept the immutable AppModel and draw to the screen. * View::App: Root view handling high-level layout * Sub-views: Counts, Live, Log, Controls

5. Runtime (app.rb)

The MVU loop:

loop do
  tui.draw { |f| view.call(model, tui, f, f.area) }
  msg = map_event_to_msg(tui.poll_event, model)
  break if msg.is_a?(Msg::Quit)
  model = Update.call(msg, model)
end

Library Features Showcased

Reading this code will teach you how to:

What Problems Does This Solve?

β€œWhat key code is my terminal sending?”

If you are building an app and your logic isn’t catching Ctrl+Left, run this app and press the keys. You will see exactly how ratatui_ruby parses that input (e.g., is it a Key event? What are the modifiers?).

β€œHow do I structure a real app?”

Hello World examples are great, but they don’t scale. This example shows how to structure an application that can grow. By using immutable state and pure functions, it solves the problem of β€œwhere does my state live and how does it change?”

β€œHow do I test my business logic?”

The Update function is pure. You can test it by constructing a Msg, calling Update.call(msg, model), and asserting on the returned Model. No mocking required.

Comparison: Choosing an Architecture

Complex applications require structured state habits. AppAllEvents and the Color Picker demonstrate two different approaches.

The Dashboard Approach (AppAllEvents)

Dashboards display data. They rarely require complex mouse interaction. Model-View-Update works best here. State is immutable. Logic is pure. Updates are predictable. This simplifies testing.

Use this pattern for logs, monitors, and data viewers.

The Tool Approach (Color Picker)

Tools require interaction. Users click buttons and drag sliders. Each UI component needs to know where it exists on screen for hit testing.

The Color Picker uses a Component-Based pattern. Each component encapsulates its own rendering, state, and event handling. The Container routes events and coordinates cross-component effects.

Use this pattern for forms, editors, and mouse-driven tools.

Read the source code β†’