mirror of
https://github.com/vim/vim.git
synced 2025-10-17 07:44:28 -04:00
patch 9.1.1857: Missing clipboard provider support
Problem: Missing clipboard provider support (lilydjwg) Solution: Add clipboard provider feature (Foxe Chen) fixes: #12419 closes: #17998 Signed-off-by: Foxe Chen <chen.foxe@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
1a09f11f5d
commit
67860efe5b
@@ -1,4 +1,4 @@
|
||||
*builtin.txt* For Vim version 9.1. Last change: 2025 Oct 13
|
||||
*builtin.txt* For Vim version 9.1. Last change: 2025 Oct 14
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -13061,6 +13061,7 @@ channel Compiled with support for |channel| and |job|
|
||||
cindent Compiled with 'cindent' support. (always true)
|
||||
clientserver Compiled with remote invocation support |clientserver|.
|
||||
clipboard Compiled with 'clipboard' support.
|
||||
clipboard_provider Compiled with |clipboard-providers| support
|
||||
clipboard_working Compiled with 'clipboard' support and it can be used.
|
||||
cmdline_compl Compiled with |cmdline-completion| support.
|
||||
cmdline_hist Compiled with |cmdline-history| support.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
*eval.txt* For Vim version 9.1. Last change: 2025 Oct 12
|
||||
*eval.txt* For Vim version 9.1. Last change: 2025 Oct 14
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -38,6 +38,7 @@ a remark is given.
|
||||
12. The sandbox |eval-sandbox|
|
||||
13. Textlock |textlock|
|
||||
14. Vim script library |vim-script-library|
|
||||
15. Clipboard providers |clipboard-providers|
|
||||
|
||||
Testing support is documented in |testing.txt|.
|
||||
Profiling is documented at |profiling|.
|
||||
@@ -2251,6 +2252,11 @@ v:clipmethod The current method of accessing the clipboard that is being
|
||||
unavailable.
|
||||
See 'clipmethod' for more details.
|
||||
|
||||
*v:clipproviders*
|
||||
v:clipproviders
|
||||
A dictionary containing clipboard providers, see
|
||||
|clipboard-providers| for more information.
|
||||
|
||||
*v:cmdarg* *cmdarg-variable*
|
||||
v:cmdarg This variable is used for two purposes:
|
||||
1. The extra arguments given to a file read/write command.
|
||||
@@ -5263,5 +5269,133 @@ Usage: >vim
|
||||
:call dist#vim9#Launch(<args>)
|
||||
:Launch <app> <args>.
|
||||
<
|
||||
==============================================================================
|
||||
15. Clipboard providers *clipboard-providers*
|
||||
|
||||
When Vim is compiled with the |+clipboard_provider| feature, which requires
|
||||
the |+eval| feature, creating custom clipboards is possible. These providers
|
||||
handle the "+" and "*" registers. Note that on non-Unix or non-VMS systems,
|
||||
only the "*" register will be available for use.
|
||||
|
||||
To add a provider, add a new entry to the |v:clipproviders| dictionary, in the
|
||||
format of: >
|
||||
let v:clipproviders["name"] = {
|
||||
\ "available": function("Available"),
|
||||
\ "paste": {
|
||||
\ '+': function("Paste"), " For the + register
|
||||
\ '*': function("Paste"), " For the * register
|
||||
\ },
|
||||
\ "copy": {
|
||||
\ '+': function("Copy"), " Same thing as above
|
||||
\ '*': function("Copy"),
|
||||
\ },
|
||||
\ }
|
||||
|
||||
The key is the provider name, which should be used in 'clipmethod', for
|
||||
example in the following example, you would add "name" to 'clipmethod' in
|
||||
order to use it. >
|
||||
set clipmethod=name,wayland,x11,gui
|
||||
|
||||
Each callback can either be a name of a function in a string, a |Funcref|, or
|
||||
a |lambda| expression.
|
||||
|
||||
Note that these dictionary entries are optional, for example, if you don't
|
||||
care about the "copy" functions, then you can simply exclude them. When Vim
|
||||
yanks/copies something, then simply nothing will be done.
|
||||
|
||||
*clipboard-provider-available*
|
||||
The "available" callback should return a string, which should contain which
|
||||
clipboard registers are available. For example, if the "+" register is only
|
||||
available, then the function would return "+", or if both "+" and "*" are
|
||||
available, then return "+*".
|
||||
|
||||
*clipboard-provider-paste*
|
||||
The "paste" callback takes a first argument which is the register being put
|
||||
(string), and a second argument which is the type of access (string). It
|
||||
should return either a tuple/list or string. If a tuple/list is returned, it
|
||||
should have two elements:
|
||||
- The register type conforming to |setreg()|.
|
||||
- A list of strings
|
||||
If the register type is an empty string, then the type is automatically
|
||||
chosen, see |setreg()|. If a string is returned, then it can either be "clear"
|
||||
or "previous". "clear" makes Vim clear the register, and "previous" makes Vim
|
||||
use the previous register contents (or current depending on how you view it).
|
||||
|
||||
The second argument, the access type, can either be "explicit" or "implicit".
|
||||
"explicit" means that the user is directly accessing the clipboard, such as
|
||||
putting text, or calling |getreg()|; "implicit" means that the clipboard is
|
||||
being accessed indirectly, such when |:registers| is called, or when an
|
||||
unrelated operation causes Vim to access the clipboard.
|
||||
|
||||
This is useful since some operations in Vim implicity access the clipboard
|
||||
indirectly. For example, if when you want to create a provider for the OSC52
|
||||
command (accessing the clipboard via an escape code). Many terminals show a
|
||||
confirmation if you want Vim to access the clipboard. This can be very
|
||||
annoying with the terminal asking for permission everytime you do something
|
||||
that accesses the clipboard behind the scenes. A good way to handle implicit
|
||||
access is to return "previous", which leaves the register contents unchanged.
|
||||
|
||||
*clipboard-provider-copy*
|
||||
The "copy" callback returns nothing, and takes the given arguments in order:
|
||||
- The register being operated on
|
||||
- The register type, conforming to |getregtype()|
|
||||
- A list of strings to copy
|
||||
|
||||
The provider can do whatever it wants with the given information. This
|
||||
function is called on every request to change the clipboard register(s).
|
||||
|
||||
*clipboard-provider-textlock*
|
||||
In both the "paste" and "copy" callbacks, it is not allowed to change the
|
||||
buffer text, see |textlock|.
|
||||
|
||||
*clipboard-provider-example*
|
||||
Here is an example script that uses the clipboard provider feature through the
|
||||
OSC52 command: >vim
|
||||
|
||||
func Available()
|
||||
return "+"
|
||||
endfunc
|
||||
|
||||
func Paste(reg, type)
|
||||
" If implicit access, don't do anything
|
||||
if a:type == "implicit"
|
||||
return "previous"
|
||||
endif
|
||||
|
||||
augroup OSC
|
||||
autocmd!
|
||||
autocmd TermResponseAll osc ++once call feedkeys("\<F30>", '!')
|
||||
augroup END
|
||||
|
||||
" Send command
|
||||
call echoraw("\<Esc>]52;c;?\<Esc>\\")
|
||||
|
||||
" Wait until autocmd is triggered
|
||||
while getchar(-1) != "\<F30>"
|
||||
endwhile
|
||||
|
||||
autocmd! OSC
|
||||
|
||||
" Extract the base64 stuff
|
||||
let l:stuff = matchstr(v:termosc, '52;c;\zs[A-Za-z0-9+/=]\+')
|
||||
|
||||
return ("", blob2str(base64_decode(l:stuff)))
|
||||
endfunc
|
||||
|
||||
func Copy(reg, type, lines)
|
||||
call echoraw("\<Esc>]52;c;" ..
|
||||
\ base64_encode(str2blob(a:lines)) .. "\<Esc>\\")
|
||||
endfunc
|
||||
let v:clipproviders["myosc"] = {
|
||||
\ "available": function("Available"),
|
||||
\ "paste": {
|
||||
\ '+': function("Paste"),
|
||||
\ },
|
||||
\ "copy": {
|
||||
\ '+': function("Copy"),
|
||||
\ },
|
||||
\ }
|
||||
set clipmethod=myosc
|
||||
|
||||
<
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -1919,10 +1919,15 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
x11 X11 selections
|
||||
gui GUI specific method
|
||||
other Some other method
|
||||
* Clipboard provider method
|
||||
|
||||
Note: "other" is used on systems without X11/Wayland, such as
|
||||
MS-Windows or MacOS, when running Vim without the GUI.
|
||||
|
||||
Note that the name of the clipboard provider should be used when you
|
||||
want to use a clipboard provider. See |clipboard-providers| for more
|
||||
information.
|
||||
|
||||
The option value is a list of comma separated items. The list is
|
||||
parsed left to right in order, and the first method that Vim
|
||||
determines is available or is working is used as the actual method for
|
||||
|
@@ -1411,6 +1411,7 @@ $quote eval.txt /*$quote*
|
||||
+cindent various.txt /*+cindent*
|
||||
+clientserver various.txt /*+clientserver*
|
||||
+clipboard various.txt /*+clipboard*
|
||||
+clipboard_provider various.txt /*+clipboard_provider*
|
||||
+clipboard_working various.txt /*+clipboard_working*
|
||||
+cmd editing.txt /*+cmd*
|
||||
+cmdline_compl various.txt /*+cmdline_compl*
|
||||
@@ -6691,6 +6692,12 @@ clipboard-autoselectml options.txt /*clipboard-autoselectml*
|
||||
clipboard-autoselectplus options.txt /*clipboard-autoselectplus*
|
||||
clipboard-exclude options.txt /*clipboard-exclude*
|
||||
clipboard-html options.txt /*clipboard-html*
|
||||
clipboard-provider-available eval.txt /*clipboard-provider-available*
|
||||
clipboard-provider-copy eval.txt /*clipboard-provider-copy*
|
||||
clipboard-provider-example eval.txt /*clipboard-provider-example*
|
||||
clipboard-provider-paste eval.txt /*clipboard-provider-paste*
|
||||
clipboard-provider-textlock eval.txt /*clipboard-provider-textlock*
|
||||
clipboard-providers eval.txt /*clipboard-providers*
|
||||
clipboard-unnamed options.txt /*clipboard-unnamed*
|
||||
clipboard-unnamedplus options.txt /*clipboard-unnamedplus*
|
||||
clojure-indent indent.txt /*clojure-indent*
|
||||
@@ -11254,6 +11261,7 @@ v:char eval.txt /*v:char*
|
||||
v:charconvert_from eval.txt /*v:charconvert_from*
|
||||
v:charconvert_to eval.txt /*v:charconvert_to*
|
||||
v:clipmethod eval.txt /*v:clipmethod*
|
||||
v:clipproviders eval.txt /*v:clipproviders*
|
||||
v:cmdarg eval.txt /*v:cmdarg*
|
||||
v:cmdbang eval.txt /*v:cmdbang*
|
||||
v:collate eval.txt /*v:collate*
|
||||
|
@@ -1,4 +1,4 @@
|
||||
*various.txt* For Vim version 9.1. Last change: 2025 Oct 12
|
||||
*various.txt* For Vim version 9.1. Last change: 2025 Oct 14
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -378,6 +378,7 @@ m *+channel* inter process communication |channel|
|
||||
T *+cindent* 'cindent', C indenting; Always enabled
|
||||
N *+clientserver* Unix and Win32: Remote invocation |clientserver|
|
||||
*+clipboard* |clipboard| support compiled-in
|
||||
N *+clipboard_provider* |clipboard-providers| support compiled-in
|
||||
*+clipboard_working* |clipboard| support compiled-in and working
|
||||
T *+cmdline_compl* command line completion |cmdline-completion|
|
||||
T *+cmdline_hist* command line history |cmdline-history|
|
||||
@@ -807,7 +808,10 @@ K Run a program to lookup the keyword under the
|
||||
:clip[reset] Attempts to choose a new method for accessing the
|
||||
clipboard, using the 'clipmethod' option. This is
|
||||
useful when the current method has become unavailable,
|
||||
and you want to try using another method.
|
||||
and you want to try using another method. If the
|
||||
|+clipboard_provider| feature is being used, this
|
||||
command should be called after the availability of one
|
||||
of the clipboard registers changes.
|
||||
{only available when compiled with the |+clipboard|
|
||||
feature}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
*version9.txt* For Vim version 9.1. Last change: 2025 Oct 12
|
||||
*version9.txt* For Vim version 9.1. Last change: 2025 Oct 14
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -41653,6 +41653,8 @@ Other new features ~
|
||||
|
||||
- |items()| function now supports Blob.
|
||||
|
||||
- |clipboard-providers| support.
|
||||
|
||||
*changed-9.2*
|
||||
Changed~
|
||||
-------
|
||||
@@ -41900,13 +41902,29 @@ Options: ~
|
||||
compositor
|
||||
|
||||
Vim Variables: ~
|
||||
|v:clipmethod| The current 'clipmethod'.
|
||||
|v:clipproviders| A dictionary containing clipboard providers
|
||||
information.
|
||||
|v:stacktrace| The most recent caught exception.
|
||||
|v:t_enumvalue| Value of |enumvalue|.
|
||||
|v:t_enum| Value of |enum| type.
|
||||
|v:t_tuple| Value of |Tuple| type.
|
||||
|v:termda1| The escape sequence returned for the primary device
|
||||
attribute query (DA1).
|
||||
|v:termosc| The most recent received OSC response.
|
||||
|v:wayland_display| The name of the Wayland display Vim is connected to.
|
||||
|
||||
Vim Arguments: ~
|
||||
|-Y| Do not connect to the |wayland| compositor.
|
||||
|--clientserver| Specify backend for clientserver functionality.
|
||||
|
||||
Configure Switches: ~
|
||||
--with-wayland Enable the |wayland| feature.
|
||||
--enable-wayland-focus-steal Enable the |wayland-focus-steal| feature.
|
||||
--enable-socketserver Enable the |socketserver-clientserver|
|
||||
feature.
|
||||
--enable-clipboard-provider Enable the |clipboard-providers| feature.
|
||||
|
||||
|
||||
==============================================================================
|
||||
INCOMPATIBLE CHANGES *incompatible-9.2*
|
||||
|
@@ -2,7 +2,7 @@
|
||||
" Language: Vim script
|
||||
" Maintainer: Hirohito Higashi <h.east.727 ATMARK gmail.com>
|
||||
" Doug Kearns <dougkearns@gmail.com>
|
||||
" Last Change: 2025 Oct 11
|
||||
" Last Change: 2025 Oct 14
|
||||
" Former Maintainer: Charles E. Campbell
|
||||
|
||||
" DO NOT CHANGE DIRECTLY.
|
||||
@@ -166,7 +166,7 @@ syn keyword vimFuncName contained win_execute win_findbuf win_getid win_gettype
|
||||
" Predefined variable names {{{2
|
||||
" GEN_SYN_VIM: vimVarName, START_STR='syn keyword vimVimVarName contained', END_STR=''
|
||||
syn keyword vimVimVarName contained count count1 prevcount errmsg warningmsg statusmsg shell_error this_session version lnum termresponse fname lang lc_time ctype charconvert_from charconvert_to fname_in fname_out fname_new fname_diff cmdarg foldstart foldend folddashes foldlevel progname servername dying exception throwpoint register cmdbang insertmode val key profiling fcs_reason fcs_choice beval_bufnr beval_winnr beval_winid beval_lnum beval_col beval_text scrollstart swapname swapchoice swapcommand char mouse_win mouse_winid mouse_lnum mouse_col operator searchforward hlsearch oldfiles windowid progpath completed_item option_new option_old option_oldlocal option_oldglobal option_command option_type errors false true none null numbermax numbermin numbersize
|
||||
syn keyword vimVimVarName contained vim_did_enter testing t_number t_string t_func t_list t_dict t_float t_bool t_none t_job t_channel t_blob t_class t_object termrfgresp termrbgresp termu7resp termstyleresp termblinkresp event versionlong echospace argv collate exiting colornames sizeofint sizeoflong sizeofpointer maxcol python3_version t_typealias t_enum t_enumvalue stacktrace t_tuple wayland_display clipmethod termda1 termosc
|
||||
syn keyword vimVimVarName contained vim_did_enter testing t_number t_string t_func t_list t_dict t_float t_bool t_none t_job t_channel t_blob t_class t_object termrfgresp termrbgresp termu7resp termstyleresp termblinkresp event versionlong echospace argv collate exiting colornames sizeofint sizeoflong sizeofpointer maxcol python3_version t_typealias t_enum t_enumvalue stacktrace t_tuple wayland_display clipmethod termda1 termosc clipproviders
|
||||
|
||||
"--- syntax here and above generated by runtime/syntax/generator/gen_syntax_vim.vim ---
|
||||
|
||||
|
31
src/auto/configure
vendored
31
src/auto/configure
vendored
@@ -857,6 +857,7 @@ enable_arabic
|
||||
enable_farsi
|
||||
enable_xim
|
||||
enable_fontset
|
||||
enable_clipboard_provider
|
||||
with_wayland
|
||||
enable_wayland_focus_steal
|
||||
with_x
|
||||
@@ -1539,6 +1540,7 @@ Optional Features:
|
||||
--disable-farsi Deprecated.
|
||||
--enable-xim Include XIM input support.
|
||||
--enable-fontset Include X fontset output support.
|
||||
--enable-clipboard-provider Include clipboard provider support.
|
||||
--enable-wayland-focus-steal
|
||||
Include focus stealing support for Wayland
|
||||
clipboard.
|
||||
@@ -9208,6 +9210,35 @@ fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_fontset" >&5
|
||||
printf "%s\n" "$enable_fontset" >&6; }
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking --enable-clipboard-provider" >&5
|
||||
printf %s "checking --enable-clipboard-provider... " >&6; }
|
||||
# Check whether --enable-clipboard-provider was given.
|
||||
if test ${enable_clipboard_provider+y}
|
||||
then :
|
||||
enableval=$enable_clipboard_provider; enable_clipboard_provider=$enableval
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
|
||||
printf "%s\n" "$enableval" >&6; }
|
||||
else case e in #(
|
||||
e) if test "x$features" = xtiny
|
||||
then :
|
||||
enable_clipboard_provider="no"
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cannot use clipboard provider with tiny features" >&5
|
||||
printf "%s\n" "cannot use clipboard provider with tiny features" >&6; }
|
||||
else case e in #(
|
||||
e) enable_clipboard_provider="yes"
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; } ;;
|
||||
esac
|
||||
fi ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test "$enable_clipboard_provider" = "yes"; then
|
||||
printf "%s\n" "#define FEAT_CLIPBOARD_PROVIDER 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if shm_open is available" >&5
|
||||
printf %s "checking if shm_open is available... " >&6; }
|
||||
cppflags_save=$CPPFLAGS
|
||||
|
403
src/clipboard.c
403
src/clipboard.c
@@ -134,6 +134,12 @@ static bool clip_wl_owner_exists(Clipboard_T *cbd);
|
||||
|
||||
#endif // FEAT_WAYLAND_CLIPBOARD
|
||||
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
static int clip_provider_is_available(Clipboard_T *cbd, char_u *provider);
|
||||
static void clip_provider_set_selection(Clipboard_T *cbd, char_u *provider);
|
||||
static void clip_provider_request_selection(Clipboard_T *cbd, char_u *provider);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Selection stuff using Visual mode, for cutting and pasting text to other
|
||||
* windows.
|
||||
@@ -254,7 +260,7 @@ clip_gen_own_selection(Clipboard_T *cbd UNUSED)
|
||||
}
|
||||
else if (clipmethod == CLIPMETHOD_OTHER)
|
||||
{
|
||||
#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
|
||||
#ifndef UNIX
|
||||
return clip_mch_own_selection(cbd);
|
||||
#endif
|
||||
}
|
||||
@@ -321,7 +327,7 @@ clip_gen_lose_selection(Clipboard_T *cbd UNUSED)
|
||||
}
|
||||
else if (clipmethod == CLIPMETHOD_OTHER)
|
||||
{
|
||||
#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
|
||||
#ifndef UNIX
|
||||
clip_mch_lose_selection(cbd);
|
||||
#endif
|
||||
}
|
||||
@@ -1354,7 +1360,7 @@ clip_gen_set_selection(Clipboard_T *cbd)
|
||||
{
|
||||
#ifdef FEAT_GUI
|
||||
if (gui.in_use)
|
||||
clip_mch_set_selection(cbd);
|
||||
clip_mch_set_selection(cbd);
|
||||
#endif
|
||||
}
|
||||
else if (clipmethod == CLIPMETHOD_WAYLAND)
|
||||
@@ -1371,8 +1377,14 @@ clip_gen_set_selection(Clipboard_T *cbd)
|
||||
}
|
||||
else if (clipmethod == CLIPMETHOD_OTHER)
|
||||
{
|
||||
#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
|
||||
#ifndef UNIX
|
||||
clip_mch_set_selection(cbd);
|
||||
#endif
|
||||
}
|
||||
else if (clipmethod == CLIPMETHOD_PROVIDER)
|
||||
{
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
clip_provider_set_selection(cbd, clipprovider_name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1401,8 +1413,14 @@ clip_gen_request_selection(Clipboard_T *cbd UNUSED)
|
||||
}
|
||||
else if (clipmethod == CLIPMETHOD_OTHER)
|
||||
{
|
||||
#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
|
||||
#ifndef UNIX
|
||||
clip_mch_request_selection(cbd);
|
||||
#endif
|
||||
}
|
||||
else if (clipmethod == CLIPMETHOD_PROVIDER)
|
||||
{
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
clip_provider_request_selection(cbd, clipprovider_name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -2266,10 +2284,18 @@ clip_get_selection(Clipboard_T *cbd)
|
||||
}
|
||||
else if (!is_clipboard_needs_update())
|
||||
{
|
||||
clip_free_selection(cbd);
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
// We will choose if we want to the free the selection if using provider
|
||||
if (clipmethod != CLIPMETHOD_PROVIDER)
|
||||
clip_free_selection(cbd);
|
||||
#endif
|
||||
|
||||
// Try to get selected text from another window
|
||||
clip_gen_request_selection(cbd);
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
if (clipmethod == CLIPMETHOD_PROVIDER)
|
||||
clip_access_type = CLIP_ACCESS_IMPLICIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3507,15 +3533,34 @@ get_clipmethod(char_u *str, bool *regular, bool *primary)
|
||||
}
|
||||
else if (STRCMP(buf, "other") == 0)
|
||||
{
|
||||
#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
|
||||
#ifndef UNIX
|
||||
method = CLIPMETHOD_OTHER;
|
||||
*regular = *primary = true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = CLIPMETHOD_FAIL;
|
||||
goto exit;
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
// Check if it is the name of a provider
|
||||
int reg = clip_provider_is_available(&clip_plus, buf);
|
||||
int pri = clip_provider_is_available(&clip_star, buf);
|
||||
|
||||
if (reg == 1 || pri == 1)
|
||||
{
|
||||
method = CLIPMETHOD_PROVIDER;
|
||||
|
||||
vim_free(clipprovider_name);
|
||||
clipprovider_name = vim_strsave(buf);
|
||||
|
||||
*regular = reg == 1;
|
||||
*primary = pri == 1;
|
||||
}
|
||||
else if (reg == -1)
|
||||
#endif
|
||||
{
|
||||
ret = CLIPMETHOD_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep on going in order to catch errors
|
||||
@@ -3548,6 +3593,15 @@ clipmethod_to_str(clipmethod_T method)
|
||||
return (char_u *)"gui";
|
||||
case CLIPMETHOD_OTHER:
|
||||
return (char_u *)"other";
|
||||
case CLIPMETHOD_PROVIDER:
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
if (clipprovider_name == NULL)
|
||||
return (char_u *)"none";
|
||||
else
|
||||
return clipprovider_name;
|
||||
#else
|
||||
return (char_u *)"none";
|
||||
#endif
|
||||
default:
|
||||
return (char_u *)"none";
|
||||
}
|
||||
@@ -3584,16 +3638,26 @@ choose_clipmethod(void)
|
||||
clip_plus.did_warn = false;
|
||||
clip_star.did_warn = false;
|
||||
}
|
||||
// Disown clipboard if we are switching to a new method
|
||||
else if (clipmethod != CLIPMETHOD_NONE && method != clipmethod)
|
||||
else if ((clipmethod != CLIPMETHOD_NONE && method != clipmethod))
|
||||
{
|
||||
// Disown clipboard if we are switching to a new method
|
||||
if (clip_star.owned)
|
||||
clip_lose_selection(&clip_star);
|
||||
if (clip_plus.owned)
|
||||
clip_lose_selection(&clip_plus);
|
||||
|
||||
clip_init_single(&clip_plus, regular);
|
||||
clip_init_single(&clip_star, primary);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If availability of a clipboard changed, then update the clipboard
|
||||
// structure.
|
||||
if (regular != clip_plus.available)
|
||||
clip_init_single(&clip_plus, regular);
|
||||
if (primary != clip_star.available)
|
||||
clip_init_single(&clip_star, primary);
|
||||
}
|
||||
|
||||
clipmethod = method;
|
||||
|
||||
@@ -3621,4 +3685,321 @@ ex_clipreset(exarg_T *eap UNUSED)
|
||||
clipmethod_to_str(clipmethod));
|
||||
}
|
||||
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
|
||||
/*
|
||||
* Check if a clipboard provider with given name exists and is available for the
|
||||
* given clipboard. Returns 1 if the provider exists and the 'available'
|
||||
* function returned true, 0 if the provider exists but the function returned
|
||||
* false, and -1 on error.
|
||||
*/
|
||||
static int
|
||||
clip_provider_is_available(Clipboard_T *cbd, char_u *provider)
|
||||
{
|
||||
dict_T *providers = get_vim_var_dict(VV_CLIPPROVIDERS);
|
||||
typval_T provider_tv = {0};
|
||||
callback_T callback = {0};
|
||||
typval_T rettv = {0};
|
||||
typval_T func_tv = {0};
|
||||
char_u *avail;
|
||||
int res = 0;
|
||||
|
||||
if (dict_get_tv(providers, (char *)provider, &provider_tv) == FAIL
|
||||
|| provider_tv.v_type != VAR_DICT)
|
||||
return -1;
|
||||
|
||||
if (dict_get_tv(provider_tv.vval.v_dict, "available", &func_tv) == FAIL)
|
||||
{
|
||||
clear_tv(&provider_tv);
|
||||
// If "available" functon not specified assume always TRUE
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((callback = get_callback(&func_tv)).cb_name == NULL)
|
||||
goto fail;
|
||||
|
||||
if (call_callback(&callback, -1, &rettv, 0, NULL) == FAIL ||
|
||||
rettv.v_type != VAR_STRING)
|
||||
goto fail;
|
||||
|
||||
avail = rettv.vval.v_string;
|
||||
|
||||
if ((vim_strchr(avail, '+') != NULL && cbd == &clip_plus)
|
||||
|| (vim_strchr(avail, '*') != NULL && cbd == &clip_star))
|
||||
res = 1;
|
||||
|
||||
if (FALSE)
|
||||
fail:
|
||||
res = -1;
|
||||
|
||||
free_callback(&callback);
|
||||
clear_tv(&func_tv);
|
||||
clear_tv(&rettv);
|
||||
clear_tv(&provider_tv);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the specified callback "function" from the provider dictionary of for
|
||||
* register "reg".
|
||||
*/
|
||||
static int
|
||||
clip_provider_get_callback(
|
||||
char_u *reg,
|
||||
char_u *provider,
|
||||
char_u *function,
|
||||
callback_T *callback)
|
||||
{
|
||||
dict_T *providers = get_vim_var_dict(VV_CLIPPROVIDERS);
|
||||
typval_T provider_tv;
|
||||
typval_T action_tv;
|
||||
typval_T func_tv;
|
||||
callback_T cb;
|
||||
|
||||
if (dict_get_tv(providers, (char *)provider, &provider_tv) == FAIL)
|
||||
return FAIL;
|
||||
else if (provider_tv.v_type != VAR_DICT)
|
||||
{
|
||||
clear_tv(&provider_tv);
|
||||
return FAIL;
|
||||
}
|
||||
else if (dict_get_tv(
|
||||
provider_tv.vval.v_dict,
|
||||
(char *)function,
|
||||
&action_tv) == FAIL)
|
||||
{
|
||||
clear_tv(&provider_tv);
|
||||
return FAIL;
|
||||
}
|
||||
else if (action_tv.v_type != VAR_DICT)
|
||||
{
|
||||
clear_tv(&provider_tv);
|
||||
clear_tv(&action_tv);
|
||||
return FAIL;
|
||||
}
|
||||
else if (dict_get_tv(action_tv.vval.v_dict, (char *)reg, &func_tv) == FAIL)
|
||||
{
|
||||
clear_tv(&provider_tv);
|
||||
clear_tv(&action_tv);
|
||||
return FAIL;
|
||||
}
|
||||
else if ((cb = get_callback(&func_tv)).cb_name == NULL)
|
||||
{
|
||||
clear_tv(&provider_tv);
|
||||
clear_tv(&action_tv);
|
||||
clear_tv(&func_tv);
|
||||
return FAIL;
|
||||
}
|
||||
clear_tv(&provider_tv);
|
||||
clear_tv(&action_tv);
|
||||
|
||||
// func_tv owns the function name, so we must make a copy for the callback
|
||||
set_callback(callback, &cb);
|
||||
free_callback(&cb);
|
||||
clear_tv(&func_tv);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static void
|
||||
clip_provider_set_selection(Clipboard_T *cbd, char_u *provider)
|
||||
{
|
||||
char_u *reg = (char_u *)(cbd == &clip_star ? "*" : "+");
|
||||
callback_T callback;
|
||||
typval_T rettv;
|
||||
typval_T argvars[4];
|
||||
yankreg_T *y_ptr;
|
||||
char_u type[2 + NUMBUFLEN] = {0};
|
||||
list_T *list = NULL;
|
||||
|
||||
if (clip_provider_get_callback(
|
||||
reg,
|
||||
provider,
|
||||
(char_u *)"copy",
|
||||
&callback) == FAIL)
|
||||
return;
|
||||
|
||||
// Possibly get selected text, if using autoselect for 'clipboard'
|
||||
cbd->owned = TRUE;
|
||||
clip_get_selection(cbd);
|
||||
cbd->owned = FALSE;
|
||||
|
||||
// Convert register type into a string
|
||||
if (cbd == &clip_plus)
|
||||
y_ptr = get_y_register(PLUS_REGISTER);
|
||||
else
|
||||
y_ptr = get_y_register(STAR_REGISTER);
|
||||
|
||||
switch (y_ptr->y_type)
|
||||
{
|
||||
case MCHAR:
|
||||
type[0] = 'v';
|
||||
break;
|
||||
case MLINE:
|
||||
type[0] = 'V';
|
||||
break;
|
||||
case MBLOCK:
|
||||
sprintf((char *)type, "%c%d", Ctrl_V, y_ptr->y_width + 1);
|
||||
break;
|
||||
default:
|
||||
type[0] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
argvars[0].v_type = VAR_STRING;
|
||||
argvars[0].vval.v_string = reg;
|
||||
|
||||
argvars[1].v_type = VAR_STRING;
|
||||
argvars[1].vval.v_string = type;
|
||||
|
||||
// Get register contents by creating a list of lines
|
||||
list = list_alloc();
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
free_callback(&callback);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < y_ptr->y_size; i++)
|
||||
if (list_append_string(list, y_ptr->y_array[i].string, -1) == FAIL)
|
||||
{
|
||||
free_callback(&callback);
|
||||
list_unref(list);
|
||||
return;
|
||||
}
|
||||
|
||||
list->lv_refcount++;
|
||||
|
||||
argvars[2].v_type = VAR_LIST;
|
||||
argvars[2].v_lock = VAR_FIXED;
|
||||
argvars[2].vval.v_list = list;
|
||||
|
||||
argvars[3].v_type = VAR_UNKNOWN;
|
||||
|
||||
textlock++;
|
||||
call_callback(&callback, -1, &rettv, 3, argvars);
|
||||
clear_tv(&rettv);
|
||||
textlock--;
|
||||
|
||||
free_callback(&callback);
|
||||
list_unref(list);
|
||||
}
|
||||
|
||||
static void
|
||||
clip_provider_request_selection(Clipboard_T *cbd, char_u *provider)
|
||||
{
|
||||
char_u *reg = (char_u *)(cbd == &clip_star ? "*" : "+");
|
||||
callback_T callback;
|
||||
typval_T argvars[3];
|
||||
typval_T rettv;
|
||||
int ret;
|
||||
char_u *reg_type;
|
||||
list_T *lines;
|
||||
|
||||
if (clip_provider_get_callback(
|
||||
reg,
|
||||
provider,
|
||||
(char_u *)"paste",
|
||||
&callback) == FAIL)
|
||||
return;
|
||||
|
||||
argvars[0].v_type = VAR_STRING;
|
||||
argvars[0].vval.v_string = reg;
|
||||
|
||||
argvars[1].v_type = VAR_STRING;
|
||||
argvars[1].vval.v_string = (char_u *)
|
||||
(clip_access_type == CLIP_ACCESS_EXPLICIT ? "explicit" : "implicit");
|
||||
|
||||
argvars[2].v_type = VAR_UNKNOWN;
|
||||
|
||||
textlock++;
|
||||
ret = call_callback(&callback, -1, &rettv, 2, argvars);
|
||||
textlock--;
|
||||
|
||||
if (ret == FAIL)
|
||||
goto exit;
|
||||
else if (rettv.v_type == VAR_STRING
|
||||
&& STRCMP(rettv.vval.v_string, "clear") == 0)
|
||||
{
|
||||
clip_free_selection(cbd);
|
||||
goto exit;
|
||||
}
|
||||
else if (rettv.v_type == VAR_STRING
|
||||
&& STRCMP(rettv.vval.v_string, "previous") == 0)
|
||||
goto exit;
|
||||
else if (rettv.v_type == VAR_TUPLE
|
||||
&& TUPLE_LEN(rettv.vval.v_tuple) == 2
|
||||
&& TUPLE_ITEM(rettv.vval.v_tuple, 0)->v_type == VAR_STRING
|
||||
&& TUPLE_ITEM(rettv.vval.v_tuple, 1)->v_type == VAR_LIST)
|
||||
{
|
||||
reg_type = TUPLE_ITEM(rettv.vval.v_tuple, 0)->vval.v_string;
|
||||
lines = TUPLE_ITEM(rettv.vval.v_tuple, 1)->vval.v_list;
|
||||
}
|
||||
else if (rettv.v_type == VAR_LIST
|
||||
&& rettv.vval.v_list->lv_len == 2
|
||||
&& rettv.vval.v_list->lv_first->li_tv.v_type == VAR_STRING
|
||||
&& rettv.vval.v_list->lv_first->li_next->li_tv.v_type == VAR_LIST)
|
||||
{
|
||||
reg_type = rettv.vval.v_list->lv_first->li_tv.vval.v_string;
|
||||
lines = rettv.vval.v_list->lv_first->li_next->li_tv.vval.v_list;
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
{
|
||||
char_u yank_type = MAUTO;
|
||||
long block_len = -1;
|
||||
yankreg_T *y_ptr;
|
||||
char_u **contents;
|
||||
listitem_T *li;
|
||||
int i = 0;
|
||||
|
||||
contents = ALLOC_MULT(char_u *, lines->lv_len + 1); // Ends with a NULL
|
||||
|
||||
if (contents == NULL)
|
||||
goto exit;
|
||||
|
||||
// Convert strings in list to type char_u **
|
||||
FOR_ALL_LIST_ITEMS(lines, li)
|
||||
{
|
||||
char_u *str = tv_get_string_chk(&li->li_tv);
|
||||
|
||||
if (str == NULL)
|
||||
goto exit;
|
||||
|
||||
contents[i++] = vim_strsave(str);
|
||||
}
|
||||
contents[i] = NULL;
|
||||
|
||||
if (STRLEN(reg_type) > 0
|
||||
&& get_yank_type(®_type, &yank_type, &block_len) == FAIL)
|
||||
goto exit;
|
||||
|
||||
if (cbd == &clip_plus)
|
||||
y_ptr = get_y_register(PLUS_REGISTER);
|
||||
else
|
||||
y_ptr = get_y_register(STAR_REGISTER);
|
||||
|
||||
clip_free_selection(cbd);
|
||||
|
||||
str_to_reg(y_ptr,
|
||||
yank_type,
|
||||
(char_u *)contents,
|
||||
STRLEN(contents),
|
||||
block_len,
|
||||
TRUE);
|
||||
|
||||
for (int k = 0; k < i; k++)
|
||||
vim_free(contents[k]);
|
||||
vim_free(contents);
|
||||
}
|
||||
|
||||
exit:
|
||||
free_callback(&callback);
|
||||
clear_tv(&rettv);
|
||||
}
|
||||
|
||||
#endif // FEAT_CLIPBOARD_PROVIDER
|
||||
|
||||
#endif // FEAT_CLIPBOARD
|
||||
|
@@ -528,3 +528,6 @@
|
||||
|
||||
/* Define if you want to load libgpm dynamically */
|
||||
#undef DYNAMIC_GPM
|
||||
|
||||
/* Define if you want to have clipboard provider functionality*/
|
||||
#undef FEAT_CLIPBOARD_PROVIDER
|
||||
|
@@ -2434,6 +2434,21 @@ AC_ARG_ENABLE(fontset,
|
||||
AC_MSG_RESULT($enable_fontset)
|
||||
dnl defining FEAT_XFONTSET is delayed, so that it can be disabled for no GUI
|
||||
|
||||
AC_MSG_CHECKING(--enable-clipboard-provider)
|
||||
AC_ARG_ENABLE(clipboard-provider,
|
||||
[ --enable-clipboard-provider Include clipboard provider support.],
|
||||
[enable_clipboard_provider=$enableval
|
||||
AC_MSG_RESULT($enableval)],
|
||||
AS_IF([test "x$features" = xtiny],
|
||||
[enable_clipboard_provider="no"
|
||||
AC_MSG_RESULT([cannot use clipboard provider with tiny features])],
|
||||
[enable_clipboard_provider="yes"
|
||||
AC_MSG_RESULT([yes])]))
|
||||
if test "$enable_clipboard_provider" = "yes"; then
|
||||
AC_DEFINE(FEAT_CLIPBOARD_PROVIDER)
|
||||
fi
|
||||
|
||||
|
||||
AC_MSG_CHECKING(if shm_open is available)
|
||||
cppflags_save=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $X_CFLAGS"
|
||||
|
@@ -6500,6 +6500,11 @@ f_getreg(typval_T *argvars, typval_T *rettv)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
if (clipmethod == CLIPMETHOD_PROVIDER)
|
||||
clip_access_type = CLIP_ACCESS_EXPLICIT;
|
||||
#endif
|
||||
|
||||
if (return_list)
|
||||
{
|
||||
rettv->v_type = VAR_LIST;
|
||||
@@ -6866,6 +6871,13 @@ f_has(typval_T *argvars, typval_T *rettv)
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{"clipboard_provider",
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{"cmdline_compl", 1},
|
||||
@@ -11493,7 +11505,7 @@ f_setpos(typval_T *argvars, typval_T *rettv)
|
||||
/*
|
||||
* Translate a register type string to the yank type and block length
|
||||
*/
|
||||
static int
|
||||
int
|
||||
get_yank_type(char_u **pp, char_u *yank_type, long *block_len)
|
||||
{
|
||||
char_u *stropt = *pp;
|
||||
|
@@ -166,7 +166,8 @@ static struct vimvar
|
||||
{VV_NAME("wayland_display", VAR_STRING), NULL, VV_RO},
|
||||
{VV_NAME("clipmethod", VAR_STRING), NULL, VV_RO},
|
||||
{VV_NAME("termda1", VAR_STRING), NULL, VV_RO},
|
||||
{VV_NAME("termosc", VAR_STRING), NULL, VV_RO},
|
||||
{VV_NAME("termosc", VAR_STRING), NULL, VV_RO},
|
||||
{VV_NAME("clipproviders", VAR_DICT), &t_dict_string, VV_RO}
|
||||
};
|
||||
|
||||
// shorthand
|
||||
|
@@ -905,6 +905,19 @@
|
||||
# define FEAT_CLIPBOARD
|
||||
#endif
|
||||
|
||||
/*
|
||||
* +clipboard_provider Allow Vim to use clipboard providers
|
||||
*/
|
||||
#if defined(FEAT_CLIPBOARD_PROVIDER)
|
||||
# ifndef FEAT_EVAL
|
||||
# undef FEAT_CLIPBOARD_PROVIDER
|
||||
# else
|
||||
# ifndef FEAT_CLIPBOARD
|
||||
# define FEAT_CLIPBOARD
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_GUI
|
||||
# ifndef FEAT_CLIPBOARD
|
||||
# define FEAT_CLIPBOARD
|
||||
|
@@ -972,7 +972,8 @@ EXTERN int gui_win_y INIT(= -1);
|
||||
|
||||
#ifdef FEAT_CLIPBOARD
|
||||
EXTERN Clipboard_T clip_star; // PRIMARY selection in X11/Wayland
|
||||
# if defined(FEAT_X11) || defined(FEAT_WAYLAND_CLIPBOARD)
|
||||
# if defined(FEAT_X11) || defined(FEAT_WAYLAND_CLIPBOARD) \
|
||||
|| ((defined(UNIX) || defined(VMS)) && defined(FEAT_CLIPBOARD_PROVIDER))
|
||||
EXTERN Clipboard_T clip_plus; // CLIPBOARD selection in X11/Wayland
|
||||
# else
|
||||
# define clip_plus clip_star // there is only one clipboard
|
||||
@@ -2067,6 +2068,9 @@ EXTERN int p_tgc_set INIT(= FALSE);
|
||||
|
||||
#ifdef FEAT_CLIPBOARD
|
||||
EXTERN clipmethod_T clipmethod INIT(= CLIPMETHOD_NONE);
|
||||
# ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
EXTERN char_u *clipprovider_name INIT(= NULL);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_WAYLAND
|
||||
@@ -2116,3 +2120,16 @@ INIT(= CLIENTSERVER_METHOD_NONE);
|
||||
// Path to socket of last client that communicated with us
|
||||
EXTERN char_u *client_socket INIT(= NULL);
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
typedef enum
|
||||
{
|
||||
CLIP_ACCESS_IMPLICIT,
|
||||
CLIP_ACCESS_EXPLICIT,
|
||||
} clip_access_T;
|
||||
|
||||
// Only relevant for the clipboard provider feature. This indicates if the
|
||||
// clipboard request is implicit (ex. access when doing :registers),
|
||||
// explicit (ex. typing "+p). Always defaults to implicit.
|
||||
EXTERN clip_access_T clip_access_type INIT(= CLIP_ACCESS_IMPLICIT);
|
||||
#endif
|
||||
|
@@ -28,4 +28,5 @@ void f_len(typval_T *argvars, typval_T *rettv);
|
||||
void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
|
||||
void range_list_materialize(list_T *list);
|
||||
long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir, typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit);
|
||||
int get_yank_type(char_u **pp, char_u *yank_type, long *block_len);
|
||||
/* vim: set ft=c : */
|
||||
|
@@ -1559,6 +1559,10 @@ do_put(
|
||||
#ifdef FEAT_CLIPBOARD
|
||||
// Adjust register name for "unnamed" in 'clipboard'.
|
||||
adjust_clip_reg(®name);
|
||||
# ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
if (clipmethod == CLIPMETHOD_PROVIDER)
|
||||
clip_access_type = CLIP_ACCESS_EXPLICIT;
|
||||
# endif
|
||||
(void)may_get_selection(regname);
|
||||
#endif
|
||||
|
||||
|
@@ -105,6 +105,7 @@ NEW_TESTS = \
|
||||
test_cjk_linebreak \
|
||||
test_clientserver \
|
||||
test_clipmethod \
|
||||
test_clipboard_provider \
|
||||
test_close_count \
|
||||
test_cmd_lists \
|
||||
test_cmdline \
|
||||
@@ -395,6 +396,7 @@ NEW_TESTS_RES = \
|
||||
test_cjk_linebreak.res \
|
||||
test_clientserver.res \
|
||||
test_clipmethod.res \
|
||||
test_clipboard_provider.res \
|
||||
test_close_count.res \
|
||||
test_cmd_lists.res \
|
||||
test_cmdline.res \
|
||||
|
170
src/testdir/test_clipboard_provider.vim
Normal file
170
src/testdir/test_clipboard_provider.vim
Normal file
@@ -0,0 +1,170 @@
|
||||
" Test for clipboard provider feature
|
||||
|
||||
CheckFeature clipboard_provider
|
||||
|
||||
func! AvailableBoth()
|
||||
return "+*"
|
||||
endfunc
|
||||
|
||||
func! AvailablePlus()
|
||||
return "+"
|
||||
endfunc
|
||||
|
||||
func! PasteList(reg, type)
|
||||
return ["c", ["list"]]
|
||||
endfunc
|
||||
|
||||
func! PasteTuple(reg, type)
|
||||
return ("", ["tuple", "of", "strings"])
|
||||
endfunc
|
||||
|
||||
func! PasteType(reg, type)
|
||||
let g:vim_test_type = a:type
|
||||
return ("c", [a:type])
|
||||
endfunc
|
||||
|
||||
func! PasteRegType(reg, type)
|
||||
return (g:vim_test_reg_type, ["7 chars"])
|
||||
endfunc
|
||||
|
||||
func! Copy(reg, type, lines)
|
||||
let g:vim_test_stuff = {
|
||||
\ "type": a:type,
|
||||
\ "lines": a:lines
|
||||
\ }
|
||||
endfunc
|
||||
|
||||
" Test if "available" function works properly for provider
|
||||
func Test_clipboard_provider_available()
|
||||
CheckUnix
|
||||
let v:clipproviders["test"] = {
|
||||
\ "available": function("AvailablePlus"),
|
||||
\ "paste": {
|
||||
\ '+': function("PasteList"),
|
||||
\ '*': function("PasteList")
|
||||
\ }
|
||||
\ }
|
||||
|
||||
set clipmethod=test
|
||||
call assert_equal("test", v:clipmethod)
|
||||
|
||||
call assert_equal("list", getreg("+"))
|
||||
" Test if star register is unavailable
|
||||
call assert_equal("", getreg("*"))
|
||||
|
||||
let v:clipproviders["test"] = {
|
||||
\ "available": function("AvailableBoth"),
|
||||
\ "paste": {
|
||||
\ '+': function("PasteList"),
|
||||
\ '*': function("PasteList")
|
||||
\ }
|
||||
\ }
|
||||
|
||||
clipreset
|
||||
|
||||
call assert_equal("list", getreg("+"))
|
||||
call assert_equal("list", getreg("*"))
|
||||
|
||||
let v:clipproviders["test"] = {
|
||||
\ "paste": {
|
||||
\ '+': function("PasteList"),
|
||||
\ '*': function("PasteList")
|
||||
\ }
|
||||
\ }
|
||||
|
||||
" Should default to TRUE
|
||||
call assert_equal("list", getreg("+"))
|
||||
call assert_equal("list", getreg("*"))
|
||||
|
||||
set clipmethod&
|
||||
endfunc
|
||||
|
||||
" Test if "paste" functions work properly for provider
|
||||
func Test_clipboard_provider_paste()
|
||||
" Test if tuples and lists work the same
|
||||
let v:clipproviders["test"] = {
|
||||
\ "paste": {
|
||||
\ '*': function("PasteList")
|
||||
\ }
|
||||
\ }
|
||||
|
||||
set clipmethod=test
|
||||
call assert_equal("test", v:clipmethod)
|
||||
|
||||
call assert_equal("list", getreg("*"))
|
||||
|
||||
let v:clipproviders["test"] = {
|
||||
\ "paste": {
|
||||
\ '*': function("PasteTuple")
|
||||
\ }
|
||||
\ }
|
||||
|
||||
call assert_equal("tuple\nof\nstrings\n", getreg("*"))
|
||||
|
||||
" Test if "implicit" and "explicit" arguments are correctly used
|
||||
let v:clipproviders["test"] = {
|
||||
\ "paste": {
|
||||
\ '*': function("PasteType")
|
||||
\ }
|
||||
\ }
|
||||
|
||||
call assert_equal("explicit", getreg("*"))
|
||||
|
||||
:registers
|
||||
|
||||
call assert_equal("implicit", g:vim_test_type)
|
||||
unlet g:vim_test_type
|
||||
|
||||
" Test if correct register type is used
|
||||
let v:clipproviders["test"] = {
|
||||
\ "paste": {
|
||||
\ '*': function("PasteRegType")
|
||||
\ }
|
||||
\ }
|
||||
|
||||
let g:vim_test_reg_type = "v"
|
||||
call assert_equal("v", getregtype("*"))
|
||||
let g:vim_test_reg_type = "c"
|
||||
call assert_equal("v", getregtype("*"))
|
||||
|
||||
let g:vim_test_reg_type = "l"
|
||||
call assert_equal("V", getregtype("*"))
|
||||
let g:vim_test_reg_type = "l"
|
||||
call assert_equal("V", getregtype("*"))
|
||||
|
||||
let g:vim_test_reg_type = "b"
|
||||
call assert_equal("7", getregtype("*"))
|
||||
let g:vim_test_reg_type = ""
|
||||
call assert_equal("7", getregtype("*"))
|
||||
|
||||
let g:vim_test_reg_type = "b40"
|
||||
call assert_equal("40", getregtype("*"))
|
||||
|
||||
set clipmethod&
|
||||
endfunc
|
||||
|
||||
" Test if "copy" functions work properly for provider
|
||||
func Test_clipboard_provider_copy()
|
||||
let v:clipproviders["test"] = {
|
||||
\ "copy": {
|
||||
\ '*': function("Copy")
|
||||
\ }
|
||||
\ }
|
||||
|
||||
set clipmethod=test
|
||||
call assert_equal("test", v:clipmethod)
|
||||
|
||||
call setreg("*", ["hello", "world", "!"], "c")
|
||||
call assert_equal(["hello", "world", "!"], g:vim_test_stuff.lines)
|
||||
call assert_equal("v", g:vim_test_stuff.type)
|
||||
|
||||
call setreg("*", ["hello", "world", "!"], "l")
|
||||
call assert_equal(["hello", "world", "!"], g:vim_test_stuff.lines)
|
||||
call assert_equal("V", g:vim_test_stuff.type)
|
||||
|
||||
call setreg("*", ["hello", "world", "!"], "b40")
|
||||
call assert_equal(["hello", "world", "!"], g:vim_test_stuff.lines)
|
||||
call assert_equal("40", g:vim_test_stuff.type)
|
||||
|
||||
set clipmethod&
|
||||
endfunc
|
@@ -155,6 +155,11 @@ static char *(features[]) =
|
||||
"+clipboard",
|
||||
#else
|
||||
"-clipboard",
|
||||
#endif
|
||||
#ifdef FEAT_CLIPBOARD_PROVIDER
|
||||
"+clipboard_provider",
|
||||
#else
|
||||
"-clipboard_provider",
|
||||
#endif
|
||||
"+cmdline_compl",
|
||||
"+cmdline_hist",
|
||||
@@ -729,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1857,
|
||||
/**/
|
||||
1856,
|
||||
/**/
|
||||
|
@@ -2256,7 +2256,8 @@ typedef int sock_T;
|
||||
#define VV_CLIPMETHOD 113
|
||||
#define VV_TERMDA1 114
|
||||
#define VV_TERMOSC 115
|
||||
#define VV_LEN 116 // number of v: vars
|
||||
#define VV_CLIPPROVIDERS 116
|
||||
#define VV_LEN 117 // number of v: vars
|
||||
|
||||
// used for v_number in VAR_BOOL and VAR_SPECIAL
|
||||
#define VVAL_FALSE 0L // VAR_BOOL
|
||||
@@ -2318,6 +2319,7 @@ typedef enum {
|
||||
CLIPMETHOD_X11,
|
||||
CLIPMETHOD_GUI,
|
||||
CLIPMETHOD_OTHER,
|
||||
CLIPMETHOD_PROVIDER
|
||||
} clipmethod_T;
|
||||
|
||||
// Info about selected text
|
||||
|
Reference in New Issue
Block a user