Skip to content

Clipboard

Feature Flag

The clipboard is enabled by default via the clipboard feature (backed by arboard):

toml
# Default: clipboard enabled (no extra config needed)
tui-lipan = { version = "*" }

# Opt out for minimal builds with no system clipboard dependency
tui-lipan = { version = "*", default-features = false }

# Re-enable clipboard alongside other features
tui-lipan = { version = "*", default-features = false, features = ["clipboard", "image"] }

When the clipboard feature is disabled, all clipboard operations silently return ClipboardError::Unsupported - the API surface is identical.

ClipboardConfig

Configure clipboard behavior via App::clipboard_config(...):

rust
use tui_lipan::prelude::*;

App::new()
    .clipboard_config(ClipboardConfig {
        enable_performable_ctrl_c_copy: true,  // Bind Ctrl+C to copy when selection exists
        enable_primary_selection: true,         // X11 primary selection
        paste_shift_insert_behavior: PasteShiftInsertBehavior::PrimarySelection,
        paste_max_bytes: 1_000_000,            // Clamp large text pastes
        enable_osc52: true,                    // OSC52 for SSH clipboard
        paste_max_image_bytes: 10_000_000,     // Clamp large image pastes (default 10MB)
    })
    .mount(Root)
    .run()
FieldTypeDefaultPurpose
enable_performable_ctrl_c_copybooltrueBind Ctrl+C to copy when selection exists; otherwise it falls through
enable_primary_selectionboolplatformEnable X11 primary (middle-click) clipboard
paste_shift_insert_behaviorPasteShiftInsertBehaviorplatformPrimarySelection or Clipboard
paste_max_bytesusizeunboundedClamp large text pastes to avoid stalls
enable_osc52boolfalseEmit OSC52 escape on copy/cut (useful over SSH)
paste_max_image_bytesusize10MBClamp large image pastes

All clipboard shortcuts are performable by default: copy/cut only consume when a selection exists, and paste only consumes when the focused widget can accept pasted content. Ctrl+C also copies any active mouse selection from Input, TextArea, DocumentView, or Terminal, even when those widgets are not focusable. Otherwise the key falls through to app-level handlers.

For DocumentView, when siblings inside the same ScrollView share shared_selection_id, Ctrl+C copies a single concatenated selection for that shared group (in visual order). Groups with different ids are copied independently.

Programmatic Access

Use ctx.clipboard() from any component to copy or read text programmatically:

rust
fn update(&mut self, msg: Msg, ctx: &mut Context<Self>) -> Update {
    match msg {
        Msg::CopyClicked => {
            if let Err(e) = ctx.clipboard().copy("copied text") {
                ctx.toast().error(format!("Copy failed: {e}"));
            }
        }
        Msg::Paste => {
            match ctx.clipboard().read() {
                Ok(text) => { /* use text */ }
                Err(e) => { /* handle error */ }
            }
        }
    }
    Update::default()
}

ClipboardHandle returned by ctx.clipboard() respects the app-level ClipboardConfig - it automatically emits OSC 52 when enabled and writes to the primary selection on supported platforms.

Image Clipboard (requires feature image)

rust
use tui_lipan::{ImageContent, ImageFormat};

Reading images from clipboard is handled automatically by TextArea when image callbacks are set. When the user pastes and the clipboard contains an image, the framework invokes the on_images_change or on_image_paste callback with the decoded ImageContent.

TextArea image integration (recommended pattern):

rust
// Inline mode: sentinel chars in text value
TextArea::new(self.input.clone())
    .image_mode(TextAreaImageMode::Inline)
    .images(self.images.clone())
    .on_images_change(ctx.link().callback(Msg::ImagesChanged))
    .image_placeholder("[Img]")
    .image_placeholder_style(Style::new().fg(Color::Magenta).bold())

ImageContent API:

rust
let content: ImageContent = ...;
content.mime      // e.g. "image/png"
content.data      // base64-encoded string

// Decode to raw bytes
let bytes = content.to_bytes()?;
let arc_bytes: Arc<[u8]> = Arc::from(bytes.as_slice());

// Use with Image widget
Image::from_bytes(arc_bytes)

ImageFormat: ImageFormat::Png, ImageFormat::Jpeg

Images are automatically converted to/from RGBA format for clipboard compatibility. Supported on Linux (X11/Wayland), macOS, and Windows.

TextArea Image Modes

See docs/widgets/input.md for complete TextAreaImageMode documentation.

ModeBehavior
TextAreaImageMode::InlineImages embedded as Unicode PUA sentinels in text value
TextAreaImageMode::AttachmentImages appended to separate list; text value unchanged

Image pasting is opt-in: only active when on_images_change or on_image_paste is set on TextArea.

MIT OR Apache-2.0