Raxol.Terminal.Input.ClipboardHandler (Raxol v2.0.1)

View Source

Handles clipboard operations for the terminal emulator.

Supports both local system clipboard operations and OSC 52 escape sequences for remote clipboard access over SSH and other terminal connections.

OSC 52 Support

OSC 52 allows applications to read from and write to the system clipboard even when running over SSH or in remote terminal sessions. This module can generate OSC 52 sequences to communicate clipboard operations to compatible terminal emulators.

Features

  • Local system clipboard integration (pbcopy/pbpaste, xclip, etc.)
  • OSC 52 escape sequences for remote clipboard access
  • Base64 encoding/decoding for OSC 52 payloads
  • Bracketed paste mode support
  • Security controls and size limits

Summary

Functions

Detects if a terminal supports OSC 52 based on environment variables.

Disables bracketed paste mode.

Enables bracketed paste mode by generating the appropriate escape sequence.

Generates an OSC 52 escape sequence to copy text to the system clipboard.

Generates an OSC 52 escape sequence to query the system clipboard.

Handles clipboard operations with automatic fallback between local and OSC 52.

Handles clipboard copy operation. (Currently copies the entire buffer)

Handles clipboard cut operation. (Currently cuts the entire buffer)

Handles clipboard paste operation.

Parses an OSC 52 response from the terminal.

Functions

detect_osc52_support()

@spec detect_osc52_support() :: :supported | :unsupported | :unknown

Detects if a terminal supports OSC 52 based on environment variables.

Returns

  • :supported - Terminal likely supports OSC 52
  • :unsupported - Terminal likely does not support OSC 52
  • :unknown - Cannot determine terminal capabilities

disable_bracketed_paste()

@spec disable_bracketed_paste() :: binary()

Disables bracketed paste mode.

Returns

  • binary() - Escape sequence to disable bracketed paste mode

enable_bracketed_paste()

@spec enable_bracketed_paste() :: binary()

Enables bracketed paste mode by generating the appropriate escape sequence.

Bracketed paste mode allows terminals to distinguish between typed text and pasted text, preventing issues with automatic indentation and other editor features.

Returns

  • binary() - Escape sequence to enable bracketed paste mode

generate_osc52_copy(text, options \\ %{})

@spec generate_osc52_copy(String.t(), map()) :: {:ok, binary()} | {:error, term()}

Generates an OSC 52 escape sequence to copy text to the system clipboard.

This is useful for remote terminal sessions where direct clipboard access is not available (such as over SSH).

Parameters

  • text - Text to copy to clipboard
  • options - Options map with optional keys:
    • :target - Clipboard target (default: :clipboard)
    • :max_length - Maximum length to copy (default: @max_osc_52_length)

Returns

  • {:ok, osc_sequence} - OSC 52 escape sequence to send to terminal
  • {:error, reason} - Error if text is too long or other issues

Examples

iex> ClipboardHandler.generate_osc52_copy("Hello, World!")
{:ok, "]52;c;SGVsbG8sIFdvcmxkIQ==\"}

iex> ClipboardHandler.generate_osc52_copy("test", target: :primary)
{:ok, "]52;p;dGVzdA==\"}

generate_osc52_query(target \\ :clipboard)

@spec generate_osc52_query(atom()) :: {:ok, binary()} | {:error, term()}

Generates an OSC 52 escape sequence to query the system clipboard.

Parameters

  • target - Clipboard target to query (default: :clipboard)

Returns

  • {:ok, osc_sequence} - OSC 52 query sequence to send to terminal
  • {:error, reason} - Error for invalid target

Examples

iex> ClipboardHandler.generate_osc52_query()
{:ok, "]52;c;?\"}

iex> ClipboardHandler.generate_osc52_query(:primary)
{:ok, "]52;p;?\"}

handle_clipboard_with_fallback(operation, text \\ nil, options \\ %{})

@spec handle_clipboard_with_fallback(atom(), String.t() | nil, map()) ::
  {:ok, term()} | {:error, term()}

Handles clipboard operations with automatic fallback between local and OSC 52.

Attempts local clipboard access first, falls back to OSC 52 if running in a remote session or if local access fails.

Parameters

  • operation - :copy or :paste
  • text - Text to copy (required for :copy, ignored for :paste)
  • options - Options including :force_osc52 to skip local clipboard

Returns

  • For copy: {:ok, output} where output is either :ok or an OSC 52 sequence
  • For paste: {:ok, text} or {:error, :paste_not_supported_osc52}

handle_copy(handler)

@spec handle_copy(Raxol.Terminal.Input.CoreHandler.t()) ::
  {:ok, Raxol.Terminal.Input.CoreHandler.t()} | {:error, any()}

Handles clipboard copy operation. (Currently copies the entire buffer)

handle_cut(handler)

@spec handle_cut(Raxol.Terminal.Input.CoreHandler.t()) ::
  {:ok, Raxol.Terminal.Input.CoreHandler.t()} | {:error, any()}

Handles clipboard cut operation. (Currently cuts the entire buffer)

handle_paste(handler)

@spec handle_paste(Raxol.Terminal.Input.CoreHandler.t()) ::
  {:ok, Raxol.Terminal.Input.CoreHandler.t()} | {:error, any()}

Handles clipboard paste operation.

parse_osc52_response(response)

@spec parse_osc52_response(binary()) :: {:ok, {atom(), String.t()}} | {:error, term()}

Parses an OSC 52 response from the terminal.

When a terminal responds to an OSC 52 query, it sends back the clipboard contents as a base64-encoded string. This function decodes the response.

Parameters

  • osc_response - Raw OSC 52 response from terminal

Returns

  • {:ok, {target, text}} - Decoded clipboard target and text
  • {:error, reason} - Error if response is malformed

Examples

iex> ClipboardHandler.parse_osc52_response("]52;c;SGVsbG8=\")
{:ok, {:clipboard, "Hello"}}