Kino.ExRatatui (KinoExRatatui v0.1.1)

Copy Markdown View Source

Run an ExRatatui.App inside a Livebook notebook via xterm.js.

Kino.ExRatatui is a byte-stream transport that pipes the runtime server's rendered ANSI through an xterm.js iframe and forwards keypresses + resize events back.

Example

defmodule Counter do
  use ExRatatui.App
  alias ExRatatui.Event.Key
  alias ExRatatui.Layout.Rect
  alias ExRatatui.Widgets.Paragraph

  def mount(_), do: {:ok, %{n: 0}}

  def render(state, frame) do
    [{%Paragraph{text: "Count: #{state.n}"},
      %Rect{x: 0, y: 0, width: frame.width, height: frame.height}}]
  end

  def handle_event(%Key{code: "+"}, s), do: {:noreply, %{s | n: s.n + 1}}
  def handle_event(%Key{code: "q"}, s), do: {:stop, s}
  def handle_event(_, s),                do: {:noreply, s}
end

Kino.ExRatatui.new(Counter)

Options

The second argument is a keyword list passed straight to ExRatatui.App.mount/1. Use it for any per-instance configuration your App reads from its mount opts. The keys :mod, :name, and :transport are reserved by the runtime and silently overwritten.

Lifecycle

Each new/2 call spawns a fresh Kino.JS.Live server. The runtime server and ExRatatui.Session are created lazily on the first "resize" event from the iframe so we always start at the correct cell dimensions reported by xterm.js's FitAddon. Re-evaluating the cell (or closing the notebook) tears the runtime server down and starts a new one — no state is preserved across re-evals.

How it plugs into ExRatatui

Implements ExRatatui.Transport as a byte-stream transport, using ExRatatui.Transport.start_server/1 to boot the runtime and ExRatatui.Transport.ByteStream to pump input + resize events. See the Custom Transports guide for the reference shape.

Summary

Functions

Renders a one-shot static frame of widgets and returns a non-interactive Kino.JS widget that paints it once.

Builds a new live kino that hosts mod (an ExRatatui.App).

Functions

frame(widgets, opts \\ [])

@spec frame(
  [{ExRatatui.widget(), ExRatatui.Layout.Rect.t()}],
  keyword()
) :: Kino.JS.t()

Renders a one-shot static frame of widgets and returns a non-interactive Kino.JS widget that paints it once.

Useful for documentation, screenshots in notebooks, or Kino.Layout.grid([frame_a, frame_b, frame_c]) side-by-side comparisons. There is no event loop, no resize handling, and no runtime server — just an ExRatatui.Session rendered once and written to xterm.js.

Options

  • :cols — terminal width in cells. Defaults to 80.
  • :rows — terminal height in cells. Defaults to 24.

Examples

iex> alias ExRatatui.Layout.Rect
iex> alias ExRatatui.Widgets.{Block, Paragraph}
iex> kino = Kino.ExRatatui.frame(
...>   [
...>     {%Paragraph{
...>        text: "Hello from a static frame!",
...>        block: %Block{title: "demo"}
...>      },
...>      %Rect{x: 0, y: 0, width: 40, height: 5}}
...>   ],
...>   cols: 40,
...>   rows: 5
...> )
iex> kino.module
Kino.ExRatatui

new(mod, mount_opts \\ [])

@spec new(
  module(),
  keyword()
) :: Kino.JS.Live.t()

Builds a new live kino that hosts mod (an ExRatatui.App).

mount_opts is forwarded verbatim to ExRatatui.App.mount/1, so an App can do per-instance setup the same way it would over SSH.

Examples

Kino.ExRatatui.new(Counter)
Kino.ExRatatui.new(Counter, start: 10, theme: :dark)