runex 0.1.14

Cross-shell abbreviation engine that expands short tokens into full commands
//! `runex paste-clipboard` — read the system clipboard and write the
//! text to stdout.
//!
//! Hidden subcommand. The only intended caller is the nu Ctrl+V
//! binding generated by `app::shell_export` when
//! `[keybind.paste_intercept]` is set. The binding pipes our stdout
//! into `commandline edit --insert`, which means a clipboard paste
//! lands in the buffer **without** going through the per-keystroke
//! abbreviation trigger — sidestepping the paste-mid-trigger
//! limitation documented in `domain/templates/nu.nu`.
//!
//! Empty clipboard / no text format on the clipboard returns an
//! empty stdout and exit 0; the nu binding's `is-empty` check then
//! no-ops the insert. Provider failures (no xclip / wl-paste / etc.)
//! print a hint to stderr and exit 1, so the user sees what to
//! install rather than getting a silent no-op.

use std::io::{self, Write};

use crate::infra::clipboard::{read_clipboard_text, ClipboardError};
use crate::{CmdOutcome, CmdResult};

pub(crate) fn handle() -> CmdResult {
    match read_clipboard_text() {
        Ok(text) => {
            // `write_all` (not `println!`) keeps embedded newlines
            // and the final byte exactly as the clipboard delivered
            // them. The nu binding `commandline edit --insert` accepts
            // multi-line strings, so we must not normalise.
            io::stdout().write_all(text.as_bytes())?;
            Ok(CmdOutcome::Ok)
        }
        Err(ClipboardError::NoProvider) => {
            eprintln!(
                "runex paste-clipboard: no clipboard provider found. \
                 On Linux install xclip, wl-clipboard, or xsel; \
                 on WSL ensure powershell.exe is on PATH; \
                 on macOS pbpaste is built in."
            );
            Ok(CmdOutcome::ExitCode(1))
        }
        Err(e) => {
            eprintln!("runex paste-clipboard: {e}");
            Ok(CmdOutcome::ExitCode(1))
        }
    }
}