mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 03:05:11 -07:00
clipboard: Support custom VimL functions #9304
Up to now g:clipboard["copy"] only supported string values invoked as system commands. This commit enables the use of VimL functions instead. The function signatures are the same as in provider/clipboard.vim. A clipboard provider is expected to store and return a list of lines (i.e. the text) and a register type (as seen in setreg()). cache_enabled is ignored if "copy" is provided by a VimL function.
This commit is contained in:
parent
b19403e73e
commit
07ad5d71ab
@ -55,11 +55,22 @@ endfunction
|
||||
function! provider#clipboard#Executable() abort
|
||||
if exists('g:clipboard')
|
||||
if type({}) isnot# type(g:clipboard)
|
||||
\ || type({}) isnot# type(get(g:clipboard, 'copy', v:null))
|
||||
\ || type({}) isnot# type(get(g:clipboard, 'paste', v:null))
|
||||
let s:err = 'clipboard: invalid g:clipboard'
|
||||
return ''
|
||||
endif
|
||||
|
||||
if type(get(g:clipboard, 'copy', v:null)) isnot# v:t_dict
|
||||
\ && type(get(g:clipboard, 'copy', v:null)) isnot# v:t_func
|
||||
let s:err = "clipboard: invalid g:clipboard['copy']"
|
||||
return ''
|
||||
endif
|
||||
|
||||
if type(get(g:clipboard, 'paste', v:null)) isnot# v:t_dict
|
||||
\ && type(get(g:clipboard, 'paste', v:null)) isnot# v:t_func
|
||||
let s:err = "clipboard: invalid g:clipboard['paste']"
|
||||
return ''
|
||||
endif
|
||||
|
||||
let s:copy = get(g:clipboard, 'copy', { '+': v:null, '*': v:null })
|
||||
let s:paste = get(g:clipboard, 'paste', { '+': v:null, '*': v:null })
|
||||
let s:cache_enabled = get(g:clipboard, 'cache_enabled', 0)
|
||||
@ -127,7 +138,9 @@ if empty(provider#clipboard#Executable())
|
||||
endif
|
||||
|
||||
function! s:clipboard.get(reg) abort
|
||||
if s:selections[a:reg].owner > 0
|
||||
if type(s:paste[a:reg]) == v:t_func
|
||||
return s:paste[a:reg]()
|
||||
elseif s:selections[a:reg].owner > 0
|
||||
return s:selections[a:reg].data
|
||||
end
|
||||
return s:try_cmd(s:paste[a:reg])
|
||||
@ -141,6 +154,12 @@ function! s:clipboard.set(lines, regtype, reg) abort
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
if type(s:copy[a:reg]) == v:t_func
|
||||
call s:copy[a:reg](a:lines, a:regtype)
|
||||
return 0
|
||||
end
|
||||
|
||||
if s:cache_enabled == 0
|
||||
call s:try_cmd(s:copy[a:reg], a:lines)
|
||||
return 0
|
||||
|
@ -160,7 +160,9 @@ registers. Nvim looks for these clipboard tools, in order of priority:
|
||||
- tmux (if $TMUX is set)
|
||||
|
||||
*g:clipboard*
|
||||
To configure a custom clipboard tool, set `g:clipboard` to a dictionary: >
|
||||
To configure a custom clipboard tool, set g:clipboard to a dictionary.
|
||||
For example this configuration integrates the tmux clipboard: >
|
||||
|
||||
let g:clipboard = {
|
||||
\ 'name': 'myClipboard',
|
||||
\ 'copy': {
|
||||
@ -174,9 +176,28 @@ To configure a custom clipboard tool, set `g:clipboard` to a dictionary: >
|
||||
\ 'cache_enabled': 1,
|
||||
\ }
|
||||
|
||||
If `cache_enabled` is |TRUE| then when a selection is copied, Nvim will cache
|
||||
If "cache_enabled" is |TRUE| then when a selection is copied Nvim will cache
|
||||
the selection until the copy command process dies. When pasting, if the copy
|
||||
process has not died, the cached selection is applied.
|
||||
process has not died the cached selection is applied.
|
||||
|
||||
g:clipboard can also use functions (see |lambda|) instead of strings.
|
||||
For example this configuration uses the g:foo variable as a fake clipboard: >
|
||||
|
||||
let g:clipboard = {
|
||||
\ 'name': 'myClipboard',
|
||||
\ 'copy': {
|
||||
\ '+': {lines, regtype -> extend(g:, {'foo': [lines, regtype]}) },
|
||||
\ '*': {lines, regtype -> extend(g:, {'foo': [lines, regtype]}) },
|
||||
\ },
|
||||
\ 'paste': {
|
||||
\ '+': {-> get(g:, 'foo', [])},
|
||||
\ '*': {-> get(g:, 'foo', [])},
|
||||
\ },
|
||||
\ }
|
||||
|
||||
The "copy" function stores a list of lines and the register type. The "paste"
|
||||
function returns the clipboard as a `[lines, regtype]` list, where `lines` is
|
||||
a list of lines and `regtype` is a register type conforming to |setreg()|.
|
||||
|
||||
==============================================================================
|
||||
X11 selection mechanism *clipboard-x11* *x11-selection*
|
||||
|
@ -3,7 +3,7 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
|
||||
local feed_command, expect, eq, eval = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval
|
||||
local feed_command, expect, eq, eval, source = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval, helpers.source
|
||||
local command = helpers.command
|
||||
local meths = helpers.meths
|
||||
|
||||
@ -147,6 +147,93 @@ describe('clipboard', function()
|
||||
eq('clippy!', eval('provider#clipboard#Executable()'))
|
||||
eq('', eval('provider#clipboard#Error()'))
|
||||
end)
|
||||
|
||||
it('g:clipboard using VimL functions', function()
|
||||
-- Implements a fake clipboard provider. cache_enabled is meaningless here.
|
||||
source([[let g:clipboard = {
|
||||
\ 'name': 'custom',
|
||||
\ 'copy': {
|
||||
\ '+': {lines, regtype -> extend(g:, {'dummy_clipboard_plus': [lines, regtype]}) },
|
||||
\ '*': {lines, regtype -> extend(g:, {'dummy_clipboard_star': [lines, regtype]}) },
|
||||
\ },
|
||||
\ 'paste': {
|
||||
\ '+': {-> get(g:, 'dummy_clipboard_plus', [])},
|
||||
\ '*': {-> get(g:, 'dummy_clipboard_star', [])},
|
||||
\ },
|
||||
\ 'cache_enabled': 1,
|
||||
\}]])
|
||||
|
||||
eq('', eval('provider#clipboard#Error()'))
|
||||
eq('custom', eval('provider#clipboard#Executable()'))
|
||||
|
||||
eq('', eval("getreg('*')"))
|
||||
eq('', eval("getreg('+')"))
|
||||
|
||||
command('call setreg("*", "star")')
|
||||
command('call setreg("+", "plus")')
|
||||
eq('star', eval("getreg('*')"))
|
||||
eq('plus', eval("getreg('+')"))
|
||||
|
||||
command('call setreg("*", "star", "v")')
|
||||
eq({{'star'}, 'v'}, eval("g:dummy_clipboard_star"))
|
||||
command('call setreg("*", "star", "V")')
|
||||
eq({{'star', ''}, 'V'}, eval("g:dummy_clipboard_star"))
|
||||
command('call setreg("*", "star", "b")')
|
||||
eq({{'star', ''}, 'b'}, eval("g:dummy_clipboard_star"))
|
||||
end)
|
||||
|
||||
describe('g:clipboard[paste] VimL function', function()
|
||||
it('can return empty list for empty clipboard', function()
|
||||
source([[let g:dummy_clipboard = []
|
||||
let g:clipboard = {
|
||||
\ 'name': 'custom',
|
||||
\ 'copy': { '*': {lines, regtype -> 0} },
|
||||
\ 'paste': { '*': {-> g:dummy_clipboard} },
|
||||
\}]])
|
||||
eq('', eval('provider#clipboard#Error()'))
|
||||
eq('custom', eval('provider#clipboard#Executable()'))
|
||||
eq('', eval("getreg('*')"))
|
||||
end)
|
||||
|
||||
it('can return a list with a single string', function()
|
||||
source([=[let g:dummy_clipboard = ['hello']
|
||||
let g:clipboard = {
|
||||
\ 'name': 'custom',
|
||||
\ 'copy': { '*': {lines, regtype -> 0} },
|
||||
\ 'paste': { '*': {-> g:dummy_clipboard} },
|
||||
\}]=])
|
||||
eq('', eval('provider#clipboard#Error()'))
|
||||
eq('custom', eval('provider#clipboard#Executable()'))
|
||||
|
||||
eq('hello', eval("getreg('*')"))
|
||||
source([[let g:dummy_clipboard = [''] ]])
|
||||
eq('', eval("getreg('*')"))
|
||||
end)
|
||||
|
||||
it('can return a list of lines if a regtype is provided', function()
|
||||
source([=[let g:dummy_clipboard = [['hello'], 'v']
|
||||
let g:clipboard = {
|
||||
\ 'name': 'custom',
|
||||
\ 'copy': { '*': {lines, regtype -> 0} },
|
||||
\ 'paste': { '*': {-> g:dummy_clipboard} },
|
||||
\}]=])
|
||||
eq('', eval('provider#clipboard#Error()'))
|
||||
eq('custom', eval('provider#clipboard#Executable()'))
|
||||
eq('hello', eval("getreg('*')"))
|
||||
end)
|
||||
|
||||
it('can return a list of lines instead of [lines, regtype]', function()
|
||||
source([=[let g:dummy_clipboard = ['hello', 'v']
|
||||
let g:clipboard = {
|
||||
\ 'name': 'custom',
|
||||
\ 'copy': { '*': {lines, regtype -> 0} },
|
||||
\ 'paste': { '*': {-> g:dummy_clipboard} },
|
||||
\}]=])
|
||||
eq('', eval('provider#clipboard#Error()'))
|
||||
eq('custom', eval('provider#clipboard#Executable()'))
|
||||
eq('hello\nv', eval("getreg('*')"))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('clipboard', function()
|
||||
|
Loading…
Reference in New Issue
Block a user