Raxol.Plugins.Plugin behaviour (Raxol v0.2.0)

View Source

Defines the behavior for Raxol terminal emulator plugins. Plugins can extend the terminal's functionality by implementing this behavior.

Summary

Callbacks

Returns the plugin's API version. This is used to check compatibility with the plugin manager.

Returns the plugin's dependencies. Each dependency is a map with the following keys

(Optional) Processes a cell, potentially a placeholder, before drawing.

Optional callback executed just before the terminal buffer is presented. Allows plugins to inject direct output commands (e.g., escape sequences).

Types

t()

@type t() :: %Raxol.Plugins.Plugin{
  api_version: String.t(),
  config: map(),
  dependencies: [map()],
  description: String.t(),
  enabled: boolean(),
  name: String.t(),
  version: String.t()
}

Callbacks

cleanup(plugin_state)

(optional)
@callback cleanup(plugin_state :: term()) :: :ok | {:error, String.t()}

get_api_version()

@callback get_api_version() :: String.t()

Returns the plugin's API version. This is used to check compatibility with the plugin manager.

get_dependencies()

@callback get_dependencies() :: [map()]

Returns the plugin's dependencies. Each dependency is a map with the following keys:

  • name: The name of the plugin
  • version: The version constraint (e.g., ">= 1.0.0")
  • optional: Whether the dependency is optional (default: false)

handle_cells(cell, emulator_state, plugin_state)

(optional)
@callback handle_cells(
  cell :: map(),
  emulator_state :: map(),
  plugin_state :: t()
) ::
  {:ok, updated_plugin_state :: t(), replacement_cells :: list(),
   commands :: [binary()]}
  | {:cont, updated_plugin_state :: t()}

(Optional) Processes a cell, potentially a placeholder, before drawing.

Allows plugins to identify specific cells (like placeholders) and replace them with actual content (a list of cells) or generate commands (like escape sequences).

Parameters

  • cell - The specific cell being processed. Can be a regular cell map
         `%{x: _, y: _, char: _, ...}` or a special map like
         `%{type: :placeholder, value: :image, bounds: ...}`.
  • emulator_state - The current state map of the Runtime GenServer.
  • plugin_state - The current internal state of the plugin itself.

Returns

  • {:ok, updated_plugin_state, replacement_cells, commands}: The plugin handled the cell. replacement_cells (a list of {x,y,map} tuples) will replace the original cell in the render list. commands are executed. updated_plugin_state is stored.
  • {:cont, updated_plugin_state}: The plugin declined to handle this cell or handled it internally without replacing it. The original cell is kept. updated_plugin_state is stored. Allows other plugins to potentially process the same cell.

handle_input(plugin_state, input)

(optional)
@callback handle_input(plugin_state :: term(), input :: String.t()) ::
  {:ok, term()} | {:error, String.t()}

handle_mouse(plugin_state, event, emulator_state)

(optional)
@callback handle_mouse(
  plugin_state :: term(),
  event :: tuple(),
  emulator_state :: map()
) :: {:ok, struct()} | {:error, reason :: term()}

handle_output(plugin_state, output)

(optional)
@callback handle_output(plugin_state :: term(), output :: String.t()) ::
  {:ok, term()} | {:error, String.t()}

handle_render(plugin_state)

(optional)
@callback handle_render(plugin_state :: struct()) ::
  {:ok, struct(), binary() | nil} | {:ok, struct()} | binary() | :ok

Optional callback executed just before the terminal buffer is presented. Allows plugins to inject direct output commands (e.g., escape sequences).

Should return:

  • {:ok, updated_plugin_state, command_to_write} - If state changes and command is output.
  • {:ok, updated_plugin_state} - If state changes but no command is output.
  • command_to_write - If only a command is output (state unchanged).
  • :ok - If nothing needs to be done.

handle_resize(plugin_state, width, height)

(optional)
@callback handle_resize(
  plugin_state :: term(),
  width :: non_neg_integer(),
  height :: non_neg_integer()
) :: {:ok, struct()} | {:error, reason :: term()}

init(config)

@callback init(config :: map()) :: {:ok, term()} | {:error, String.t()}