refactor: move clipboard tools to search fo into opts
This commit is contained in:
2 files changed
+185
-87
No files matched your search
@@ -10,8 +10,9 @@ clipboard** across multiple platforms. It addresses this issue:
|
|||||||
With **universal-clipboard.nvim**:
|
With **universal-clipboard.nvim**:
|
||||||
|
|
||||||
- If we detect an external clipboard tool (`wl-clipboard`, `xclip`, `xsel`),
|
- If we detect an external clipboard tool (`wl-clipboard`, `xclip`, `xsel`),
|
||||||
we configure the `clipboard` to use it.
|
we configure Neovim’s `clipboard` to use it.
|
||||||
- Otherwise, we simply set it to `unnamedplus` with no further configuration.
|
- Otherwise, we simply set `clipboard` to `unnamedplus` with no further
|
||||||
|
configuration needed.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ use({
|
|||||||
"swaits/universal-clipboard.nvim",
|
"swaits/universal-clipboard.nvim",
|
||||||
config = function()
|
config = function()
|
||||||
require("universal-clipboard").setup({
|
require("universal-clipboard").setup({
|
||||||
verbose = false, -- optional, set true to see a small startup message
|
verbose = false, -- optional: set true to log detection details
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@@ -34,33 +35,109 @@ Or [**lazy.nvim**](https://github.com/folke/lazy.nvim):
|
|||||||
{
|
{
|
||||||
"swaits/universal-clipboard.nvim",
|
"swaits/universal-clipboard.nvim",
|
||||||
opts = {
|
opts = {
|
||||||
verbose = true, -- optional, set true to see a small startup message
|
verbose = true, -- optional: set true to log detection details
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note:** If your Neovim lacks `+clipboard`, make sure you have at least one
|
> **Note**: If your Neovim lacks `+clipboard`, make sure you have at least one
|
||||||
> of `wl-clipboard`, `xclip`, or `xsel` is installed.
|
> of `wl-clipboard`, `xclip`, or `xsel` installed. Or you may customize the
|
||||||
|
> tools searched -- see below.
|
||||||
|
|
||||||
### Default Options
|
---
|
||||||
|
|
||||||
|
## Default Options
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
{
|
{
|
||||||
-- If true, prints the chosen clipboard mode at startup
|
-- If true, prints the chosen clipboard mode/tool at startup
|
||||||
verbose = false,
|
verbose = false,
|
||||||
|
|
||||||
|
-- A table of tools to check, in order
|
||||||
|
tools = {
|
||||||
|
{
|
||||||
|
name = "wl-clipboard",
|
||||||
|
-- Either a string (the executable name) or a function returning boolean
|
||||||
|
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.isdirectory(socket_path) == 1)
|
||||||
|
end,
|
||||||
|
commands = {
|
||||||
|
copy = "wl-copy",
|
||||||
|
paste = "wl-paste --no-newline",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "xclip",
|
||||||
|
detect = "xclip", -- Will check vim.fn.executable("xclip")
|
||||||
|
commands = {
|
||||||
|
copy = "xclip -selection clipboard",
|
||||||
|
paste = "xclip -selection clipboard -o",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "xsel",
|
||||||
|
detect = "xsel",
|
||||||
|
commands = {
|
||||||
|
copy = "xsel --clipboard --input",
|
||||||
|
paste = "xsel --clipboard --output",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 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
|
## Usage
|
||||||
|
|
||||||
Once installed, **no additional steps** are needed. The plugin configures your
|
Once installed, **no additional steps** are required. The plugin configures your
|
||||||
clipboard on startup. Simply copy and paste in Neovim as usual.
|
clipboard on startup. Simply copy and paste in Neovim as usual.
|
||||||
|
|
||||||
### Commands
|
### Commands
|
||||||
|
|
||||||
- `:UniversalClipboardCheck` - Shows the current `clipboard` configuration.
|
- **`:UniversalClipboardCheck`**
|
||||||
- `:UniversalClipboardReinit` - Re-runs detection. You **do not normally need to
|
Prints the current `clipboard` configuration to the command line, showing what
|
||||||
run this.** It's run automatically on startup.
|
`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
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -1,126 +1,147 @@
|
|||||||
-- lua/universal-clipboard/init.lua
|
-- lua/universal-clipboard/init.lua
|
||||||
local M = {}
|
local M = {
|
||||||
|
|
||||||
-- Our default options
|
-- Our default options
|
||||||
local default_opts = {
|
opts = {
|
||||||
|
-- Whether to log stuff to the vim console
|
||||||
verbose = false,
|
verbose = false,
|
||||||
}
|
|
||||||
|
|
||||||
-- Pick copy/paste commands for Wayland or X11 if '+clipboard' is missing
|
-- Copy/paste tools to check for
|
||||||
local function pick_copy_paste_commands(opts)
|
tools = {
|
||||||
if opts.verbose then
|
-- Wayland and wl-copy/wl-paste
|
||||||
vim.notify("[universal-clipboard.nvim] looking for wl-copy/xclip/xsel ...")
|
{
|
||||||
end
|
name = "wl-clipboard",
|
||||||
|
detect = function()
|
||||||
-- Check Wayland + wl-copy/wl-paste
|
|
||||||
local wayland_display = os.getenv("WAYLAND_DISPLAY")
|
local wayland_display = os.getenv("WAYLAND_DISPLAY")
|
||||||
local wayland_runtime = os.getenv("XDG_RUNTIME_DIR")
|
local wayland_runtime = os.getenv("XDG_RUNTIME_DIR")
|
||||||
local wayland_socket_path = (wayland_runtime or "") .. "/" .. (wayland_display or "")
|
local socket_path = (wayland_runtime or "") .. "/" .. (wayland_display or "")
|
||||||
|
return (vim.fn.executable("wl-copy") == 1)
|
||||||
local has_wlcopy = (vim.fn.executable("wl-copy") == 1)
|
and (vim.fn.executable("wl-paste") == 1)
|
||||||
local has_wlpaste = (vim.fn.executable("wl-paste") == 1)
|
and wayland_display ~= ""
|
||||||
local have_wayland = wayland_display and wayland_display ~= "" and (vim.fn.isdirectory(wayland_socket_path) == 1)
|
and (vim.fn.isdirectory(socket_path) == 1)
|
||||||
|
end,
|
||||||
if has_wlcopy and has_wlpaste and have_wayland then
|
commands = {
|
||||||
if opts.verbose then
|
|
||||||
vim.notify("[universal-clipboard.nvim] found wl-copy/wl-paste + Wayland", vim.log.levels.INFO)
|
|
||||||
end
|
|
||||||
return {
|
|
||||||
copy = "wl-copy",
|
copy = "wl-copy",
|
||||||
paste = "wl-paste --no-newline",
|
paste = "wl-paste --no-newline",
|
||||||
}
|
},
|
||||||
end
|
},
|
||||||
|
-- X11 and xclip
|
||||||
-- Next, try xclip
|
{
|
||||||
if vim.fn.executable("xclip") == 1 then
|
name = "xclip",
|
||||||
if opts.verbose then
|
detect = "xclip", -- Just a string, means "check if `xclip` is executable"
|
||||||
vim.notify("[universal-clipboard.nvim] found xclip", vim.log.levels.INFO)
|
commands = {
|
||||||
end
|
|
||||||
return {
|
|
||||||
copy = "xclip -selection clipboard",
|
copy = "xclip -selection clipboard",
|
||||||
paste = "xclip -selection clipboard -o",
|
paste = "xclip -selection clipboard -o",
|
||||||
}
|
},
|
||||||
end
|
},
|
||||||
|
-- X11 and xsel
|
||||||
-- Otherwise, try xsel
|
{
|
||||||
if vim.fn.executable("xsel") == 1 then
|
name = "xsel",
|
||||||
if opts.verbose then
|
detect = "xsel",
|
||||||
vim.notify("[universal-clipboard.nvim] found xsel", vim.log.levels.INFO)
|
commands = {
|
||||||
end
|
|
||||||
return {
|
|
||||||
copy = "xsel --clipboard --input",
|
copy = "xsel --clipboard --input",
|
||||||
paste = "xsel --clipboard --output",
|
paste = "xsel --clipboard --output",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Utils for logging
|
||||||
|
local function log(msg, level)
|
||||||
|
if M.opts.verbose then
|
||||||
|
vim.notify(msg, level or vim.log.levels.INFO)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- No suitable tool found
|
local function info(msg)
|
||||||
if opts.verbose then
|
log(msg, vim.log.levels.INFO)
|
||||||
vim.notify("[universal-clipboard.nvim] none found.")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function warn(msg)
|
||||||
|
log(msg, vim.log.levels.WARN)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Pick copy/paste commands from the list in opts.tools
|
||||||
|
local function pick_copy_paste_tool(opts)
|
||||||
|
info("[universal-clipboard.nvim] looking for copy/paste tool ...")
|
||||||
|
|
||||||
|
local function check_detect(tool)
|
||||||
|
if type(tool.detect) == "function" then
|
||||||
|
return tool.detect()
|
||||||
|
elseif type(tool.detect) == "string" then
|
||||||
|
return vim.fn.executable(tool.detect) == 1
|
||||||
|
else
|
||||||
|
vim.notify(
|
||||||
|
"[universal-clipboard.nvim] tool.detect is not a string or function: " .. vim.inspect(tool),
|
||||||
|
vim.log.levels.ERROR
|
||||||
|
)
|
||||||
|
end
|
||||||
|
-- Fallback for unexpected types
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, tool in ipairs(opts.tools) do
|
||||||
|
if check_detect(tool) then
|
||||||
|
info("[universal-clipboard.nvim] found " .. tool.name)
|
||||||
|
return tool
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
info("[universal-clipboard.nvim] none found.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 4) Actually configure Neovim's clipboard usage
|
-- Configure Neovim's clipboard usage
|
||||||
local function configure_clipboard(opts)
|
local function configure_clipboard(opts)
|
||||||
-- Unify normal yanks/pastes to systepm clipboard
|
-- Unify normal yanks/pastes to systepm clipboard
|
||||||
vim.opt.clipboard = "unnamedplus"
|
vim.opt.clipboard = "unnamedplus"
|
||||||
|
|
||||||
-- Search for custom clipboard provider
|
-- Search for custom clipboard provider
|
||||||
local commands = pick_copy_paste_commands(opts)
|
local tool = pick_copy_paste_tool(opts)
|
||||||
if commands then
|
if tool then
|
||||||
vim.g.clipboard = {
|
vim.g.clipboard = {
|
||||||
name = "UniversalClipboard",
|
name = "UniversalClipboard(" .. tool.name .. ")",
|
||||||
copy = {
|
copy = {
|
||||||
["+"] = commands.copy,
|
["+"] = tool.commands.copy,
|
||||||
["*"] = commands.copy,
|
["*"] = tool.commands.copy,
|
||||||
},
|
},
|
||||||
paste = {
|
paste = {
|
||||||
["+"] = commands.paste,
|
["+"] = tool.commands.paste,
|
||||||
["*"] = commands.paste,
|
["*"] = tool.commands.paste,
|
||||||
},
|
},
|
||||||
cache_enabled = 0,
|
cache_enabled = 0,
|
||||||
}
|
}
|
||||||
return "wl-copy/xclip/xsel"
|
return tool.name
|
||||||
else
|
else
|
||||||
-- No tool found
|
-- No tool found
|
||||||
if opts.verbose then
|
warn("[universal-clipboard.nvim] No external clipboard tool found.")
|
||||||
vim.notify(
|
return "(none)"
|
||||||
"[universal-clipboard.nvim] No external clipboard tool found (wl-copy, xclip, xsel).",
|
|
||||||
vim.log.levels.WARN
|
|
||||||
)
|
|
||||||
end
|
|
||||||
return "system"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Setup function (entry point)
|
-- Setup function (entry point)
|
||||||
function M.setup(user_opts)
|
function M.setup(opts)
|
||||||
-- Merge defaults with user_opts
|
-- Merge defaults with opts
|
||||||
local opts = vim.tbl_deep_extend("force", default_opts, user_opts or {})
|
M.opts = vim.tbl_deep_extend("force", M.opts, opts or {})
|
||||||
|
|
||||||
-- Set the clipboard up
|
-- Set the clipboard up
|
||||||
local mode = configure_clipboard(opts)
|
local tool_name = configure_clipboard(M.opts)
|
||||||
if opts.verbose then
|
info(("[universal-clipboard.nvim] Clipboard tool: %s"):format(tool_name))
|
||||||
vim.notify(("[universal-clipboard.nvim] Clipboard mode: %s"):format(mode), vim.log.levels.INFO)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Create user commands for debugging / re-init
|
-- Command for viewing results
|
||||||
vim.api.nvim_create_user_command("UniversalClipboardCheck", function()
|
vim.api.nvim_create_user_command("UniversalClipboardCheck", function()
|
||||||
print("=== UniversalClipboardCheck ===")
|
print("=== UniversalClipboardCheck ===")
|
||||||
|
|
||||||
local opt_clipboard = vim.opt.clipboard:get()
|
local opt_clipboard = vim.opt.clipboard:get()
|
||||||
print("vim.opt.clipboard = ", vim.inspect(opt_clipboard))
|
print("vim.opt.clipboard = ", vim.inspect(opt_clipboard))
|
||||||
|
|
||||||
if vim.g.clipboard then
|
|
||||||
print("vim.g.clipboard = ", vim.inspect(vim.g.clipboard))
|
print("vim.g.clipboard = ", vim.inspect(vim.g.clipboard))
|
||||||
else
|
|
||||||
print("vim.g.clipboard is not set.")
|
|
||||||
end
|
|
||||||
end, {})
|
end, {})
|
||||||
|
|
||||||
|
-- Command for re-running checks
|
||||||
vim.api.nvim_create_user_command("UniversalClipboardReinit", function()
|
vim.api.nvim_create_user_command("UniversalClipboardReinit", function()
|
||||||
local new_mode = configure_clipboard({ verbose = true })
|
print("=== UniversalClipboardReinit ===")
|
||||||
print("Reinitialized clipboard mode: " .. new_mode)
|
local verbose_opts = vim.tbl_deep_extend("force", M.opts, { verbose = true })
|
||||||
|
local new_tool_name = configure_clipboard(verbose_opts)
|
||||||
|
print("Reinitialized external clipboard tool: " .. new_tool_name)
|
||||||
vim.cmd("UniversalClipboardCheck")
|
vim.cmd("UniversalClipboardCheck")
|
||||||
end, {})
|
end, {})
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in new issue
Block a user