Vim uses registers to store copied text and paste from, rather than the system clipboard. When copy-pasting from another app, this isn't ideal, since the clipboard is inaccessible within Vim.
To avoid this, the clipboard flag needs to be set. To check it, run
$ vim --version
This output contains all the flags that are set. If you see +clipboard, you're good. Otherwise, you'll have to recompile Vim with this flag, but the easier solution would be to additionally install vim-gtk3.
Then, add
set clipboard=unnamedplus
to your ~/.vimrc.
The problem
The above solution used to work on X11, but it only partially works on Wayland.
Yanking text copies it to the clipboard, but pasting still uses Vim's internal register. Even explicitly pasting from the clipboard register with "+p doesn't work.
If you are also facing this issue, check whether wayland and wayland_clipboard flags are set. If they aren't present, clipboard functionality wont properly.
The solution
This solution is meant for KDE Plasma, since it uses qdbus. An alternative solution is also provided below.
The output of
$ qdbus6 org.kde.klipper /klipper getClipboardContents
shows the last copied clipboard content followed by a line break. We could just directly use this command via command-line mode in Vim, but the trailing newline causes problems. When pasting the same text multiple times, these unnecessary line breaks add up in between.
To avoid this, a custom script can be utilized to format the output. Within /usr/bin, create a script called kpaste.
#!/bin/bash
REAL_USER="${SUDO_USER:-$(logname)}"
REAL_UID=$(id -u "$REAL_USER")
DBUS_ADDR="unix:path=/run/user/$REAL_UID/bus"
if [ "$EUID" -eq 0 ]; then
exec sudo -u "$REAL_USER" DBUS_SESSION_BUS_ADDRESS="$DBUS_ADDR" "$0"
fi
echo -n "$(qdbus6 org.kde.klipper /klipper getClipboardContents)"
Only the last line is required if the script is run as a regular user, but if we're editing a file as sudo (via sudo -E vim), the script won't work since root doesn't have access to the user's clipboard.
Therefore, we obtain the current user's name (REAL_USER), which is used to find their UID (REAL_UID), which finally allows us to connect to their DBus (DBUS_ADDR).
If the script is run as sudo, then call it again as the current user. Otherwise, call the clipboard normally.
Make it executable with
$ chmod +x /usr/bin/kpaste
Now, add the below line to ~/.vimrc to remap in normal mode.
nnoremap p :let @0=system("kpaste")<CR>"0gp
So what does it do?
nnoremap p: Assign a custom mapping to p in normal mode.
:let @0=system("kpaste")<CR>: Copy the output of kpaste to Vim's clipboard register "0 (which is the register for the yank operation, though you can also use any other register).
"0gp: Paste from the clipboard register after the cursor. If using just "0p, pasting text that contains line breaks would place the cursor at the beginning of the pasted text, rather than at the end as expected. To avoid this, we use "0gp.
To remap in visual mode,
vnoremap p :<C-U>let @0 = system("kpaste")<CR>gv"_d"0gp
In addition to the above explanation,
:<C-U>: Removes the visual range '<,'> so :let works.
gv: Reselect the previous selection.
"_d: Delete into the black hole register.
This also pastes after the cursor. To paste before the cursor, replace p with P in the above mappings.
This restores complete clipboard functionality!
Alternative solution
If you're not on Plasma, install wl-clipboard. This package provides the command wl-paste, which pastes the last copied item from the clipboard. As mentioned above, create an additional script that echoes the output without a newline, and remap p correspondingly.
However, I wouldn't recommend this method, since the output when the clipboard is empty is
$ wl-paste
Nothing is copied
This causes the text "Nothing is copied" to be pasted into Vim. An additional check would be needed to output nothing in this situation 🙃.
Top comments (0)