Sessions inside tmux used to skip the clipboard provider entirely, so yanks only reached the machine's own Wayland clipboard and never traveled over OSC 52 to clients attached via SSH. Now every copy also emits OSC 52, which tmux turns into a buffer and rebroadcasts to all attached clients. Paste prefers wl-paste when a display is available. This also drops the private-file fallback clipboard and its regtype sidecar: Neovim's built-in clipboard layer already restores the register type when pasted content matches its cache, and OSC 52 queries answered by tmux cover the display-less paste case. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
100 lines
2.5 KiB
Lua
100 lines
2.5 KiB
Lua
-- Clipboard for sessions whose yanks may need to reach another machine:
|
|
-- every copy is emitted as OSC 52 (inside tmux this becomes a tmux buffer,
|
|
-- rebroadcast to every attached client, local or SSH). Paste prefers the
|
|
-- local Wayland clipboard when one is available, so content copied in other
|
|
-- apps remains pasteable; without a display, paste is an OSC 52 query that
|
|
-- tmux (or the terminal) answers.
|
|
local M = {}
|
|
|
|
local function proc_lines(pid, file)
|
|
local ok, lines = pcall(vim.fn.readfile, "/proc/" .. pid .. "/" .. file)
|
|
return ok and lines or {}
|
|
end
|
|
|
|
local function proc_ppid(pid)
|
|
for _, line in ipairs(proc_lines(pid, "status")) do
|
|
local ppid = line:match("^PPid:%s+(%d+)")
|
|
if ppid then
|
|
return tonumber(ppid)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function ancestor_process_named(name)
|
|
local pid = vim.fn.getpid()
|
|
|
|
for _ = 1, 16 do
|
|
local ppid = proc_ppid(pid)
|
|
if not ppid or ppid <= 1 then
|
|
return false
|
|
end
|
|
|
|
local comm = proc_lines(ppid, "comm")[1] or ""
|
|
if comm:find(name, 1, true) then
|
|
return true
|
|
end
|
|
|
|
pid = ppid
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function M.setup()
|
|
local in_tmux = vim.env.TMUX ~= nil
|
|
local in_ssh = vim.env.SSH_TTY ~= nil or vim.env.SSH_CONNECTION ~= nil
|
|
local in_herdr = vim.env.HERDR_PANE_ID ~= nil or ancestor_process_named("herdr")
|
|
|
|
if not (in_tmux or in_ssh or in_herdr) then
|
|
return
|
|
end
|
|
|
|
local osc52 = require("vim.ui.clipboard.osc52")
|
|
local has_wayland = vim.env.WAYLAND_DISPLAY ~= nil
|
|
and vim.fn.executable("wl-copy") == 1
|
|
and vim.fn.executable("wl-paste") == 1
|
|
|
|
local function copy(register)
|
|
local emit = osc52.copy(register)
|
|
|
|
return function(lines)
|
|
if has_wayland then
|
|
local cmd = { "wl-copy", "--sensitive", "--type", "text/plain" }
|
|
if register == "*" then
|
|
cmd[#cmd + 1] = "--primary"
|
|
end
|
|
vim.fn.system(cmd, lines)
|
|
end
|
|
|
|
if vim.g.omarchy_remote_clipboard_osc52 ~= false then
|
|
emit(lines)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function paste(register)
|
|
if not has_wayland then
|
|
return osc52.paste(register)
|
|
end
|
|
|
|
return function()
|
|
local cmd = { "wl-paste", "--no-newline" }
|
|
if register == "*" then
|
|
cmd[#cmd + 1] = "--primary"
|
|
end
|
|
|
|
local lines = vim.fn.systemlist(cmd, "", 1)
|
|
return vim.v.shell_error == 0 and lines or {}
|
|
end
|
|
end
|
|
|
|
vim.g.clipboard = {
|
|
name = "OmarchyRemoteClipboard",
|
|
copy = { ["+"] = copy("+"), ["*"] = copy("*") },
|
|
paste = { ["+"] = paste("+"), ["*"] = paste("*") },
|
|
cache_enabled = 0,
|
|
}
|
|
end
|
|
|
|
return M
|