210 lines
5.0 KiB
Markdown
210 lines
5.0 KiB
Markdown
# universal-clipboard.nvim
|
||
|
||
A **minimal** Neovim plugin that automatically sets up sharing your **system
|
||
clipboard** across multiple platforms. It addresses this issue:
|
||
|
||
> **Platform Differences**: On macOS, Neovim appears to behave nicely with the
|
||
> system `clipboard`. On others, not so much. External tools can help. For
|
||
> example, there’s `wl-copy`/`wl-paste` for Wayland or `xclip`/`xsel` for X11.
|
||
|
||
With **universal-clipboard.nvim**:
|
||
|
||
- If we detect an external clipboard tool (`wl-clipboard`, `xclip`, `xsel`),
|
||
we configure Neovim’s `clipboard` to use it.
|
||
- Otherwise, we simply set `clipboard` to `unnamedplus` with no further
|
||
configuration needed.
|
||
|
||
## Installation
|
||
|
||
Using [**packer.nvim**](https://github.com/wbthomason/packer.nvim):
|
||
|
||
```lua
|
||
use({
|
||
"swaits/universal-clipboard.nvim",
|
||
config = function()
|
||
require("universal-clipboard").setup({
|
||
verbose = false, -- optional: set true to log detection details
|
||
})
|
||
end,
|
||
})
|
||
```
|
||
|
||
Or [**lazy.nvim**](https://github.com/folke/lazy.nvim):
|
||
|
||
```lua
|
||
{
|
||
"swaits/universal-clipboard.nvim",
|
||
opts = {
|
||
verbose = true, -- optional: set true to log detection details
|
||
},
|
||
}
|
||
```
|
||
|
||
> **Note**: If your Neovim lacks `+clipboard`, make sure you have at least one
|
||
> of `wl-clipboard`, `xclip`, or `xsel` installed. Or you may customize the
|
||
> tools searched -- see below.
|
||
|
||
---
|
||
|
||
## Default Options
|
||
|
||
```lua
|
||
{
|
||
-- Whether to log stuff to the vim console
|
||
verbose = false,
|
||
|
||
-- Copy/paste tools to check for
|
||
tools = {
|
||
-- macOS clipboard
|
||
{
|
||
name = "pbcopy",
|
||
detect = function()
|
||
return vim.fn.executable("pbcopy") == 1 and vim.fn.executable("pbpaste") == 1
|
||
end,
|
||
commands = {
|
||
copy = "pbcopy",
|
||
paste = "pbpaste",
|
||
},
|
||
},
|
||
-- Wayland and wl-copy/wl-paste
|
||
{
|
||
name = "wl-clipboard",
|
||
detect = function()
|
||
local wayland_display = os.getenv("WAYLAND_DISPLAY")
|
||
local wayland_runtime = os.getenv("XDG_RUNTIME_DIR")
|
||
local socket_path = (wayland_runtime or "") .. "/" .. (wayland_display or "")
|
||
return (vim.fn.executable("wl-copy") == 1)
|
||
and (vim.fn.executable("wl-paste") == 1)
|
||
and wayland_display ~= ""
|
||
and (vim.fn.filereadable(socket_path) == 1)
|
||
end,
|
||
commands = {
|
||
copy = "wl-copy",
|
||
paste = "wl-paste --no-newline",
|
||
},
|
||
},
|
||
-- Alternative Wayland tools
|
||
{
|
||
name = "waycopy",
|
||
detect = function()
|
||
local wayland_display = os.getenv("WAYLAND_DISPLAY")
|
||
return vim.fn.executable("waycopy") == 1
|
||
and vim.fn.executable("waypaste") == 1
|
||
and wayland_display ~= nil
|
||
end,
|
||
commands = {
|
||
copy = "waycopy",
|
||
paste = "waypaste --no-newline",
|
||
},
|
||
},
|
||
-- X11 and xclip
|
||
{
|
||
name = "xclip",
|
||
detect = "xclip", -- Just a string, means "check if `xclip` is executable"
|
||
commands = {
|
||
copy = "xclip -selection clipboard",
|
||
paste = "xclip -selection clipboard -o",
|
||
},
|
||
},
|
||
-- X11 and xsel
|
||
{
|
||
name = "xsel",
|
||
detect = "xsel",
|
||
commands = {
|
||
copy = "xsel --clipboard --input",
|
||
paste = "xsel --clipboard --output",
|
||
},
|
||
},
|
||
-- tmux clipboard
|
||
{
|
||
name = "tmux",
|
||
detect = function()
|
||
return os.getenv("TMUX") ~= nil and vim.fn.executable("tmux") == 1
|
||
end,
|
||
commands = {
|
||
copy = "tmux load-buffer -",
|
||
paste = "tmux save-buffer -",
|
||
},
|
||
},
|
||
-- Lemonade (SSH)
|
||
{
|
||
name = "lemonade",
|
||
detect = "lemonade",
|
||
commands = {
|
||
copy = "lemonade copy",
|
||
paste = "lemonade paste",
|
||
},
|
||
},
|
||
-- DoIt client (SSH)
|
||
{
|
||
name = "doitclient",
|
||
detect = "doitclient",
|
||
commands = {
|
||
copy = "doitclient wclip",
|
||
paste = "doitclient rclip",
|
||
},
|
||
},
|
||
-- Windows win32yank
|
||
{
|
||
name = "win32yank",
|
||
detect = "win32yank.exe",
|
||
commands = {
|
||
copy = "win32yank.exe -i --crlf",
|
||
paste = "win32yank.exe -o --lf",
|
||
},
|
||
},
|
||
},
|
||
}
|
||
```
|
||
|
||
### Customizing Tools
|
||
|
||
If you want to add or remove tools, you can override the `tools` table in your
|
||
`setup()` call. For example:
|
||
|
||
```lua
|
||
require("universal-clipboard").setup({
|
||
verbose = true,
|
||
tools = {
|
||
-- If you only want xclip, for instance:
|
||
{
|
||
name = "xclip-only",
|
||
detect = "xclip",
|
||
commands = {
|
||
copy = "xclip -selection clipboard",
|
||
paste = "xclip -selection clipboard -o",
|
||
},
|
||
},
|
||
-- Or add more custom entries
|
||
},
|
||
})
|
||
```
|
||
|
||
The plugin will iterate over `tools` in order and select the first one that is
|
||
“available.”
|
||
|
||
---
|
||
|
||
## Usage
|
||
|
||
Once installed, **no additional steps** are required. The plugin configures your
|
||
clipboard on startup. Simply copy and paste in Neovim as usual.
|
||
|
||
### Commands
|
||
|
||
- **`:UniversalClipboardCheck`**
|
||
Prints the current `clipboard` configuration to the command line, showing what
|
||
`vim.opt.clipboard` and `vim.g.clipboard` are set to.
|
||
|
||
- **`:UniversalClipboardReinit`**
|
||
Re-runs the detection logic, forcing `verbose` mode for that run to help
|
||
troubleshoot. You normally do **not** need this, but it can be helpful if you
|
||
install a new system tool _after_ starting Neovim and want to see if it’s
|
||
detected.
|
||
|
||
---
|
||
|
||
## License
|
||
|
||
[MIT License](LICENSE)
|