aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2014-12-08 18:23:09 -0500
committerJustin M. Keyes <justinkz@gmail.com>2014-12-08 18:23:09 -0500
commit8bb7aa329d20cb265d8952c96c84a0e54a5726ab (patch)
tree83a0ac7a24243d357c75ee976298901642df92c2
parent8666a148ccacefe2d574eb2c1f2887b740fe6bfc (diff)
parentdf2eeaeb375a7a7f7cb92586b03d10260d485c90 (diff)
downloadrneovim-8bb7aa329d20cb265d8952c96c84a0e54a5726ab.tar.gz
rneovim-8bb7aa329d20cb265d8952c96c84a0e54a5726ab.tar.bz2
rneovim-8bb7aa329d20cb265d8952c96c84a0e54a5726ab.zip
Merge pull request #1182 from bfredl/clipboard
clipboard: support separate +/* clipboards, linewise copy/paste and add tests
-rw-r--r--runtime/autoload/provider/clipboard.vim36
-rw-r--r--runtime/doc/options.txt7
-rw-r--r--src/nvim/eval.c20
-rw-r--r--src/nvim/normal.c12
-rw-r--r--src/nvim/ops.c163
-rw-r--r--src/nvim/option.c10
-rw-r--r--src/nvim/option_defs.h8
-rw-r--r--test/functional/clipboard/autoload/provider/clipboard.vim16
-rw-r--r--test/functional/clipboard/clipboard_provider_spec.lua141
9 files changed, 319 insertions, 94 deletions
diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim
index 46c05a882c..458ef6257d 100644
--- a/runtime/autoload/provider/clipboard.vim
+++ b/runtime/autoload/provider/clipboard.vim
@@ -1,11 +1,11 @@
" The clipboard provider uses shell commands to communicate with the clipboard.
" The provider function will only be registered if one of the supported
" commands are available.
-let s:copy = ''
-let s:paste = ''
+let s:copy = {}
+let s:paste = {}
function! s:try_cmd(cmd, ...)
- let out = a:0 ? systemlist(a:cmd, a:1) : systemlist(a:cmd)
+ let out = a:0 ? systemlist(a:cmd, a:1, 1) : systemlist(a:cmd, [''], 1)
if v:shell_error
echo "clipboard: error: ".(len(out) ? out[0] : '')
return ''
@@ -14,14 +14,20 @@ function! s:try_cmd(cmd, ...)
endfunction
if executable('pbcopy')
- let s:copy = 'pbcopy'
- let s:paste = 'pbpaste'
-elseif executable('xsel')
- let s:copy = 'xsel -i -b'
- let s:paste = 'xsel -o -b'
+ let s:copy['+'] = 'pbcopy'
+ let s:paste['+'] = 'pbpaste'
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
elseif executable('xclip')
- let s:copy = 'xclip -i -selection clipboard'
- let s:paste = 'xclip -o -selection clipboard'
+ let s:copy['+'] = 'xclip -i -selection clipboard'
+ let s:paste['+'] = 'xclip -o -selection clipboard'
+ let s:copy['*'] = 'xclip -i -selection primary'
+ let s:paste['*'] = 'xclip -o -selection primary'
+elseif executable('xsel')
+ let s:copy['+'] = 'xsel -i -b'
+ let s:paste['+'] = 'xsel -o -b'
+ let s:copy['*'] = 'xsel -i -p'
+ let s:paste['*'] = 'xsel -o -p'
else
echom 'clipboard: No shell command for communicating with the clipboard found.'
finish
@@ -29,14 +35,14 @@ endif
let s:clipboard = {}
-function! s:clipboard.get(...)
- return s:try_cmd(s:paste)
+function! s:clipboard.get(reg)
+ return s:try_cmd(s:paste[a:reg])
endfunction
-function! s:clipboard.set(...)
- call s:try_cmd(s:copy, a:1)
+function! s:clipboard.set(lines, regtype, reg)
+ call s:try_cmd(s:copy[a:reg], a:lines)
endfunction
function! provider#clipboard#Call(method, args)
- return s:clipboard[a:method](a:args)
+ return call(s:clipboard[a:method],a:args,s:clipboard)
endfunction
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 0844d74070..8672ab2af9 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -7547,13 +7547,6 @@ A jump table for the options with a short description can be found at |Q_op|.
Note that this causes the whole buffer to be stored in memory. Set
this option to a lower value if you run out of memory.
- {Nvim} *'unnamedclip'* *ucp'*
-'unnamedclip' 'ucp' boolean (default off)
- global
- Use the unnamed register to access the clipboard(when available).
- This option has the same effect of setting 'clipboard' to
- 'unnamed/unnamedplus' in Vim.
-
*'updatecount'* *'uc'*
'updatecount' 'uc' number (default: 200)
global
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index be69bdbe61..b4d1677520 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -5119,6 +5119,20 @@ void list_append_tv(list_T *l, typval_T *tv)
}
/*
+ * Add a list to a list.
+ */
+void list_append_list(list_T *list, list_T *itemlist)
+{
+ listitem_T *li = listitem_alloc();
+
+ li->li_tv.v_type = VAR_LIST;
+ li->li_tv.v_lock = 0;
+ li->li_tv.vval.v_list = itemlist;
+ list_append(list, li);
+ ++list->lv_refcount;
+}
+
+/*
* Add a dictionary to a list. Used by getqflist().
*/
void list_append_dict(list_T *list, dict_T *dict)
@@ -19815,16 +19829,12 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments)
bool eval_has_provider(char *name)
{
-#define source_provider(name) \
- do_source((uint8_t *)"$VIMRUNTIME/autoload/provider/" name ".vim", \
- false, \
- false)
#define check_provider(name) \
if (has_##name == -1) { \
has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
if (!has_##name) { \
- source_provider(#name); \
+ script_autoload((uint8_t *)"provider#" #name "#Call", false); \
has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
} \
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 1b21100933..192633a996 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -915,14 +915,7 @@ getcount:
&& !oap->op_type
&& (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG))) {
clearop(oap);
- {
- int regname = 0;
-
- /* Adjust the register according to 'clipboard', so that when
- * "unnamed" is present it becomes '*' or '+' instead of '"'. */
- adjust_clipboard_register(&regname);
- set_reg_var(regname);
- }
+ set_reg_var(0);
}
/* Get the length of mapped chars again after typing a count, second
@@ -5105,7 +5098,6 @@ static void nv_brackets(cmdarg_T *cap)
end = equalpos(start, VIsual) ? curwin->w_cursor : VIsual;
curwin->w_cursor = (dir == BACKWARD ? start : end);
}
- adjust_clipboard_register(&regname);
prep_redo_cmd(cap);
do_put(regname, dir, cap->count1, PUT_FIXINDENT);
if (was_visual) {
@@ -7272,10 +7264,8 @@ static void nv_put(cmdarg_T *cap)
*/
was_visual = true;
regname = cap->oap->regname;
- bool adjusted = adjust_clipboard_register(&regname);
if (regname == 0 || regname == '"'
|| VIM_ISDIGIT(regname) || regname == '-'
- || adjusted
) {
/* The delete is going to overwrite the register we want to
* put, save it first. */
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 6bf3f6036f..c20a017088 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -60,6 +60,7 @@
#define DELETION_REGISTER 36
#define CLIP_REGISTER 37
+# define CB_UNNAMEDMASK (CB_UNNAMED | CB_UNNAMEDPLUS)
/*
* Each yank register is an array of pointers to lines.
*/
@@ -74,6 +75,7 @@ static struct yankreg *y_current; /* ptr to current yankreg */
static int y_append; /* TRUE when appending */
static struct yankreg *y_previous = NULL; /* ptr to last written yankreg */
+static bool clipboard_didwarn_unnamed = false;
/*
* structure used by block_prep, op_delete and op_yank for blockwise operators
* also op_change, op_shift, op_insert, op_replace - AKelly
@@ -751,7 +753,8 @@ void get_yank_register(int regname, int writing)
int i;
y_append = FALSE;
- if ((regname == 0 || regname == '"') && !writing && y_previous != NULL) {
+ int unnamedclip = cb_flags & CB_UNNAMEDMASK;
+ if ((regname == 0 || regname == '"') && !unnamedclip && !writing && y_previous != NULL) {
y_current = y_previous;
return;
}
@@ -1302,18 +1305,6 @@ cmdline_paste_reg (
return OK;
}
-bool adjust_clipboard_register(int *rp)
-{
- // If no reg. specified and 'unnamedclip' is set, use the
- // clipboard register.
- if (*rp == 0 && p_unc && eval_has_provider("clipboard")) {
- *rp = '+';
- return true;
- }
-
- return false;
-}
-
/*
* Handle a delete operation.
*
@@ -1328,7 +1319,6 @@ int op_delete(oparg_T *oap)
struct block_def bd;
linenr_T old_lcount = curbuf->b_ml.ml_line_count;
int did_yank = FALSE;
- int orig_regname = oap->regname;
if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to do */
return OK;
@@ -1342,8 +1332,6 @@ int op_delete(oparg_T *oap)
return FAIL;
}
- bool adjusted = adjust_clipboard_register(&oap->regname);
-
if (has_mbyte)
mb_adjust_opend(oap);
@@ -1393,9 +1381,10 @@ int op_delete(oparg_T *oap)
* register. For the black hole register '_' don't yank anything.
*/
if (oap->regname != '_') {
- if (oap->regname != 0) {
+ bool unnamedclip = oap->regname == 0 && (cb_flags & CB_UNNAMEDMASK);
+ if (oap->regname != 0 || unnamedclip) {
/* check for read-only register */
- if (!valid_yank_reg(oap->regname, TRUE)) {
+ if (!( valid_yank_reg(oap->regname, TRUE) || unnamedclip )) {
beep_flush();
return OK;
}
@@ -1407,10 +1396,8 @@ int op_delete(oparg_T *oap)
/*
* Put deleted text into register 1 and shift number registers if the
* delete contains a line break, or when a regname has been specified.
- * Use the register name from before adjust_clip_reg() may have
- * changed it.
*/
- if (orig_regname != 0 || oap->motion_type == MLINE
+ if (oap->regname != 0 || oap->motion_type == MLINE
|| oap->line_count > 1 || oap->use_reg_one) {
y_current = &y_regs[9];
free_yank_all(); /* free register nine */
@@ -1424,9 +1411,7 @@ int op_delete(oparg_T *oap)
/* Yank into small delete register when no named register specified
* and the delete is within one line. */
- if ((
- adjusted ||
- oap->regname == 0) && oap->motion_type != MLINE
+ if (oap->regname == 0 && oap->motion_type != MLINE
&& oap->line_count == 1) {
oap->regname = '-';
get_yank_register(oap->regname, TRUE);
@@ -2623,7 +2608,6 @@ do_put (
int allocated = FALSE;
long cnt;
- adjust_clipboard_register(&regname);
get_clipboard(regname);
if (flags & PUT_FIXINDENT)
@@ -3215,7 +3199,6 @@ void ex_display(exarg_T *eap)
)
continue; /* did not ask for this register */
- adjust_clipboard_register(&name);
get_clipboard(name);
if (i == -1) {
@@ -4842,6 +4825,7 @@ void write_reg_contents_ex(int name,
if (!y_append && !must_append)
free_yank_all();
str_to_reg(y_current, yank_type, str, len, block_len);
+ set_clipboard(name);
/* ':let @" = "val"' should change the meaning of the "" register */
@@ -5225,33 +5209,82 @@ static void free_register(struct yankreg *reg)
y_current = curr;
}
-static void copy_register(struct yankreg *dest, struct yankreg *src)
-{
- free_register(dest);
- *dest = *src;
- dest->y_array = xcalloc(src->y_size, sizeof(uint8_t *));
- for (int j = 0; j < src->y_size; ++j) {
- dest->y_array[j] = (uint8_t *)xstrdup((char *)src->y_array[j]);
+// return target register
+static int adjust_clipboard_name(int *name) {
+ if (*name == '*' || *name == '+') {
+ if(!eval_has_provider("clipboard")) {
+ EMSG("clipboard: provider is not available");
+ return -1;
+ }
+ return CLIP_REGISTER;
+ } else if (*name == NUL && (cb_flags & (CB_UNNAMED | CB_UNNAMEDPLUS))) {
+ if(!eval_has_provider("clipboard")) {
+ if (!clipboard_didwarn_unnamed) {
+ msg((char_u*)"clipboard: provider not available, ignoring clipboard=unnamed[plus]");
+ clipboard_didwarn_unnamed = true;
+ }
+ return -1;
+ }
+ if (cb_flags & CB_UNNAMEDPLUS) {
+ *name = '+';
+ } else {
+ *name = '*';
+ }
+ return 0; //unnamed
}
+ // don't do anything for other register names
+ return -1;
}
static void get_clipboard(int name)
{
- if (!(name == '*' || name == '+'
- || (p_unc && !name && eval_has_provider("clipboard")))) {
+ int ireg = adjust_clipboard_name(&name);
+ if (ireg < 0) {
return;
}
- struct yankreg *reg = &y_regs[CLIP_REGISTER];
+ struct yankreg *reg = &y_regs[ireg];
free_register(reg);
+
list_T *args = list_alloc();
+ char_u regname = name;
+ list_append_string(args, &regname, 1);
+
typval_T result = eval_call_provider("clipboard", "get", args);
if (result.v_type != VAR_LIST) {
goto err;
}
- list_T *lines = result.vval.v_list;
+ list_T *res = result.vval.v_list, *lines = NULL;
+ if (res->lv_len == 2 && res->lv_first->li_tv.v_type == VAR_LIST) {
+ lines = res->lv_first->li_tv.vval.v_list;
+ if (res->lv_last->li_tv.v_type != VAR_STRING) {
+ goto err;
+ }
+ char_u* regtype = res->lv_last->li_tv.vval.v_string;
+ if (regtype == NULL || strlen((char*)regtype) != 1) {
+ goto err;
+ }
+ switch (regtype[0]) {
+ case 'v': case 'c':
+ reg->y_type = MCHAR;
+ break;
+ case 'V': case 'l':
+ reg->y_type = MLINE;
+ break;
+ case 'b': case Ctrl_V:
+ reg->y_type = MBLOCK;
+ break;
+ default:
+ goto err;
+ }
+ } else {
+ lines = res;
+ // provider did not specify regtype, calculate it below
+ reg->y_type = MAUTO;
+ }
+
reg->y_array = xcalloc(lines->lv_len, sizeof(uint8_t *));
reg->y_size = lines->lv_len;
@@ -5263,9 +5296,23 @@ static void get_clipboard(int name)
reg->y_array[i++] = (uint8_t *)xstrdup((char *)li->li_tv.vval.v_string);
}
- if (!name && p_unc) {
- // copy to the unnamed register
- copy_register(&y_regs[0], reg);
+ if (reg->y_type == MAUTO) {
+ if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) {
+ reg->y_type = MLINE;
+ free(reg->y_array[reg->y_size-1]);
+ reg->y_size--;
+ } else {
+ reg->y_type = MCHAR;
+ }
+ } else if (reg->y_type == MBLOCK) {
+ int maxlen = 0;
+ for (int i = 0; i < reg->y_size; i++) {
+ int rowlen = STRLEN(reg->y_array[i]);
+ if (rowlen > maxlen) {
+ maxlen = rowlen;
+ }
+ }
+ reg->y_width = maxlen-1;
}
return;
@@ -5279,22 +5326,17 @@ err:
}
reg->y_array = NULL;
reg->y_size = 0;
- EMSG("Clipboard provider returned invalid data");
+ EMSG("clipboard: provider returned invalid data");
}
static void set_clipboard(int name)
{
- if (!(name == '*' || name == '+'
- || (p_unc && !name && eval_has_provider("clipboard")))) {
+ int ireg = adjust_clipboard_name(&name);
+ if (ireg < 0) {
return;
}
- struct yankreg *reg = &y_regs[CLIP_REGISTER];
-
- if (!name && p_unc) {
- // copy from the unnamed register
- copy_register(reg, &y_regs[0]);
- }
+ struct yankreg *reg = &y_regs[ireg];
list_T *lines = list_alloc();
@@ -5302,5 +5344,26 @@ static void set_clipboard(int name)
list_append_string(lines, reg->y_array[i], -1);
}
- (void)eval_call_provider("clipboard", "set", lines);
+ list_T *args = list_alloc();
+ list_append_list(args, lines);
+
+ char_u regtype;
+ switch (reg->y_type) {
+ case MLINE:
+ regtype = 'V';
+ list_append_string(lines, (char_u*)"", 0);
+ break;
+ case MCHAR:
+ regtype = 'v';
+ break;
+ case MBLOCK:
+ regtype = 'b';
+ break;
+ }
+ list_append_string(args, &regtype, 1);
+
+ char_u regname = name;
+ list_append_string(args, &regname, 1);
+
+ (void)eval_call_provider("clipboard", "set", args);
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 2882d7a511..fd0978f3a6 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -527,7 +527,7 @@ static struct vimoption
(char_u *)0L}
SCRIPTID_INIT},
{"clipboard", "cb", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
- (char_u *)NULL, PV_NONE,
+ (char_u *)&p_cb, PV_NONE,
{(char_u *)"", (char_u *)0L}
SCRIPTID_INIT},
{"cmdheight", "ch", P_NUM|P_VI_DEF|P_RALL,
@@ -1620,9 +1620,6 @@ static struct vimoption
{"undoreload", "ur", P_NUM|P_VI_DEF,
(char_u *)&p_ur, PV_NONE,
{ (char_u *)10000L, (char_u *)0L} SCRIPTID_INIT},
- {"unnamedclip", "ucp", P_BOOL|P_VI_DEF|P_VIM,
- (char_u *)&p_unc, PV_NONE,
- {(char_u *)FALSE, (char_u *)FALSE} SCRIPTID_INIT},
{"updatecount", "uc", P_NUM|P_VI_DEF,
(char_u *)&p_uc, PV_NONE,
{(char_u *)200L, (char_u *)0L} SCRIPTID_INIT},
@@ -4279,6 +4276,10 @@ did_set_string_option (
if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK)
errmsg = e_invarg;
}
+ else if (varp == &p_cb) {
+ if (opt_strings_flags(p_cb, p_cb_values, &cb_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ }
/* When 'spelllang' or 'spellfile' is set and there is a window for this
* buffer in which 'spell' is set load the wordlists. */
else if (varp == &(curbuf->b_s.b_p_spl) || varp == &(curbuf->b_s.b_p_spf)) {
@@ -4846,7 +4847,6 @@ char_u *check_stl_option(char_u *s)
return NULL;
}
-
/*
* Set curbuf->b_cap_prog to the regexp program for 'spellcapcheck'.
* Return error message when failed, NULL when OK.
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 89264f8982..39dfbe8b88 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -317,6 +317,13 @@ EXTERN char_u *p_enc; /* 'encoding' */
EXTERN int p_deco; /* 'delcombine' */
EXTERN char_u *p_ccv; /* 'charconvert' */
EXTERN char_u *p_cedit; /* 'cedit' */
+EXTERN char_u *p_cb; /* 'clipboard' */
+EXTERN unsigned cb_flags;
+#ifdef IN_OPTION_C
+static char *(p_cb_values[]) = {"unnamed", "unnamedplus", NULL};
+#endif
+# define CB_UNNAMED 0x001
+# define CB_UNNAMEDPLUS 0x002
EXTERN long p_cwh; /* 'cmdwinheight' */
EXTERN long p_ch; /* 'cmdheight' */
EXTERN int p_confirm; /* 'confirm' */
@@ -582,7 +589,6 @@ static char *(p_ttym_values[]) =
EXTERN char_u *p_udir; /* 'undodir' */
EXTERN long p_ul; /* 'undolevels' */
EXTERN long p_ur; /* 'undoreload' */
-EXTERN int p_unc; /* 'unnamedclip' */
EXTERN long p_uc; /* 'updatecount' */
EXTERN long p_ut; /* 'updatetime' */
EXTERN char_u *p_fcs; /* 'fillchar' */
diff --git a/test/functional/clipboard/autoload/provider/clipboard.vim b/test/functional/clipboard/autoload/provider/clipboard.vim
new file mode 100644
index 0000000000..6c05a19fc3
--- /dev/null
+++ b/test/functional/clipboard/autoload/provider/clipboard.vim
@@ -0,0 +1,16 @@
+let g:test_clip = { '+': [''], '*': [''], }
+
+let s:methods = {}
+
+function! s:methods.get(reg)
+ return g:test_clip[a:reg]
+endfunction
+
+function! s:methods.set(lines, regtype, reg)
+ let g:test_clip[a:reg] = a:lines
+endfunction
+
+
+function! provider#clipboard#Call(method, args)
+ return call(s:methods[a:method],a:args,s:methods)
+endfunction
diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua
new file mode 100644
index 0000000000..ccbb74e487
--- /dev/null
+++ b/test/functional/clipboard/clipboard_provider_spec.lua
@@ -0,0 +1,141 @@
+-- Test clipboard provider support
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect, eq, eval = helpers.execute, helpers.expect, helpers.eq, helpers.eval
+local nvim, run, stop, restart = helpers.nvim, helpers.run, helpers.stop, helpers.restart
+
+local function reset()
+ clear()
+ execute('let &rtp = "test/functional/clipboard,".&rtp')
+end
+
+local function basic_register_test()
+ insert("some words")
+
+ feed('^dwP')
+ expect('some words')
+
+ feed('veyP')
+ expect('some words words')
+
+ feed('^dwywe"-p')
+ expect('wordssome words')
+
+ feed('p')
+ expect('wordssome words words')
+
+ feed('yyp')
+ expect([[
+ wordssome words words
+ wordssome words words]])
+ feed('d-')
+
+ insert([[
+ some text, and some more
+ random text stuff]])
+ feed('ggtav+2ed$p')
+ expect([[
+ some text, stuff and some more
+ random text]])
+ reset()
+end
+
+describe('clipboard usage', function()
+ setup(reset)
+ it("works", function()
+ basic_register_test()
+
+ -- "* and unnamed should function as independent registers
+ insert("some words")
+ feed('^"*dwdw"*P')
+ expect('some ')
+ eq({'some '}, eval("g:test_clip['*']"))
+ reset()
+
+ -- "* and "+ should be independent when the provider supports it
+ insert([[
+ text:
+ first line
+ secound line
+ third line]])
+
+ feed('G"+dd"*dddd"+p"*pp')
+ expect([[
+ text:
+ third line
+ secound line
+ first line]])
+ -- linewise selection should be encoded as an extra newline
+ eq({'third line', ''}, eval("g:test_clip['+']"))
+ eq({'secound line', ''}, eval("g:test_clip['*']"))
+ reset()
+
+ -- handle null bytes
+ insert("some\x16000text\n\x16000very binary\x16000")
+ feed('"*y-+"*p')
+ eq({'some\ntext', '\nvery binary\n',''}, eval("g:test_clip['*']"))
+ expect("some\x00text\n\x00very binary\x00\nsome\x00text\n\x00very binary\x00")
+
+ -- test getreg/getregtype
+ eq('some\ntext\n\nvery binary\n\n', eval("getreg('*', 1)"))
+ eq("V", eval("getregtype('*')"))
+ reset()
+
+ -- blockwise paste
+ insert([[
+ much
+ text]])
+ feed('"*yy') -- force load of provider
+ execute("let g:test_clip['*'] = [['very','block'],'b']")
+ feed('gg"*P')
+ expect([[
+ very much
+ blocktext]])
+ eq("\x165", eval("getregtype('*')"))
+ reset()
+
+ -- test setreg
+ execute('call setreg("*", "setted\\ntext", "c")')
+ execute('call setreg("+", "explicitly\\nlines", "l")')
+ feed('"+P"*p')
+ expect([[
+ esetted
+ textxplicitly
+ lines
+ ]])
+ reset()
+
+ -- test let @+ (issue #1427)
+ execute("let @+ = 'some'")
+ execute("let @* = ' other stuff'")
+ eq({'some'}, eval("g:test_clip['+']"))
+ eq({' other stuff'}, eval("g:test_clip['*']"))
+ feed('"+p"*p')
+ expect('some other stuff')
+ execute("let @+ .= ' more'")
+ feed('dd"+p')
+ expect('some more')
+ reset()
+
+ -- the basic behavior of unnamed register should be the same
+ -- even when handled by clipboard provider
+ execute('set clipboard=unnamed')
+ basic_register_test()
+
+ -- with cb=unnamed, "* and unnamed will be the same register
+ execute('set clipboard=unnamed')
+ insert("some words")
+ feed('^"*dwdw"*P')
+ expect('words')
+ eq({'words'}, eval("g:test_clip['*']"))
+
+ execute("let g:test_clip['*'] = ['linewise stuff','']")
+ feed('p')
+ expect([[
+ words
+ linewise stuff]])
+ reset()
+
+ end)
+end)