# OSC52: My Cut & Paste Journey


In the olden days with X11, you could just do x11-forwarding in SSH and remote cut and paste would
work. Now with Wayland, this is all broken and supposedly "there are better ways of doing it". One
of those is
[OSC52](https://www.reddit.com/r/vim/comments/k1ydpn/a_guide_on_how_to_copy_text_from_anywhere/)
support in terminals, but not in [VTE](https://wiki.gnome.org/Apps/Terminal/VTE) based ones, like
[Tilix](https://gnunn1.github.io/tilix-web/), which <strike>is</strike> was my default terminal.
(See https://gitlab.gnome.org/GNOME/vte/-/issues/2495 for the 5(!) year old bug).

So I wanted this to work, which meant changing terminal and configuring Neovim - where the latter
was way more complex, hard to debug and reason about.

## Foot Terminal

Foot is available in Debian/Ubuntu, and looked like a nice alternative. However it doesn't register
itself as a x-terminal-emulator alternative, which can be fixed with:

~~~ sh
sudo update-alternatives --install /usr/bin/x-terminal-emulator x-terminal-emulator /usr/bin/foot 100
~~~

And then:

~~~ sh
sudo update-alternatives --config x-terminal-emulator
~~~

To select foot. Then configure it to your liking. Because it's not a GTK-based terminal I've mostly
disabled any decorations, only a border, a tiny menu bar and hiding the buttons.

~~~ ini
[csd]
border-width=2
border-color=ff404040
color=ff404040
size=12
button-width=0
~~~

## Neovim

In Neovim (0.9.5, 0.10 has builtin support... no idea if the following will then need to be updated
-- again):

With your plugin manager, have ojroques/nvim-osc52 included and add the following Lua config:

~~~ lua
require('osc52').setup {
  max_length = 0,
  silent = false,
  trim = true,
  tmux_passthrough = false,
}
local function copy(lines, _)
  require('osc52').copy(table.concat(lines, '\n'))
end

local function paste()
  return {vim.fn.split(vim.fn.getreg(''), '\n'), vim.fn.getregtype('')}
end

vim.g.clipboard = {
  name = 'osc52',
  copy = {['+'] = copy, ['*'] = copy},
  paste = {['+'] = paste, ['*'] = paste},
}
~~~

Next set `set clipboard=unnamed`.
This has the effect that y and p use the register + or * (dunno - it works). The `silent=false` gives me
some feedback this OSC52 stuff is working.

All the other things that you can find didn't work for, did nothing, or I needed to type "+p and "+y
like a farmer to paste and copy.

Anyway, the above works *for me*, *for now*.

## Update 2024-12-31

With Neovim (0.10.3) I'm using the following, which *should* transparently work once I have a
terminal (*cough* [ghostty](https://ghostty.org/)) that supports OSC52 and looks good in GNOME.

It basically makes all yank and paste commands use the `+` (system clipboard) register. This does
need `wl-clipboard` or anything else that can interact with the clipboard.

Added benefit is that yank and paste between *local* nvim sessions also works again, I was/am using
the mouse for this....

~~~ vim
" clear clipboard, needed to autom. enable osc52 once available
set clipboard=

" remap the y and p commands I use to use the "+" reg explicitly
nnoremap y "+y
nnoremap p "+p
nnoremap x "+x
nnoremap d "+d
nnoremap Y "+yy
nnoremap dd "+dd

vnoremap y "+y
vnoremap d "+d
vnoremap Y "+yy
~~~

## Update 2025-01-01

After installing ghostty and configuring it for OSC52 - the promised world from above now works
for me. **For now**.

Using the following config in ghostty:

~~~ txt
...
clipboard-read = allow
clipboard-write = allow
copy-on-select = clipboard
...
~~~

And in neovim using key mapping to use the '+' register:

~~~ vim
nnoremap y "+y
nnoremap p "+p
nnoremap P "+P
nnoremap x "+x
nnoremap X "+X
nnoremap d "+d
nnoremap Y "+yy
nnoremap dd "+dd

vnoremap y "+y
vnoremap d "+d
vnoremap x "+x
vnoremap X "+X
vnoremap Y "+yy
~~~

Annoyingly I then run into this [neovim? bug?](https://github.com/neovim/neovim/issues/25180), but I
can live with that.

## Update 2025-05-07

I've moved my neovim configuration to [NvChad](https://nvchad.com/) (although I'm not using very
much of it). But I don't need the above mappings anymore, and I have:

~~~ lua
local g = vim.g

o.clipboard = "unnamedplus"
g.clipboard = {
	name = "OSC 52",
	copy = {
		["+"] = require("vim.ui.clipboard.osc52").copy("+"),
		["*"] = require("vim.ui.clipboard.osc52").copy("*"),
	},
	paste = {
		["+"] = require("vim.ui.clipboard.osc52").paste("+"),
		["*"] = require("vim.ui.clipboard.osc52").paste("*"),
	},
}
~~~

... and this, with maybe some mappings on the NvChad side, makes everything work beautifully. This
is with neovim 0.11 and higher.

