import { execFile } from "node:child_process"; import { promisify } from "node:util"; import * as Clipboard from "@mariozechner/clipboard"; const execFileAsync = promisify(execFile); const COMMAND_TIMEOUT_MS = 5_000; const MAX_BUFFER_BYTES = 20 * 1024 * 1024; export async function readClipboardText(): Promise { const nativeText = await readClipboardTextViaNative(); if (nativeText !== undefined) { return nativeText; } return await readClipboardTextViaCommands(process.platform, process.env); } async function readClipboardTextViaNative(): Promise { try { if (!Clipboard.hasText()) { return undefined; } return await Clipboard.getText(); } catch { return undefined; } } async function readClipboardTextViaCommands( platform: NodeJS.Platform, env: NodeJS.ProcessEnv, ): Promise { if (env.TERMUX_VERSION) { return await runCommand("termux-clipboard-get", []); } if (platform === "darwin") { return await runCommand("pbpaste", []); } if (platform === "win32") { return await runCommand("powershell.exe", ["-NoProfile", "-Command", "Get-Clipboard -Raw"]); } if (platform === "linux") { if (isWSL(env)) { const windowsClipboard = await runCommand("powershell.exe", ["-NoProfile", "-Command", "Get-Clipboard -Raw"]); if (windowsClipboard !== undefined) { return windowsClipboard; } } if (env.WAYLAND_DISPLAY || env.XDG_SESSION_TYPE === "wayland") { const waylandClipboard = await runCommand("wl-paste", ["--no-newline"]); if (waylandClipboard !== undefined) { return waylandClipboard; } } if (env.DISPLAY) { const xclipClipboard = await runCommand("xclip", ["-selection", "clipboard", "-out"]); if (xclipClipboard !== undefined) { return xclipClipboard; } const xselClipboard = await runCommand("xsel", ["--clipboard", "--output"]); if (xselClipboard !== undefined) { return xselClipboard; } } } return undefined; } async function runCommand(command: string, args: string[]): Promise { try { const { stdout } = await execFileAsync(command, args, { encoding: "utf8", timeout: COMMAND_TIMEOUT_MS, maxBuffer: MAX_BUFFER_BYTES, windowsHide: true, }); return typeof stdout === "string" ? stdout : String(stdout); } catch { return undefined; } } function isWSL(env: NodeJS.ProcessEnv): boolean { return Boolean(env.WSL_DISTRO_NAME || env.WSLENV); }