From c1854d2433a10122ae2933e2dcbc970b53e9438b Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 22 Nov 2014 16:01:14 +0100 Subject: clipboard: support separate '+' and '*' clipboards --- runtime/autoload/provider/clipboard.vim | 34 +++++++++++++++++++-------------- src/nvim/eval.c | 14 ++++++++++++++ src/nvim/ops.c | 13 ++++++++++++- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim index 46c05a882c..04a3068360 100644 --- a/runtime/autoload/provider/clipboard.vim +++ b/runtime/autoload/provider/clipboard.vim @@ -1,8 +1,8 @@ " 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) @@ -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, 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/src/nvim/eval.c b/src/nvim/eval.c index be69bdbe61..c2156c5d58 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5118,6 +5118,20 @@ void list_append_tv(list_T *l, typval_T *tv) list_append(l, li); } +/* + * 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(). */ diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 6bf3f6036f..8dfb986714 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5244,7 +5244,11 @@ static void get_clipboard(int name) struct yankreg *reg = &y_regs[CLIP_REGISTER]; free_register(reg); + list_T *args = list_alloc(); + char_u regname = (char_u)name; + list_append_string(args, ®name, 1); + typval_T result = eval_call_provider("clipboard", "get", args); if (result.v_type != VAR_LIST) { @@ -5294,6 +5298,7 @@ static void set_clipboard(int name) if (!name && p_unc) { // copy from the unnamed register copy_register(reg, &y_regs[0]); + name = '+'; } list_T *lines = list_alloc(); @@ -5302,5 +5307,11 @@ 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 regname = (char_u)name; + list_append_string(args, ®name, 1); + + (void)eval_call_provider("clipboard", "set", args); } -- cgit From 63efb9b1f14420f5402e04c282b79d4515c2384e Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 22 Nov 2014 19:16:04 +0100 Subject: clipboard: handle linewise/charwise selections correctly --- runtime/autoload/provider/clipboard.vim | 4 +-- src/nvim/ops.c | 64 ++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim index 04a3068360..458ef6257d 100644 --- a/runtime/autoload/provider/clipboard.vim +++ b/runtime/autoload/provider/clipboard.vim @@ -5,7 +5,7 @@ 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 '' @@ -39,7 +39,7 @@ function! s:clipboard.get(reg) return s:try_cmd(s:paste[a:reg]) endfunction -function! s:clipboard.set(lines, reg) +function! s:clipboard.set(lines, regtype, reg) call s:try_cmd(s:copy[a:reg], a:lines) endfunction diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 8dfb986714..8a174c2a9e 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5255,7 +5255,35 @@ static void get_clipboard(int name) 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; @@ -5267,6 +5295,25 @@ static void get_clipboard(int name) reg->y_array[i++] = (uint8_t *)xstrdup((char *)li->li_tv.vval.v_string); } + 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; + } + if (!name && p_unc) { // copy to the unnamed register copy_register(&y_regs[0], reg); @@ -5310,6 +5357,21 @@ static void set_clipboard(int name) 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, ®type, 1); + char_u regname = (char_u)name; list_append_string(args, ®name, 1); -- cgit From 61aaf815dbf42c11947748656f377f578c4ed4c7 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 16 Sep 2014 11:32:02 +0200 Subject: clipboard: clean up unnamedclip logic --- src/nvim/normal.c | 12 +-------- src/nvim/ops.c | 74 +++++++++++++++++-------------------------------------- 2 files changed, 23 insertions(+), 63 deletions(-) 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(®name); - 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(®name); 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(®name); 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 8a174c2a9e..b19140813f 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -751,7 +751,7 @@ void get_yank_register(int regname, int writing) int i; y_append = FALSE; - if ((regname == 0 || regname == '"') && !writing && y_previous != NULL) { + if ((regname == 0 || regname == '"') && !p_unc && !writing && y_previous != NULL) { y_current = y_previous; return; } @@ -1302,18 +1302,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 +1316,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 +1329,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 +1378,9 @@ int op_delete(oparg_T *oap) * register. For the black hole register '_' don't yank anything. */ if (oap->regname != '_') { - if (oap->regname != 0) { + if (oap->regname != 0 || p_unc) { /* check for read-only register */ - if (!valid_yank_reg(oap->regname, TRUE)) { + if (!( valid_yank_reg(oap->regname, TRUE) || (p_unc && oap->regname == 0) )) { beep_flush(); return OK; } @@ -1407,10 +1392,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 +1407,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 +2604,6 @@ do_put ( int allocated = FALSE; long cnt; - adjust_clipboard_register(®name); get_clipboard(regname); if (flags & PUT_FIXINDENT) @@ -3215,7 +3195,6 @@ void ex_display(exarg_T *eap) ) continue; /* did not ask for this register */ - adjust_clipboard_register(&name); get_clipboard(name); if (i == -1) { @@ -5225,28 +5204,30 @@ 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]); +static int check_clipboard_name(int *name) { + if (*name == '*' || *name == '+') { + return CLIP_REGISTER; + } else if (p_unc && *name == NUL && eval_has_provider("clipboard")) { + *name = '+'; + return 0; //unnamed register + } else { + return -1; } } + static void get_clipboard(int name) { - if (!(name == '*' || name == '+' - || (p_unc && !name && eval_has_provider("clipboard")))) { + int ireg = check_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 = (char_u)name; + char_u regname = name; list_append_string(args, ®name, 1); typval_T result = eval_call_provider("clipboard", "get", args); @@ -5314,11 +5295,6 @@ static void get_clipboard(int name) reg->y_width = maxlen-1; } - if (!name && p_unc) { - // copy to the unnamed register - copy_register(&y_regs[0], reg); - } - return; err: @@ -5335,18 +5311,12 @@ err: static void set_clipboard(int name) { - if (!(name == '*' || name == '+' - || (p_unc && !name && eval_has_provider("clipboard")))) { + int ireg = check_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]); - name = '+'; - } + struct yankreg *reg = &y_regs[ireg]; list_T *lines = list_alloc(); @@ -5372,7 +5342,7 @@ static void set_clipboard(int name) } list_append_string(args, ®type, 1); - char_u regname = (char_u)name; + char_u regname = name; list_append_string(args, ®name, 1); (void)eval_call_provider("clipboard", "set", args); -- cgit From 5476250ba3208c92cc9865becf540fdd335c2927 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 30 Sep 2014 18:04:22 +0200 Subject: options: change "unnamedclip" back to "clipboard=unnamed/unnamedplus" This allows to configure which of '*' and '+' should be used for the unnamed clipboard, and is consistent with vim. --- src/nvim/ops.c | 26 +++++++++++++++++--------- src/nvim/option.c | 10 +++++----- src/nvim/option_defs.h | 8 +++++++- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/nvim/ops.c b/src/nvim/ops.c index b19140813f..e8cad24b92 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. */ @@ -751,7 +752,8 @@ void get_yank_register(int regname, int writing) int i; y_append = FALSE; - if ((regname == 0 || regname == '"') && !p_unc && !writing && y_previous != NULL) { + int unnamedclip = cb_flags & CB_UNNAMEDMASK; + if ((regname == 0 || regname == '"') && !unnamedclip && !writing && y_previous != NULL) { y_current = y_previous; return; } @@ -1378,9 +1380,10 @@ int op_delete(oparg_T *oap) * register. For the black hole register '_' don't yank anything. */ if (oap->regname != '_') { - if (oap->regname != 0 || p_unc) { + 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) || (p_unc && oap->regname == 0) )) { + if (!( valid_yank_reg(oap->regname, TRUE) || unnamedclip )) { beep_flush(); return OK; } @@ -5204,18 +5207,23 @@ static void free_register(struct yankreg *reg) y_current = curr; } +// return target register static int check_clipboard_name(int *name) { if (*name == '*' || *name == '+') { return CLIP_REGISTER; - } else if (p_unc && *name == NUL && eval_has_provider("clipboard")) { - *name = '+'; - return 0; //unnamed register - } else { - return -1; + } else if (*name == NUL && eval_has_provider("clipboard")) { + if (cb_flags & CB_UNNAMEDPLUS) { + *name = '+'; + return 0; //unnamed + } else if (cb_flags & CB_UNNAMED) { + *name = '*'; + return 0; //unnamed + } } + // don't do anything for other register names + return -1; } - static void get_clipboard(int name) { int ireg = check_clipboard_name(&name); 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' */ -- cgit From cccc46acd7aa1a9b89f7252a074705a1f7039c61 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 29 Nov 2014 13:58:45 +0100 Subject: clipboard: better error messages when provider not available --- src/nvim/ops.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/nvim/ops.c b/src/nvim/ops.c index e8cad24b92..1513eb2cbc 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -75,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 @@ -5208,17 +5209,27 @@ static void free_register(struct yankreg *reg) } // return target register -static int check_clipboard_name(int *name) { +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 && eval_has_provider("clipboard")) { + } 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 = '+'; - return 0; //unnamed - } else if (cb_flags & CB_UNNAMED) { + } else { *name = '*'; - return 0; //unnamed } + return 0; //unnamed } // don't do anything for other register names return -1; @@ -5226,7 +5237,7 @@ static int check_clipboard_name(int *name) { static void get_clipboard(int name) { - int ireg = check_clipboard_name(&name); + int ireg = adjust_clipboard_name(&name); if (ireg < 0) { return; } @@ -5314,12 +5325,12 @@ 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) { - int ireg = check_clipboard_name(&name); + int ireg = adjust_clipboard_name(&name); if (ireg < 0) { return; } -- cgit From d9639d3a9b512d2ef73018074fcf380d37f722a1 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 26 Sep 2014 16:08:16 +0200 Subject: clipboard: add functional test --- .../clipboard/autoload/provider/clipboard.vim | 16 +++ .../clipboard/clipboard_provider_spec.lua | 129 +++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 test/functional/clipboard/autoload/provider/clipboard.vim create mode 100644 test/functional/clipboard/clipboard_provider_spec.lua 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..0f11615bdc --- /dev/null +++ b/test/functional/clipboard/clipboard_provider_spec.lua @@ -0,0 +1,129 @@ +-- 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() + + -- 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) -- cgit From 6ddbe6d9be885c5d1b7c54b104f0322911bd9fef Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 7 Nov 2014 17:31:42 +0100 Subject: clipboard: fix `let @+ = ...` and add test --- src/nvim/ops.c | 1 + test/functional/clipboard/clipboard_provider_spec.lua | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 1513eb2cbc..c20a017088 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -4825,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 */ diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua index 0f11615bdc..ccbb74e487 100644 --- a/test/functional/clipboard/clipboard_provider_spec.lua +++ b/test/functional/clipboard/clipboard_provider_spec.lua @@ -106,6 +106,18 @@ describe('clipboard usage', function() ]]) 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') -- cgit From 9a0ec687d93ece7fea7383bcc7971cf9bc4735d3 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 29 Nov 2014 14:36:34 +0100 Subject: eval_has_provider: search autoload scripts same order as call_func --- src/nvim/eval.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c2156c5d58..b4d1677520 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -19829,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"); \ } \ } -- cgit From df2eeaeb375a7a7f7cb92586b03d10260d485c90 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Mon, 8 Dec 2014 23:42:57 +0100 Subject: docs: remove unnamedclip option --- runtime/doc/options.txt | 7 ------- 1 file changed, 7 deletions(-) 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 -- cgit