mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	feat(clipboard): g:clipboard="foo" forces the "foo" clipboard tool #33235
This commit is contained in:
		| @@ -67,6 +67,113 @@ function! s:set_osc52() abort | |||||||
|   return 'OSC 52' |   return 'OSC 52' | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_pbcopy() abort | ||||||
|  |   let s:copy['+'] = ['pbcopy'] | ||||||
|  |   let s:paste['+'] = ['pbpaste'] | ||||||
|  |   let s:copy['*'] = s:copy['+'] | ||||||
|  |   let s:paste['*'] = s:paste['+'] | ||||||
|  |   let s:cache_enabled = 0 | ||||||
|  |   return 'pbcopy' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_wayland() abort | ||||||
|  |   let s:copy['+'] = ['wl-copy', '--type', 'text/plain'] | ||||||
|  |   let s:paste['+'] = ['wl-paste', '--no-newline'] | ||||||
|  |   let s:copy['*'] = ['wl-copy', '--primary', '--type', 'text/plain'] | ||||||
|  |   let s:paste['*'] = ['wl-paste', '--no-newline', '--primary'] | ||||||
|  |   return 'wl-copy' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_wayclip() abort | ||||||
|  |   let s:copy['+'] = ['waycopy', '-t', 'text/plain'] | ||||||
|  |   let s:paste['+'] = ['waypaste', '-t', 'text/plain'] | ||||||
|  |   let s:copy['*'] = s:copy['+'] | ||||||
|  |   let s:paste['*'] = s:paste['+'] | ||||||
|  |   return 'wayclip' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_xsel() abort | ||||||
|  |   let s:copy['+'] = ['xsel', '--nodetach', '-i', '-b'] | ||||||
|  |   let s:paste['+'] = ['xsel', '-o', '-b'] | ||||||
|  |   let s:copy['*'] = ['xsel', '--nodetach', '-i', '-p'] | ||||||
|  |   let s:paste['*'] = ['xsel', '-o', '-p'] | ||||||
|  |   return 'xsel' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_xclip() abort | ||||||
|  |   let s:copy['+'] = ['xclip', '-quiet', '-i', '-selection', 'clipboard'] | ||||||
|  |   let s:paste['+'] = ['xclip', '-o', '-selection', 'clipboard'] | ||||||
|  |   let s:copy['*'] = ['xclip', '-quiet', '-i', '-selection', 'primary'] | ||||||
|  |   let s:paste['*'] = ['xclip', '-o', '-selection', 'primary'] | ||||||
|  |   return 'xclip' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_lemonade() abort | ||||||
|  |   let s:copy['+'] = ['lemonade', 'copy'] | ||||||
|  |   let s:paste['+'] = ['lemonade', 'paste'] | ||||||
|  |   let s:copy['*'] = ['lemonade', 'copy'] | ||||||
|  |   let s:paste['*'] = ['lemonade', 'paste'] | ||||||
|  |   return 'lemonade' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_doitclient() abort | ||||||
|  |   let s:copy['+'] = ['doitclient', 'wclip'] | ||||||
|  |   let s:paste['+'] = ['doitclient', 'wclip', '-r'] | ||||||
|  |   let s:copy['*'] = s:copy['+'] | ||||||
|  |   let s:paste['*'] = s:paste['+'] | ||||||
|  |   return 'doitclient' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_win32yank() abort | ||||||
|  |   if has('wsl') && getftype(exepath('win32yank.exe')) == 'link' | ||||||
|  |     let win32yank = resolve(exepath('win32yank.exe')) | ||||||
|  |   else | ||||||
|  |     let win32yank = 'win32yank.exe' | ||||||
|  |   endif | ||||||
|  |   let s:copy['+'] = [win32yank, '-i', '--crlf'] | ||||||
|  |   let s:paste['+'] = [win32yank, '-o', '--lf'] | ||||||
|  |   let s:copy['*'] = s:copy['+'] | ||||||
|  |   let s:paste['*'] = s:paste['+'] | ||||||
|  |   return 'win32yank' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_putclip() abort | ||||||
|  |   let s:copy['+'] = ['putclip'] | ||||||
|  |   let s:paste['+'] = ['getclip'] | ||||||
|  |   let s:copy['*'] = s:copy['+'] | ||||||
|  |   let s:paste['*'] = s:paste['+'] | ||||||
|  |   return 'putclip' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_clip() abort | ||||||
|  |   let s:copy['+'] = ['clip'] | ||||||
|  |   let s:paste['+'] = ['powershell', '-NoProfile', '-NoLogo', '-Command', 'Get-Clipboard'] | ||||||
|  |   let s:copy['*'] = s:copy['+'] | ||||||
|  |   let s:paste['*'] = s:paste['+'] | ||||||
|  |   return 'clip' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_termux() abort | ||||||
|  |   let s:copy['+'] = ['termux-clipboard-set'] | ||||||
|  |   let s:paste['+'] = ['termux-clipboard-get'] | ||||||
|  |   let s:copy['*'] = s:copy['+'] | ||||||
|  |   let s:paste['*'] = s:paste['+'] | ||||||
|  |   return 'termux-clipboard' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
|  | function! s:set_tmux() abort | ||||||
|  |   let tmux_v = v:lua.vim.version.parse(system(['tmux', '-V'])) | ||||||
|  |   if !empty(tmux_v) && !v:lua.vim.version.lt(tmux_v, [3,2,0]) | ||||||
|  |     let s:copy['+'] = ['tmux', 'load-buffer', '-w', '-'] | ||||||
|  |   else | ||||||
|  |     let s:copy['+'] = ['tmux', 'load-buffer', '-'] | ||||||
|  |   endif | ||||||
|  |   let s:paste['+'] = ['tmux', 'save-buffer', '-'] | ||||||
|  |   let s:copy['*'] = s:copy['+'] | ||||||
|  |   let s:paste['*'] = s:paste['+'] | ||||||
|  |   return 'tmux' | ||||||
|  | endfunction | ||||||
|  |  | ||||||
| let s:cache_enabled = 1 | let s:cache_enabled = 1 | ||||||
| let s:err = '' | let s:err = '' | ||||||
|  |  | ||||||
| @@ -78,9 +185,34 @@ function! provider#clipboard#Executable() abort | |||||||
|   " Setting g:clipboard to v:false explicitly opts-in to using the "builtin" clipboard providers below |   " Setting g:clipboard to v:false explicitly opts-in to using the "builtin" clipboard providers below | ||||||
|   if exists('g:clipboard') && g:clipboard isnot# v:false |   if exists('g:clipboard') && g:clipboard isnot# v:false | ||||||
|     if v:t_string ==# type(g:clipboard) |     if v:t_string ==# type(g:clipboard) | ||||||
|  |       " Handle string form of g:clipboard for all builtin providers | ||||||
|       if 'osc52' == g:clipboard |       if 'osc52' == g:clipboard | ||||||
|         " User opted-in to OSC 52 by manually setting g:clipboard. |         " User opted-in to OSC 52 by manually setting g:clipboard. | ||||||
|         return s:set_osc52() |         return s:set_osc52() | ||||||
|  |       elseif 'pbcopy' == g:clipboard | ||||||
|  |         return s:set_pbcopy() | ||||||
|  |       elseif 'wl-copy' == g:clipboard | ||||||
|  |         return s:set_wayland() | ||||||
|  |       elseif 'wayclip' == g:clipboard | ||||||
|  |         return s:set_wayclip() | ||||||
|  |       elseif 'xsel' == g:clipboard | ||||||
|  |         return s:set_xsel() | ||||||
|  |       elseif 'xclip' == g:clipboard | ||||||
|  |         return s:set_xclip() | ||||||
|  |       elseif 'lemonade' == g:clipboard | ||||||
|  |         return s:set_lemonade() | ||||||
|  |       elseif 'doitclient' == g:clipboard | ||||||
|  |         return s:set_doitclient() | ||||||
|  |       elseif 'win32yank' == g:clipboard | ||||||
|  |         return s:set_win32yank() | ||||||
|  |       elseif 'putclip' == g:clipboard | ||||||
|  |         return s:set_putclip() | ||||||
|  |       elseif 'clip' == g:clipboard | ||||||
|  |         return s:set_clip() | ||||||
|  |       elseif 'termux' == g:clipboard | ||||||
|  |         return s:set_termux() | ||||||
|  |       elseif 'tmux' == g:clipboard | ||||||
|  |         return s:set_tmux() | ||||||
|       endif |       endif | ||||||
|     endif |     endif | ||||||
|  |  | ||||||
| @@ -102,88 +234,29 @@ function! provider#clipboard#Executable() abort | |||||||
|     let s:cache_enabled = get(g:clipboard, 'cache_enabled', 0) |     let s:cache_enabled = get(g:clipboard, 'cache_enabled', 0) | ||||||
|     return get(g:clipboard, 'name', 'g:clipboard') |     return get(g:clipboard, 'name', 'g:clipboard') | ||||||
|   elseif has('mac') |   elseif has('mac') | ||||||
|     let s:copy['+'] = ['pbcopy'] |     return s:set_pbcopy() | ||||||
|     let s:paste['+'] = ['pbpaste'] |  | ||||||
|     let s:copy['*'] = s:copy['+'] |  | ||||||
|     let s:paste['*'] = s:paste['+'] |  | ||||||
|     let s:cache_enabled = 0 |  | ||||||
|     return 'pbcopy' |  | ||||||
|   elseif !empty($WAYLAND_DISPLAY) && executable('wl-copy') && executable('wl-paste') |   elseif !empty($WAYLAND_DISPLAY) && executable('wl-copy') && executable('wl-paste') | ||||||
|     let s:copy['+'] = ['wl-copy', '--type', 'text/plain'] |     return s:set_wayland() | ||||||
|     let s:paste['+'] = ['wl-paste', '--no-newline'] |  | ||||||
|     let s:copy['*'] = ['wl-copy', '--primary', '--type', 'text/plain'] |  | ||||||
|     let s:paste['*'] = ['wl-paste', '--no-newline', '--primary'] |  | ||||||
|     return 'wl-copy' |  | ||||||
|   elseif !empty($WAYLAND_DISPLAY) && executable('waycopy') && executable('waypaste') |   elseif !empty($WAYLAND_DISPLAY) && executable('waycopy') && executable('waypaste') | ||||||
|     let s:copy['+'] = ['waycopy', '-t', 'text/plain'] |     return s:set_wayclip() | ||||||
|     let s:paste['+'] = ['waypaste', '-t', 'text/plain'] |  | ||||||
|     let s:copy['*'] = s:copy['+'] |  | ||||||
|     let s:paste['*'] = s:paste['+'] |  | ||||||
|     return 'wayclip' |  | ||||||
|   elseif !empty($DISPLAY) && executable('xsel') && s:cmd_ok('xsel -o -b') |   elseif !empty($DISPLAY) && executable('xsel') && s:cmd_ok('xsel -o -b') | ||||||
|     let s:copy['+'] = ['xsel', '--nodetach', '-i', '-b'] |     return s:set_xsel() | ||||||
|     let s:paste['+'] = ['xsel', '-o', '-b'] |  | ||||||
|     let s:copy['*'] = ['xsel', '--nodetach', '-i', '-p'] |  | ||||||
|     let s:paste['*'] = ['xsel', '-o', '-p'] |  | ||||||
|     return 'xsel' |  | ||||||
|   elseif !empty($DISPLAY) && executable('xclip') |   elseif !empty($DISPLAY) && executable('xclip') | ||||||
|     let s:copy['+'] = ['xclip', '-quiet', '-i', '-selection', 'clipboard'] |     return s:set_xclip() | ||||||
|     let s:paste['+'] = ['xclip', '-o', '-selection', 'clipboard'] |  | ||||||
|     let s:copy['*'] = ['xclip', '-quiet', '-i', '-selection', 'primary'] |  | ||||||
|     let s:paste['*'] = ['xclip', '-o', '-selection', 'primary'] |  | ||||||
|     return 'xclip' |  | ||||||
|   elseif executable('lemonade') |   elseif executable('lemonade') | ||||||
|     let s:copy['+'] = ['lemonade', 'copy'] |     return s:set_lemonade() | ||||||
|     let s:paste['+'] = ['lemonade', 'paste'] |  | ||||||
|     let s:copy['*'] = ['lemonade', 'copy'] |  | ||||||
|     let s:paste['*'] = ['lemonade', 'paste'] |  | ||||||
|     return 'lemonade' |  | ||||||
|   elseif executable('doitclient') |   elseif executable('doitclient') | ||||||
|     let s:copy['+'] = ['doitclient', 'wclip'] |     return s:set_doitclient() | ||||||
|     let s:paste['+'] = ['doitclient', 'wclip', '-r'] |  | ||||||
|     let s:copy['*'] = s:copy['+'] |  | ||||||
|     let s:paste['*'] = s:paste['+'] |  | ||||||
|     return 'doitclient' |  | ||||||
|   elseif executable('win32yank.exe') |   elseif executable('win32yank.exe') | ||||||
|     if has('wsl') && getftype(exepath('win32yank.exe')) == 'link' |     return s:set_win32yank() | ||||||
|       let win32yank = resolve(exepath('win32yank.exe')) |  | ||||||
|     else |  | ||||||
|       let win32yank = 'win32yank.exe' |  | ||||||
|     endif |  | ||||||
|     let s:copy['+'] = [win32yank, '-i', '--crlf'] |  | ||||||
|     let s:paste['+'] = [win32yank, '-o', '--lf'] |  | ||||||
|     let s:copy['*'] = s:copy['+'] |  | ||||||
|     let s:paste['*'] = s:paste['+'] |  | ||||||
|     return 'win32yank' |  | ||||||
|   elseif executable('putclip') && executable('getclip') |   elseif executable('putclip') && executable('getclip') | ||||||
|     let s:copy['+'] = ['putclip'] |     return s:set_putclip() | ||||||
|     let s:paste['+'] = ['getclip'] |  | ||||||
|     let s:copy['*'] = s:copy['+'] |  | ||||||
|     let s:paste['*'] = s:paste['+'] |  | ||||||
|     return 'putclip' |  | ||||||
|   elseif executable('clip') && executable('powershell') |   elseif executable('clip') && executable('powershell') | ||||||
|     let s:copy['+'] = ['clip'] |     return s:set_clip() | ||||||
|     let s:paste['+'] = ['powershell', '-NoProfile', '-NoLogo', '-Command', 'Get-Clipboard'] |  | ||||||
|     let s:copy['*'] = s:copy['+'] |  | ||||||
|     let s:paste['*'] = s:paste['+'] |  | ||||||
|     return 'clip' |  | ||||||
|   elseif executable('termux-clipboard-set') |   elseif executable('termux-clipboard-set') | ||||||
|     let s:copy['+'] = ['termux-clipboard-set'] |     return s:set_termux() | ||||||
|     let s:paste['+'] = ['termux-clipboard-get'] |  | ||||||
|     let s:copy['*'] = s:copy['+'] |  | ||||||
|     let s:paste['*'] = s:paste['+'] |  | ||||||
|     return 'termux-clipboard' |  | ||||||
|   elseif executable('tmux') && (!empty($TMUX) || 0 == jobwait([jobstart(['tmux', 'list-buffers'])], 2000)[0]) |   elseif executable('tmux') && (!empty($TMUX) || 0 == jobwait([jobstart(['tmux', 'list-buffers'])], 2000)[0]) | ||||||
|     let tmux_v = v:lua.vim.version.parse(system(['tmux', '-V'])) |     return s:set_tmux() | ||||||
|     if !empty(tmux_v) && !v:lua.vim.version.lt(tmux_v, [3,2,0]) |  | ||||||
|       let s:copy['+'] = ['tmux', 'load-buffer', '-w', '-'] |  | ||||||
|     else |  | ||||||
|       let s:copy['+'] = ['tmux', 'load-buffer', '-'] |  | ||||||
|     endif |  | ||||||
|     let s:paste['+'] = ['tmux', 'save-buffer', '-'] |  | ||||||
|     let s:copy['*'] = s:copy['+'] |  | ||||||
|     let s:paste['*'] = s:paste['+'] |  | ||||||
|     return 'tmux' |  | ||||||
|   elseif get(get(g:, 'termfeatures', {}), 'osc52') && &clipboard ==# '' |   elseif get(get(g:, 'termfeatures', {}), 'osc52') && &clipboard ==# '' | ||||||
|     " Don't use OSC 52 when 'clipboard' is set. It can be slow and cause a lot |     " 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. |     " of user prompts. Users can opt-in to it by setting g:clipboard manually. | ||||||
|   | |||||||
| @@ -138,6 +138,8 @@ OPTIONS | |||||||
|  |  | ||||||
| • 'winborder' add bold style. | • 'winborder' add bold style. | ||||||
|  |  | ||||||
|  | • |g:clipboard| accepts a string name to force any builtin clipboard tool. | ||||||
|  |  | ||||||
| PERFORMANCE | PERFORMANCE | ||||||
|  |  | ||||||
| • todo | • todo | ||||||
|   | |||||||
| @@ -240,6 +240,27 @@ 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 | 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()|. | a list of lines and `regtype` is a register type conforming to |setreg()|. | ||||||
|  |  | ||||||
|  | Nvim also supports setting g:clipboard to a string to use a builtin clipboard provider: | ||||||
|  |  | ||||||
|  |   - "tmux"           - Use tmux clipboard | ||||||
|  |   - "xclip"          - Use xclip for X11 clipboard | ||||||
|  |   - "xsel"           - Use xsel for X11 clipboard | ||||||
|  |   - "wl-copy"        - Use Wayland clipboard with wl-copy/wl-paste | ||||||
|  |   - "wayclip"        - Use Wayland clipboard with waycopy/waypaste | ||||||
|  |   - "lemonade"       - Use lemonade clipboard (for SSH) | ||||||
|  |   - "doitclient"     - Use doitclient clipboard (for SSH) | ||||||
|  |   - "win32yank"      - Use win32yank clipboard (for Windows) | ||||||
|  |   - "clip"           - Use clip/powershell clipboard (for Windows) | ||||||
|  |   - "putclip"        - Use putclip/getclip clipboard (for Windows/Cygwin) | ||||||
|  |   - "termux"         - Use Termux clipboard | ||||||
|  |   - "pbcopy"         - Use macOS clipboard | ||||||
|  |   - "osc52"          - Use OSC 52 sequence | ||||||
|  |  | ||||||
|  | Example: >vim | ||||||
|  |     let g:clipboard = 'tmux' | ||||||
|  |  | ||||||
|  | This is equivalent to using the full dictionary configuration for tmux shown above. | ||||||
|  |  | ||||||
| 							      *clipboard-wsl* | 							      *clipboard-wsl* | ||||||
| For Windows WSL, try this g:clipboard definition: | For Windows WSL, try this g:clipboard definition: | ||||||
| >vim | >vim | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Deveshi Dwivedi
					Deveshi Dwivedi