### Setup Task Manager Dependencies and Database Source: https://github.com/mcass19/ex_ratatui/blob/main/examples/task_manager/README.md Navigate to the example directory, fetch dependencies, and set up the Ecto database for the task manager. ```bash cd examples/task_manager mix deps.get mix ecto.setup ``` -------------------------------- ### Run ExRatatui Example over Erlang Distribution Source: https://github.com/mcass19/ex_ratatui/blob/main/examples/README.md Start a system monitor example using Erlang Distribution. This involves running the app node and then attaching to it from another node. ```sh # Terminal 1 — start the app node elixir --sname app --cookie demo -S mix run --no-halt examples/system_monitor.exs --distributed # Terminal 2 — attach from another node iex --sname local --cookie demo -S mix iex> ExRatatui.Distributed.attach( ``` -------------------------------- ### Starting the Reducer Runtime App Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/reducer_runtime.md Demonstrates how to start the ExRatatui application within a supervision tree or run it directly. ```elixir children = [{MyApp.TUI, []}] Supervisor.start_link(children, strategy: :one_for_one) ``` -------------------------------- ### ExRatatui 'Hello World' Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/getting_started.md A basic ExRatatui application that displays a centered message with a rounded border and exits on key press. This demonstrates the core API for running the terminal, getting size, defining widgets, drawing, and polling for events. ```elixir defmodule Hello do alias ExRatatui.Layout.Rect alias ExRatatui.Style alias ExRatatui.Widgets.{Block, Paragraph} def run do ExRatatui.run(fn terminal -> {w, h} = ExRatatui.terminal_size() paragraph = %Paragraph{ text: "Hello from ExRatatui!\n\nPress any key to exit.", style: %Style{fg: :green, modifiers: [:bold]}, alignment: :center, block: %Block{ title: " Hello World ", borders: [:all], border_type: :rounded, border_style: %Style{fg: :cyan} } } ExRatatui.draw(terminal, [{paragraph, %Rect{x: 0, y: 0, width: w, height: h}}]) wait_for_key() end) end defp wait_for_key do case ExRatatui.poll_event(5_000) do nil -> wait_for_key() _ -> :ok end end end ``` -------------------------------- ### Running System Monitor Example over SSH Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/ssh_transport.md Execute the bundled system monitor example and connect to it via SSH. The example generates a temporary host key on first run. ```sh mix run --no-halt examples/system_monitor.exs --ssh ``` ```sh ssh demo@localhost -p 2222 # password: demo ``` -------------------------------- ### Run System Monitor Example Remotely Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/distributed_transport.md Demonstrates running the System Monitor example over Erlang distribution. This involves starting the app node and then attaching from another node. ```shell # Terminal 1 — start the app node elixir --sname app --cookie demo -S mix run --no-halt examples/system_monitor.exs --distributed ``` ```elixir # Terminal 2 — attach from another node iex --sname mynode --cookie demo -S mix iex> ExRatatui.Distributed.attach(:"app@hostname", SystemMonitor) ``` -------------------------------- ### Run ExRatatui Example over SSH Source: https://github.com/mcass19/ex_ratatui/blob/main/examples/README.md Execute a system monitor example using SSH transport. Ensure the SSH server is running on the specified port. ```sh mix run --no-halt examples/system_monitor.exs --ssh # in another terminal: ssh demo@localhost -p 2222 # password: demo ``` -------------------------------- ### Starting the Callback Runtime App Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/callback_runtime.md Demonstrates how to integrate the ExRatatui application into a supervision tree or run it directly. ```elixir children = [{MyApp.TUI, []}] Supervisor.start_link(children, strategy: :one_for_one) ``` ```elixir {:ok, pid} = MyApp.TUI.start_link(name: nil) ``` -------------------------------- ### Starting the ExRatatui Transport Server Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/cell_session.md Demonstrates how to start the ExRatatui runtime server with a CellSession transport, specifying the application module and the transport configuration. ```elixir {:ok, server} = ExRatatui.Transport.start_server( mod: MyTUI, transport: {:cell_session, cell_session, cell_writer_fn, intent_writer_fn} ) ``` -------------------------------- ### Running a Basic ExRatatui App Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/getting_started.md These commands show how to start and monitor a basic ExRatatui application directly in IEx. ```sh iex -S mix iex> {:ok, _pid} = Hello.start_link(name: nil) iex> Process.monitor(_pid) # optional — block until the app exits ``` -------------------------------- ### Handle Event Callback Examples Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/callback_runtime.md Provides examples for the `handle_event/2` callback, showing how to stop the application on 'q' press and modify state based on 'up' and 'down' key presses. ```elixir def handle_event(%Event.Key{code: "q", kind: "press"}, state) do {:stop, state} end ``` ```elixir def handle_event(%Event.Key{code: "up", kind: "press"}, state) do {:noreply, %{state | selected: max(state.selected - 1, 0)}} end ``` ```elixir def handle_event(_event, state) do {:noreply, state} end ``` -------------------------------- ### Mount Callback Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/callback_runtime.md Shows how to initialize the application state in the `mount/1` callback. It demonstrates retrieving options like a PubSub client and subscribing to a topic. ```elixir def mount(opts) do pubsub = Keyword.get(opts, :pubsub) if pubsub do Phoenix.PubSub.subscribe(pubsub, "updates") end {:ok, %{messages: [], pubsub: pubsub}} end ``` -------------------------------- ### MyApp.TUI Module with Mount Options Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/distributed_transport.md Example of an `ExRatatui.App` module demonstrating how to fetch and use options passed during `mount/1`. ```elixir defmodule MyApp.TUI do use ExRatatui.App @impl true def mount(opts) do pubsub = Keyword.fetch!(opts, :pubsub) Phoenix.PubSub.subscribe(pubsub, "alerts") {:ok, %{pubsub: pubsub, role: opts[:node_role]}} end end ``` -------------------------------- ### Image Demo Example Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md An interactive image viewer example. Supports runtime protocol and resize toggling, with a live status panel. Can be used for smoke-testing transports with --ssh and --distributed flags. ```Elixir examples/image_demo.exs ``` -------------------------------- ### Render Callback Example with Layout Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/callback_runtime.md Illustrates the `render/2` callback, which is responsible for drawing the UI. This example uses `Layout.split` to divide the terminal area and render different content in each section. ```elixir def render(state, frame) do area = %Rect{x: 0, y: 0, width: frame.width, height: frame.height} [header_area, body_area] = Layout.split(area, :vertical, [{:length, 3}, {:min, 0}]) [ {%Paragraph{text: "Header"}, header_area}, {%Paragraph{text: "Body: #{inspect(state)}"}, body_area} ] end ``` -------------------------------- ### ExRatatui.CellSession: Take Cells Example Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Illustrates using `take_cells/1` with ExRatatui.CellSession to get a full snapshot of the current cell buffer. This is typically used on the first call or after significant layout changes. ```elixir case ExRatatui.CellSession.take_cells(cs) do %ExRatatui.CellSession.Snapshot{cells: all_cells} -> # ... process all_cells end ``` -------------------------------- ### Headless Cell Dump Example Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md A headless example demonstrating how to use ExRatatui.CellSession to capture and dump cell output without rendering to a terminal. Useful for testing and debugging. ```elixir iex(1)> ExRatatui.CellSession.new(width: 80, height: 24) |> ExRatatui.CellSession.run(MyTuiApp) %ExRatatui.CellSession.Snapshot{cells: [...]} # Then, to see diffs: iex(2)> ExRatatui.CellSession.take_cells_diff(cs) %ExRatatui.CellSession.Diff{cells: [...]} ``` -------------------------------- ### Run Daemon-Mode Examples with --no-halt Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/debugging.md For daemon-mode examples that exit immediately due to non-TTY stdin, use the '--no-halt' flag. This keeps the VM running after the script returns, allowing the TUI to operate. ```sh mix run --no-halt examples/system_monitor.exs --ssh ``` -------------------------------- ### Running Image Demo Examples Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/images.md Demonstrates how to run the image demo script in different environments: local terminal, SSH, and distributed. These commands show how to initiate the interactive viewer. ```shell mix run examples/image_demo.exs # local terminal mix run --no-halt examples/image_demo.exs --ssh elixir --sname app --cookie demo -S mix run --no-halt \ examples/image_demo.exs --distributed ``` -------------------------------- ### Handle Info Callback Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/callback_runtime.md Demonstrates the `handle_info/2` callback for processing non-terminal messages, such as messages from a PubSub subscription. ```elixir def handle_info({:new_message, msg}, state) do {:noreply, %{state | messages: [msg | state.messages]}} end ``` -------------------------------- ### Install Dependencies and Compile Source: https://github.com/mcass19/ex_ratatui/blob/main/CONTRIBUTING.md Fetch Elixir dependencies and compile the Rust NIF from source by setting the EX_RATATUI_BUILD environment variable. ```sh mix deps.get export EX_RATATUI_BUILD=true mix compile ``` -------------------------------- ### Adding a Child to a Supervisor Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/getting_started.md This example demonstrates how to integrate an ExRatatui application, like `Hello`, as a child process within an OTP supervisor. ```elixir # lib/my_tui/application.ex children = [ Hello ] ``` -------------------------------- ### Basic 'Hello World' TUI Example Source: https://github.com/mcass19/ex_ratatui/blob/main/README.md A minimal ExRatatui application that displays 'Hello from ExRatatui!' centered on the screen with a green bold style and a rounded cyan border. It waits for a keypress before exiting. ```elixir alias ExRatatui.Layout.Rect alias ExRatatui.Style alias ExRatatui.Widgets.{Block, Paragraph} ExRatatui.run(fn terminal -> {w, h} = ExRatatui.terminal_size() paragraph = %Paragraph{ text: "Hello from ExRatatui!\n\nPress any key to exit.", style: %Style{fg: :green, modifiers: [:bold]}, alignment: :center, block: %Block{ title: " Hello World ", borders: [:all], border_type: :rounded, border_style: %Style{fg: :cyan} } } ExRatatui.draw(terminal, [{paragraph, %Rect{x: 0, y: 0, width: w, height: h}}]) # Wait for a keypress, then exit ExRatatui.poll_event(60_000) end) ``` -------------------------------- ### Table Widget Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/building_uis.md Renders a table with headers, rows, and column width constraints. Supports highlighting and selection. ```elixir %Table{ rows: [["Alice", "30"], ["Bob", "25"]], header: ["Name", "Age"], widths: [{:length, 15}, {:length, 10}], highlight_style: %Style{fg: :yellow}, selected: 0 } ``` -------------------------------- ### Start App Node Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/distributed_transport.md Launch the application node with Erlang distribution enabled. Ensure the node name, cookie, and mix environment are set up correctly. ```shell iex --sname app --cookie mycookie -S mix ``` -------------------------------- ### Reducer Runtime App Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/reducer_runtime.md A basic ExRatatui application using the reducer runtime, demonstrating initialization, rendering, state updates, and subscriptions. ```elixir defmodule MyApp.TUI do use ExRatatui.App, runtime: :reducer alias ExRatatui.{Command, Event, Subscription} alias ExRatatui.Layout.Rect alias ExRatatui.Widgets.Paragraph @impl true def init(_opts) do {:ok, %{count: 0}, commands: [Command.message(:boot)]} end @impl true def render(state, frame) do area = %Rect{x: 0, y: 0, width: frame.width, height: frame.height} [{%Paragraph{text: "Count: #{state.count}"}, area}] end @impl true def update({:event, %Event.Key{code: "q", kind: "press"}}, state) do {:stop, state} end def update({:event, %Event.Key{code: "up", kind: "press"}}, state) do {:noreply, %{state | count: state.count + 1}} end def update({:info, :boot}, state) do {:noreply, %{state | count: 1}} end def update({:info, :tick}, state) do {:noreply, %{state | count: state.count + 1}} end def update(_msg, state), do: {:noreply, state} @impl true def subscriptions(_state) do [Subscription.interval(:heartbeat, 1_000, :tick)] end end ``` -------------------------------- ### List Widget Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/building_uis.md A selectable list with highlight support for the current item. Configure items, highlight style, and selected item. ```elixir %List{ items: ["Elixir", "Rust", "Haskell"], highlight_style: %Style{fg: :yellow, modifiers: [:bold]}, highlight_symbol: " > ", selected: 0, block: %Block{title: " Languages ", borders: [:all]} } ``` -------------------------------- ### Running the Todo Application Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/getting_started.md These commands demonstrate how to start the Todo application in an interactive Elixir shell and monitor its process. This is used to verify the application's lifecycle and ensure it can be stopped gracefully. ```sh iex -S mix iex> {:ok, pid} = Todo.start_link(name: nil) iex> ref = Process.monitor(pid) iex> receive do {:DOWN, ^ref, _, _, _} -> :ok end ``` -------------------------------- ### Get Runtime Snapshot of ExRatatui App Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/debugging.md Use `ExRatatui.Runtime.snapshot/1` to get a map of the current runtime state. This is useful for quickly checking render counts, dimensions, and active subscriptions. ```elixir iex> {:ok, pid} = MyApp.TUI.start_link(name: nil) iex> ExRatatui.Runtime.snapshot(pid) %{ mode: :callbacks, mod: MyApp.TUI, transport: :local, polling_enabled?: true, dimensions: {120, 40}, render_count: 17, last_rendered_at: ~U[2026-04-20 12:34:56.789Z], subscription_count: 1, subscriptions: [%{id: :tick, kind: :interval, interval_ms: 1_000, fired?: true, active?: true}], active_async_commands: 0, trace_enabled?: false, trace_limit: 200, trace_events: [] } ``` -------------------------------- ### Quick start with CellSession Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/cell_session.md Initializes a CellSession, draws a paragraph, takes a snapshot of the cells, and closes the session. This demonstrates the basic lifecycle and cell buffer retrieval. ```elixir alias ExRatatui.CellSession alias ExRatatui.CellSession.{Cell, Snapshot} alias ExRatatui.Layout.Rect alias ExRatatui.Style alias ExRatatui.Widgets.{Block, Paragraph} session = CellSession.new(40, 6) paragraph = %Paragraph{ text: "Hello from CellSession!", style: %Style{fg: :light_cyan, modifiers: [:bold]}, alignment: :center, block: %Block{title: " demo ", borders: [:all], border_type: :rounded} } :ok = CellSession.draw(session, [{paragraph, %Rect{x: 0, y: 0, width: 40, height: 6}}]) %Snapshot{width: 40, height: 6, cells: cells} = CellSession.take_cells(session) CellSession.close(session) ``` -------------------------------- ### Enabling Runtime Tracing in mount Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/callback_runtime.md This example demonstrates enabling in-memory runtime tracing by returning the 'trace?: true' option from the 'mount' callback. This is useful for debugging purposes. ```elixir def mount(_opts) do {:ok, %{n: 0}, trace?: true} end ``` -------------------------------- ### Theme Picker Example Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Provides a visual reference for ExRatatui.Theme slots, including live previews of border styles, text styles, and selection styles. Users can switch between default, light, and a custom Nord-ish theme using keys 1, 2, or 3. ```Elixir examples/theme_picker.exs ``` -------------------------------- ### Gauge Widget Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/building_uis.md A progress bar that fills proportionally to a given ratio. Displays a label and uses a specified gauge style. ```elixir %Gauge{ ratio: 0.75, label: "75%", gauge_style: %Style{fg: :green} } ``` -------------------------------- ### Headless Image Rendering Example Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Renders an image through CellSession for Livebook or snapshot consumers. Supports ANSI foreground and background colors per cell. ```Elixir examples/headless_image.exs ``` -------------------------------- ### WidgetList Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/building_uis.md Defines a WidgetList with chat messages, selection, styling, and a block border. Use for heterogeneous lists with different item heights. ```elixir %WidgetList{ items: [ {%Paragraph{text: "User: Hello!"}, 1}, {%Markdown{content: "**Bot:** Hi there!\n\nHow can I help?"}, 4}, {%Paragraph{text: "User: What is Elixir?"}, 1} ], selected: 1, highlight_style: %Style{fg: :yellow}, scroll_offset: 0, block: %Block{title: "Chat", borders: [:all]} } ``` -------------------------------- ### Clipboard Integration Guide Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Explains bracketed paste behavior, `insert_str` helpers, and transport caveats for clipboard integration. Includes a snippet for OSC 52 clipboard copy functionality, noting it's not built-in. ```Markdown guides/paste_and_clipboard.md ``` -------------------------------- ### Trace Runtime Events for Performance Analysis Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/performance.md Enable tracing with `ExRatatui.Runtime.enable_trace/2` to get timestamps for messages, renders, commands, and subscriptions. Analyze these events to identify performance bottlenecks. ```elixir ExRatatui.Runtime.enable_trace(pid) # ... interact ... events = ExRatatui.Runtime.trace_events(pid) # Pair each :message with the next :render events |> Enum.chunk_every(2, 1, :discard) |> Enum.filter(fn [a, b] -> a.kind == :message and b.kind == :render end) |> Enum.map(fn [msg, render] -> render.at_ms - msg.at_ms end) ``` -------------------------------- ### Implement a Composed Dashboard Widget Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/custom_widgets.md This example demonstrates widget composition by creating a `Dashboard` widget that splits its allocated rectangle horizontally and returns two other widgets (`left_panel` and `right_panel`) to occupy these halves. ```elixir defmodule MyApp.Widgets.Dashboard do defstruct [:left_panel, :right_panel] defimpl ExRatatui.Widget do alias ExRatatui.Layout def render(%{left_panel: l, right_panel: r}, rect) do [left, right] = Layout.split(rect, :horizontal, [{:percentage, 50}, {:percentage, 50}]) [{l, left}, {r, right}] end end end ``` -------------------------------- ### Starting SSH Daemon with Image Protocol Configuration Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/images.md Configure the SSH daemon to inform the client about its supported image protocol and font size. This is crucial for accurate scaling of images on remote terminals. ```elixir # SSH daemon ExRatatui.SSH.Daemon.start_link( mod: MyApp.TUI, port: 2222, image_protocol: :kitty, image_font_size: {10, 20} ) ``` -------------------------------- ### SSH Transport Guide - Subsystem vs Shell Mode Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Explains the differences in server boot triggers between shell and subsystem modes in SSH transport. Recommends always passing '-t' for OpenSSH. ```markdown guides/ssh_transport.md ``` -------------------------------- ### Implement a Custom UserCard Widget Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/custom_widgets.md This example shows a full implementation of a custom `UserCard` widget. It defines a struct with user data and a selection flag, then implements the `render/2` callback to compose `Block` and `Paragraph` widgets based on the provided rectangle and state. ```elixir defmodule MyApp.Widgets.UserCard do defstruct [:user, selected?: false] defimpl ExRatatui.Widget do alias ExRatatui.Layout alias ExRatatui.Layout.Rect alias ExRatatui.Style alias ExRatatui.Widgets.{Block, Paragraph} def render(%{user: user, selected?: sel?}, %Rect{} = rect) do border_style = if sel?, do: %Style{fg: :yellow}, else: %Style{} [header, body] = Layout.split(rect, :vertical, [{:length, 1}, {:min, 0}]) [ {%Block{title: user.name, borders: [:all], border_style: border_style}, rect}, {%Paragraph{text: user.handle, style: %Style{modifiers: [:bold]}}, header}, {%Paragraph{text: user.bio}, body} ] end end end ``` -------------------------------- ### Interpreting a Typical Trace Sequence Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/debugging.md Analyze the sequence of :message, :command, and :render events to understand state transitions and rendering behavior. This example shows a button press leading to a state change and re-render. ```text :message source: :event payload: %Event.Key{code: "up"} :command kind: :message message: :boot # whatever your update returned :render widget_count: 4 ``` -------------------------------- ### Chat Log Example Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Demonstrates a chat log interface with a bottom-aligned history list, a multi-line textarea with bracketed paste support, and a block header with an unread count. Focus can be tab-cycled between the log and composer. ```Elixir examples/chat_log.exs ``` -------------------------------- ### Increment Counter via Key Press Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/testing.md Start a supervised ExRatatui application in test mode and inject key events to test state transitions. Assert on the runtime snapshot for changes like render counts. ```elixir defmodule MyApp.CounterTest do use ExUnit.Case, async: true alias ExRatatui.Event alias ExRatatui.Runtime test "up arrow increments the counter" do pid = start_supervised!({MyApp.Counter, name: nil, test_mode: {40, 10}}) :ok = Runtime.inject_event(pid, %Event.Key{code: "up", kind: "press"}) :ok = Runtime.inject_event(pid, %Event.Key{code: "up", kind: "press"}) assert %{render_count: n} = Runtime.snapshot(pid) assert n >= 2 end end ``` -------------------------------- ### Reducer Runtime Options: init/1 Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/reducer_runtime.md Shows how to return runtime options from the `init/1` callback, such as initial commands and enabling tracing. ```elixir def init(_opts) do {:ok, %{count: 0}, commands: [Command.message(:boot)], trace?: true} end ``` -------------------------------- ### Get Light Theme Source: https://github.com/mcass19/ex_ratatui/blob/main/README.md Retrieves the light theme palette provided by ExRatatui. ```elixir ExRatatui.Theme.light() ``` -------------------------------- ### Run ExRatatui Application in IEx Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/getting_started.md Executes the 'Hello World' function from an interactive Elixir shell (IEx). ```sh iex -S mix iex> Hello.run() ``` -------------------------------- ### Get Default Theme Source: https://github.com/mcass19/ex_ratatui/blob/main/README.md Retrieves the default theme palette provided by ExRatatui. ```elixir ExRatatui.Theme.default() ``` -------------------------------- ### Basic ExRatatui Application Structure Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/getting_started.md This snippet shows the basic structure of an ExRatatui application using the ExRatatui.App behavior. It includes mount, render, and handle_event callbacks for a simple 'Hello World' display. ```elixir defmodule Hello do use ExRatatui.App alias ExRatatui.Layout.Rect alias ExRatatui.Style alias ExRatatui.Widgets.{Block, Paragraph} @impl true def mount(_opts) do {:ok, %{}} end @impl true def render(_state, frame) do paragraph = %Paragraph{ text: "Hello from ExRatatui!\n\nPress any key to exit.", style: %Style{fg: :green, modifiers: [:bold]}, alignment: :center, block: %Block{ title: " Hello World ", borders: [:all], border_type: :rounded, border_style: %Style{fg: :cyan} } } [{paragraph, %Rect{x: 0, y: 0, width: frame.width, height: frame.height}}] end @impl true def handle_event(%ExRatatui.Event.Key{kind: "press"}, state) do {:stop, state} end def handle_event(_event, state), do: {:noreply, state} end ``` -------------------------------- ### Create New Mix Project Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/getting_started.md Sets up a new Elixir project with supervision enabled. Navigate into the project directory. ```sh mix new my_tui --sup cd my_tui ``` -------------------------------- ### CellWriter Function Implementation Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/cell_session.md Provides an example implementation for the cell_writer_fn, which is responsible for shipping the rendered diff to a target process or renderer. ```elixir cell_writer_fn = fn %CellSession.Diff{} = diff -> # Ship the diff to wherever your renderer lives — a LiveView socket, # a websocket, an in-process callback, etc. send(target_pid, {:render, diff}) :ok end ``` -------------------------------- ### Fetch and Compile Dependencies Source: https://github.com/mcass19/ex_ratatui/blob/main/README.md After adding ExRatatui to your dependencies, fetch and compile them using Mix. This command ensures the library and its NIF binary are ready for use. ```sh mix deps.get && mix compile ``` -------------------------------- ### Block Widget Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/building_uis.md A container with borders and a title. Can wrap any widget via its :block field. Supports various border types. ```elixir %Block{ title: "My Panel", borders: [:all], border_type: :rounded, border_style: %Style{fg: :blue} } # Compose with other widgets: %Paragraph{ text: "Inside a box", block: %Block{title: "Title", borders: [:all]} } ``` -------------------------------- ### IntentWriter Function Implementation Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/cell_session.md Provides an example implementation for the intent_writer_fn, which maps App-emitted intents to consumer-side actions. The vocabulary is entirely up to the user. ```elixir intent_writer_fn = fn intent -> # Map App-emitted intents to consumer-side actions. Vocabulary is # entirely up to you; the runtime forwards verbatim. send(target_pid, {:intent, intent}) :ok end ``` -------------------------------- ### LineGauge Widget Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/building_uis.md A thin single-line progress bar using line-drawing characters. Allows separate styles for filled and unfilled portions. ```elixir %LineGauge{ ratio: 0.6, label: "60%", filled_style: %Style{fg: :green}, unfilled_style: %Style{fg: :dark_gray} } ``` -------------------------------- ### Simulating ExRatatui Events Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/testing.md Demonstrates the structure of key, mouse, and resize events that can be injected into an ExRatatui application for testing purposes. These events mimic user interactions and terminal changes. ```elixir # Key press %ExRatatui.Event.Key{code: "enter", kind: "press"} %ExRatatui.Event.Key{code: "c", modifiers: [:ctrl], kind: "press"} # Mouse %ExRatatui.Event.Mouse{kind: :down, button: :left, column: 10, row: 5} # Resize %ExRatatui.Event.Resize{columns: 120, rows: 40} ``` -------------------------------- ### SSH Subsystem Dispatch Initialization Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Handles SSH subsystem dispatch by synthesizing a default session and starting the TUI server when a subsystem request is detected. ```elixir ssh host -s Elixir.MyApp.TUI ``` ```elixir ExRatatui.SSH.subsystem/1 ``` -------------------------------- ### Testing Widget Rendering with ExRatatui Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/testing.md Illustrates how to test the rendering of individual widgets by extracting the rendering logic into a pure function and asserting the content of the terminal buffer. This approach is useful for visual assertions. ```elixir # In lib/my_app/tui.ex def render(state, frame), do: scene(state, frame) def scene(state, frame), do: [{paragraph_for(state), rect_for(frame)}] # In test/my_app/tui_test.exs test "renders count with positive styling" do terminal = ExRatatui.init_test_terminal(40, 10) scene = MyApp.TUI.scene(%{count: 42}, %ExRatatui.Frame{width: 40, height: 10}) :ok = ExRatatui.draw(terminal, scene) assert ExRatatui.get_buffer_content(terminal) =~ "42" end ``` -------------------------------- ### Cell Session Transport with Intent Writer Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Example of the `{:cell_session, cs, cell_writer_fn, intent_writer_fn}` transport tag, demonstrating how to provide a function to handle emitted intents. ```elixir transport_tag = {:cell_session, cs, cell_writer_fn, intent_writer_fn} ``` -------------------------------- ### Forward Mount Options with Listener Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/distributed_transport.md Pass application-specific options to all attached clients' `mount/1` callback via the `:app_opts` on the Listener. ```elixir children = [ {ExRatatui.Distributed.Listener, mod: MyApp.TUI, app_opts: [pubsub: MyApp.PubSub, node_role: :primary]} ] ``` -------------------------------- ### BarChart Widget Example (Vertical) Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/building_uis.md Renders a vertical bar chart with customizable bar, value, and label styles. Supports auto-scaling or manual max value. ```elixir alias ExRatatui.Widgets.{Bar, BarChart} %BarChart{ data: [ %Bar{label: "Elixir", value: 80}, %Bar{label: "Rust", value: 95, style: %Style{fg: :red}, text_value: "95!"}, %Bar{label: "Go", value: 60} ], bar_width: 6, bar_gap: 2, bar_style: %Style{fg: :cyan}, value_style: %Style{fg: :white, modifiers: [:bold]}, label_style: %Style{fg: :dark_gray}, direction: :vertical, # or :horizontal block: %Block{title: " Traffic ", borders: [:all]} } ``` -------------------------------- ### BigText Widget Example Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/building_uis.md Renders oversized text. Use ExRatatui.BigText.new/2 for input coercion and option validation. Pixel size controls character cell mapping. ```elixir ExRatatui.BigText.new("EX_RATATUI", pixel_size: :quadrant, alignment: :center, style: %Style{fg: :magenta, modifiers: [:bold]}, block: %Block{borders: [:all], border_type: :rounded} ) ``` -------------------------------- ### Define Theming Palette Source: https://github.com/mcass19/ex_ratatui/blob/main/README.md Demonstrates creating an ExRatatui.Theme palette struct with semantic color slots and helper functions for applying styles like borders and text colors. ```elixir %ExRatatui.Theme{primary: "#abcdef", accent: "#fedcba"} ``` -------------------------------- ### Consume Paste Events in ExRatatui Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/paste_and_clipboard.md Consume %ExRatatui.Event.Paste events to insert text into a textarea. This example shows how to handle paste events alongside other key events. ```elixir case ExRatatui.poll_event(timeout) do %ExRatatui.Event.Paste{content: text} -> ExRatatui.textarea_insert_str(state.editor, text) state %ExRatatui.Event.Key{code: "q"} -> :quit _ -> state end ``` -------------------------------- ### Basic Callback Runtime App Structure Source: https://github.com/mcass19/ex_ratatui/blob/main/guides/callback_runtime.md Defines a simple ExRatatui application using the callback runtime. It includes mount, render, and handle_event callbacks to manage a counter and respond to key presses. ```elixir defmodule MyApp.TUI do use ExRatatui.App alias ExRatatui.Event alias ExRatatui.Layout.Rect alias ExRatatui.Style alias ExRatatui.Widgets.{Block, Paragraph} @impl true def mount(_opts) do {:ok, %{count: 0}} end @impl true def render(state, frame) do area = %Rect{x: 0, y: 0, width: frame.width, height: frame.height} widget = %Paragraph{ text: "Count: #{state.count}", style: %Style{fg: :white, modifiers: [:bold]}, alignment: :center, block: %Block{ title: " Counter ", borders: [:all], border_type: :rounded, border_style: %Style{fg: :cyan} } } [{widget, area}] end @impl true def handle_event(%Event.Key{code: "q", kind: "press"}, state) do {:stop, state} end def handle_event(%Event.Key{code: "up", kind: "press"}, state) do {:noreply, %{state | count: state.count + 1}} end def handle_event(%Event.Key{code: "down", kind: "press"}, state) do {:noreply, %{state | count: state.count - 1}} end def handle_event(_event, state) do {:noreply, state} end end ``` -------------------------------- ### ExRatatui.CellSession: Take Cells Diff Example Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Demonstrates how to use `take_cells_diff/1` with ExRatatui.CellSession to retrieve only the cells that have changed since the last call. This is useful for efficient rendering updates. ```elixir case ExRatatui.CellSession.take_cells_diff(cs) do %ExRatatui.CellSession.Diff{cells: changed_cells} -> # ... process changed_cells %ExRatatui.CellSession.Snapshot{cells: all_cells} -> # ... process all_cells (first call, after resize, etc.) end ``` -------------------------------- ### BigText Widget Example Source: https://github.com/mcass19/ex_ratatui/blob/main/CHANGELOG.md Demonstrates the usage of the BigText widget for creating large text elements like slide titles. It supports various pixel sizes and alignments. ```elixir ExRatatui.BigText.new("Hello, World!", pixel_size: :quadrant, alignment: :center) ```