Demonstrates the Cmd.exec command for running shell commands.
This example shows how to execute shell commands and handle both success and failure cases using pattern matching in update. The split layout shows command output in the main area with controls at the bottom.
Examples
Run the demo from the terminal:
ruby examples/widget_cmd_exec/app.rb

Source Code
# frozen_string_literal: true #-- # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com> # SPDX-License-Identifier: MIT-0 #++ $LOAD_PATH.unshift File.expand_path("../../lib", __dir__) require "ratatui_ruby" require "ratatui_ruby/tea" # Demonstrates the Cmd.exec command for running shell commands. # # This example shows how to execute shell commands and handle both success # and failure cases using pattern matching in update. The split layout shows # command output in the main area with controls at the bottom. # # === Examples # # Run the demo from the terminal: # # ruby examples/widget_cmd_exec/app.rb # # rdoc-image:/doc/images/widget_cmd_exec.png class WidgetCmdExec Model = Data.define(:result, :loading, :last_command) INITIAL = Model.new( result: "Press a key to run a command...", loading: false, last_command: nil ) VIEW = -> (model, tui) do hotkey_style = tui.style(modifiers: [:bold, :underlined]) dim_style = tui.style(fg: :dark_gray) # Styles border_color = if model.loading "yellow" elsif model.result.start_with?("Error") "red" else "cyan" end title = model.last_command ? "Output: #{model.last_command}" : "Cmd.exec Demo" content_text = model.loading ? "Running command..." : model.result # 1. Main Output Widget output_widget = tui.paragraph( text: content_text, block: tui.block( title:, borders: [:all], border_style: { fg: border_color }, padding: 1 ) ) # 2. Control Panel Widget control_widget = tui.paragraph( text: [ tui.text_line(spans: [ tui.text_span(content: "d", style: hotkey_style), tui.text_span(content: ": Directory listing (ls -la) "), tui.text_span(content: "u", style: hotkey_style), tui.text_span(content: ": System info (uname -a)"), ]), tui.text_line(spans: [ tui.text_span(content: "f", style: hotkey_style), tui.text_span(content: ": Force failure "), tui.text_span(content: "s", style: hotkey_style), tui.text_span(content: ": Sleep (3s) "), tui.text_span(content: "q", style: hotkey_style), tui.text_span(content: ": Quit"), ]), ], block: tui.block( title: "Controls", borders: [:all], border_style: dim_style ) ) # Return the Root Layout Widget (Blueprint) tui.layout( direction: :vertical, constraints: [ tui.constraint_fill(1), tui.constraint_length(6), ], children: [ output_widget, control_widget, ] ) end UPDATE = -> (msg, model) do case msg # Handle command results in [:got_output, { stdout:, status: 0 }] [model.with(result: stdout.strip.freeze, loading: false), nil] in [:got_output, { stderr:, status: }] [model.with(result: "Error (exit #{status}): #{stderr.strip}".freeze, loading: false), nil] # Handle key presses in _ if msg.q? || msg.ctrl_c? RatatuiRuby::Tea::Cmd.quit in _ if msg.d? [model.with(loading: true, last_command: "ls -la"), RatatuiRuby::Tea::Cmd.exec("ls -la", :got_output)] in _ if msg.u? [model.with(loading: true, last_command: "uname -a"), RatatuiRuby::Tea::Cmd.exec("uname -a", :got_output)] in _ if msg.s? cmd = "sleep 3 && echo 'Slept for 3s'" [model.with(loading: true, last_command: cmd.freeze), RatatuiRuby::Tea::Cmd.exec(cmd, :got_output)] in _ if msg.f? # Intentional failure to demonstrate error handling cmd = "ls /nonexistent_path_12345" [model.with(loading: true, last_command: cmd.freeze), RatatuiRuby::Tea::Cmd.exec(cmd, :got_output)] else model end end def run RatatuiRuby::Tea.run(model: INITIAL, view: VIEW, update: UPDATE) end end WidgetCmdExec.new.run if __FILE__ == $PROGRAM_NAME