aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Anders <greg@gpanders.com>2024-12-31 09:59:03 -0600
committerGitHub <noreply@github.com>2024-12-31 09:59:03 -0600
commita389dc2f950ef89492dfc2d8334e421d2252cddf (patch)
tree52173c06e3e4e95735e484ee3b554f12bd610ec3
parent0bef3b911cc262a007fb4412d864c1832d1268ad (diff)
downloadrneovim-a389dc2f950ef89492dfc2d8334e421d2252cddf.tar.gz
rneovim-a389dc2f950ef89492dfc2d8334e421d2252cddf.tar.bz2
rneovim-a389dc2f950ef89492dfc2d8334e421d2252cddf.zip
feat(clipboard)!: use OSC 52 as fallback clipboard provider (#31730)
We currently enable the OSC 52 clipboard provider by setting g:clipboard when a list of conditions are met, one of which is that $SSH_TTY must be set. We include this condition because often OSC 52 is not the best clipboard provider, so if there are "local" providers available Nvim should prefer those over OSC 52. However, if no other providers are available, Nvim should use OSC 52 even when $SSH_TTY is not set. When a user is in an SSH session then the checks for the other clipboard providers will still (typically) fail, so OSC 52 continues to be enabled by default in SSH sessions. This is marked as a breaking change because there are some cases where OSC 52 wasn't enabled before and is now (or vice versa).
-rw-r--r--runtime/autoload/provider/clipboard.vim8
-rw-r--r--runtime/doc/news.txt4
-rw-r--r--runtime/doc/provider.txt32
-rw-r--r--runtime/plugin/osc52.lua31
-rw-r--r--test/functional/terminal/tui_spec.lua7
5 files changed, 39 insertions, 43 deletions
diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim
index 848fa401f1..0bfd82f61d 100644
--- a/runtime/autoload/provider/clipboard.vim
+++ b/runtime/autoload/provider/clipboard.vim
@@ -169,6 +169,14 @@ function! provider#clipboard#Executable() abort
let s:copy['*'] = s:copy['+']
let s:paste['*'] = s:paste['+']
return 'tmux'
+ elseif get(get(g:, 'termfeatures', {}), 'osc52') && &clipboard ==# ''
+ " Don't use OSC 52 when 'clipboard' is set. It can be slow and cause a lot
+ " of user prompts. Users can opt-in to it by setting g:clipboard manually.
+ let s:copy['+'] = v:lua.require'vim.ui.clipboard.osc52'.copy('+')
+ let s:copy['*'] = v:lua.require'vim.ui.clipboard.osc52'.copy('*')
+ let s:paste['+'] = v:lua.require'vim.ui.clipboard.osc52'.paste('+')
+ let s:paste['*'] = v:lua.require'vim.ui.clipboard.osc52'.paste('*')
+ return 'OSC 52'
endif
let s:err = 'clipboard: No clipboard tool. :help clipboard'
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 7ea65479f3..49d9bb5ce0 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -174,7 +174,9 @@ TREESITTER
TUI
-• TODO
+• OSC 52 is used as a fallback clipboard provider when no other
+ |clipboard-tool| is found, even when not using SSH |clipboard-osc52|. To
+ disable OSC 52 queries, set the "osc52" key of |g:termfeatures| to false.
VIMSCRIPT
diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt
index c54a4df3d8..69ae0f20d1 100644
--- a/runtime/doc/provider.txt
+++ b/runtime/doc/provider.txt
@@ -259,23 +259,21 @@ For Windows WSL, try this g:clipboard definition:
*clipboard-osc52*
Nvim bundles a clipboard provider that allows copying to the system clipboard
using OSC 52. OSC 52 is an Operating System Command control sequence that
-writes the copied text to the terminal emulator. If the terminal emulator
-supports OSC 52 then it will write the copied text into the system clipboard.
-
-Nvim will attempt to automatically determine if the host terminal emulator
-supports the OSC 52 sequence and enable the OSC 52 clipboard provider if it
-does as long as all of the following are true:
-
- • Nvim is running in the |TUI|
- • |g:clipboard| is unset
- • 'clipboard' is not set to "unnamed" or "unnamedplus"
- • $SSH_TTY is set
-
-If any of the above conditions are not met then the OSC 52 clipboard provider
-will not be used by default and Nvim will fall back to discovering a
-|clipboard-tool| through the usual process.
-
-To force Nvim to use the OSC 52 provider you can use the following
+causes the terminal emulator to write to or read from the system clipboard.
+
+When Nvim is running in the |TUI|, it will automatically attempt to determine if
+the host terminal emulator supports OSC 52. If it does, then Nvim will use OSC
+52 for copying and pasting if no other |clipboard-tool| is found and when
+'clipboard' is unset.
+
+ *g:termfeatures*
+To disable the automatic detection, set the "osc52" key of |g:termfeatures| to
+|v:false| in the |config| file. Example: >lua
+ local termfeatures = vim.g.termfeatures or {}
+ termfeatures.osc52 = false
+ vim.g.termfeatures = termfeatures
+<
+To force Nvim to always use the OSC 52 provider you can use the following
|g:clipboard| definition: >lua
vim.g.clipboard = {
diff --git a/runtime/plugin/osc52.lua b/runtime/plugin/osc52.lua
index 7ffd64342e..c7f1cbe2e3 100644
--- a/runtime/plugin/osc52.lua
+++ b/runtime/plugin/osc52.lua
@@ -6,7 +6,15 @@ for _, ui in ipairs(vim.api.nvim_list_uis()) do
end
end
-if not tty or vim.g.clipboard ~= nil or vim.o.clipboard ~= '' or not os.getenv('SSH_TTY') then
+-- Do not query when any of the following is true:
+-- * TUI is not attached
+-- * OSC 52 support is explicitly disabled via g:termfeatures
+-- * Using a badly behaved terminal
+if
+ not tty
+ or (vim.g.termfeatures ~= nil and vim.g.termfeatures.osc52 == false)
+ or vim.env.TERM_PROGRAM == 'Apple_Terminal'
+then
return
end
@@ -17,28 +25,13 @@ require('vim.termcap').query('Ms', function(cap, found, seq)
assert(cap == 'Ms')
- -- Check 'clipboard' and g:clipboard again to avoid a race condition
- if vim.o.clipboard ~= '' or vim.g.clipboard ~= nil then
- return
- end
-
-- If the terminal reports a sequence other than OSC 52 for the Ms capability
-- then ignore it. We only support OSC 52 (for now)
if not seq or not seq:match('^\027%]52') then
return
end
- local osc52 = require('vim.ui.clipboard.osc52')
-
- vim.g.clipboard = {
- name = 'OSC 52',
- copy = {
- ['+'] = osc52.copy('+'),
- ['*'] = osc52.copy('*'),
- },
- paste = {
- ['+'] = osc52.paste('+'),
- ['*'] = osc52.paste('*'),
- },
- }
+ local termfeatures = vim.g.termfeatures or {}
+ termfeatures.osc52 = true
+ vim.g.termfeatures = termfeatures
end)
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index de92aefd5b..f9145f9b63 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -3184,7 +3184,6 @@ describe('TUI', function()
local req = args.data
local payload = req:match('^\027P%+q([%x;]+)$')
if payload and vim.text.hexdecode(payload) == 'Ms' then
- vim.g.xtgettcap = 'Ms'
local resp = string.format('\027P1+r%s=%s\027\\', payload, vim.text.hexencode('\027]52;;\027\\'))
vim.api.nvim_chan_send(vim.bo[args.buf].channel, resp)
return true
@@ -3202,9 +3201,6 @@ describe('TUI', function()
}, {
env = {
VIMRUNTIME = os.getenv('VIMRUNTIME'),
-
- -- Only queries when SSH_TTY is set
- SSH_TTY = '/dev/pts/1',
},
})
@@ -3212,8 +3208,7 @@ describe('TUI', function()
local child_session = n.connect(child_server)
retry(nil, 1000, function()
- eq('Ms', eval("get(g:, 'xtgettcap', '')"))
- eq({ true, 'OSC 52' }, { child_session:request('nvim_eval', 'g:clipboard.name') })
+ eq({ true, { osc52 = true } }, { child_session:request('nvim_eval', 'g:termfeatures') })
end)
end)
end)