Files
universal-clipboard.nvim/README.md
T

5.0 KiB
Raw Blame History

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:

use({
  "swaits/universal-clipboard.nvim",
  config = function()
    require("universal-clipboard").setup({
      verbose = false, -- optional: set true to log detection details
    })
  end,
})

Or lazy.nvim:

{
  "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

{
  -- 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:

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