Raxol.Plugin behaviour (Raxol v2.0.1)
View SourceBehavior for Raxol plugins.
Plugins extend Raxol with custom functionality while maintaining a consistent interface for lifecycle management, input handling, and rendering.
Example
defmodule MyApp.HelloPlugin do
@behaviour Raxol.Plugin
alias Raxol.Core.Buffer
@impl true
def init(_opts) do
{:ok, %{counter: 0}}
end
@impl true
def handle_input(key, _modifiers, state) do
case key do
" " -> {:ok, %{state | counter: state.counter + 1}}
"r" -> {:ok, %{counter: 0}}
"q" -> {:exit, state}
_ -> {:ok, state}
end
end
@impl true
def render(buffer, state) do
buffer
|> Buffer.write_at(0, 0, "Hello from plugin!", %{bold: true})
|> Buffer.write_at(0, 1, "Counter: #{state.counter}")
|> Buffer.write_at(0, 2, "Press SPACE to increment, R to reset, Q to quit")
end
@impl true
def cleanup(_state), do: :ok
endPlugin State
Plugin state is managed by the plugin itself and passed between callbacks. The state can be any Elixir term (map, struct, etc.).
Input Handling
The handle_input/3 callback receives:
key- The key pressed (string or atom for special keys)modifiers- Map with:ctrl,:alt,:shift,:metaflagsstate- Current plugin state
It should return:
{:ok, new_state}- Continue with updated state{:exit, state}- Signal plugin should exit{:error, reason}- Signal an error occurred
Rendering
The render/2 callback receives a buffer and current state, and should
return the modified buffer. All rendering is done using the Raxol.Core.Buffer
API for consistency.
Lifecycle
init/1- Called when plugin startshandle_input/3- Called for each input eventrender/2- Called to render current statecleanup/1- Called when plugin exits
Summary
Callbacks
Clean up plugin resources.
Optional callback for handling timer/async events.
Handle keyboard or mouse input.
Initialize the plugin with given options.
Render the plugin's current state to a buffer.
Functions
Run a plugin with the given module and options.
Types
Callbacks
Clean up plugin resources.
Called when the plugin is about to exit. Use this to close connections, save state, cancel timers, etc.
Examples
def cleanup(state) do
if state.connection do
Connection.close(state.connection)
end
:ok
end
Optional callback for handling timer/async events.
If your plugin needs to handle periodic updates or async messages, implement this callback. It receives a message and current state.
Examples
def handle_info(:tick, state) do
{:ok, %{state | last_update: System.monotonic_time()}}
end
def handle_info({:api_response, data}, state) do
{:ok, %{state | data: data}}
end
@callback handle_input(key(), modifiers(), state()) :: {:ok, state()} | {:exit, state()} | {:error, term()}
Handle keyboard or mouse input.
Called for each input event. Should return {:ok, new_state} to continue,
{:exit, state} to signal plugin exit, or {:error, reason} on error.
Special Keys
Special keys are represented as atoms:
:enter,:escape,:tab,:backspace,:delete:up,:down,:left,:right:home,:end,:page_up,:page_down:f1through:f12
Examples
def handle_input(key, modifiers, state) do
cond do
key == "q" -> {:exit, state}
key == :enter -> {:ok, process_input(state)}
modifiers.ctrl and key == "c" -> {:exit, state}
true -> {:ok, state}
end
end
Initialize the plugin with given options.
Called once when the plugin is first loaded. Should return {:ok, initial_state}
or {:error, reason} if initialization fails.
Examples
def init(opts) do
api_key = Keyword.get(opts, :api_key)
{:ok, %{api_key: api_key, data: []}}
end
@callback render(Raxol.Core.Buffer.t(), state()) :: Raxol.Core.Buffer.t()
Render the plugin's current state to a buffer.
Called each frame to render the plugin's UI. Receives the buffer and current state, should return the modified buffer.
Examples
def render(buffer, state) do
buffer
|> Buffer.write_at(0, 0, "Status: #{state.status}")
|> Buffer.write_at(0, 1, "Data: #{length(state.data)} items")
end