diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2015-04-11 17:49:47 +0200 |
---|---|---|
committer | Björn Linse <bjorn.linse@gmail.com> | 2015-04-17 11:34:06 +0200 |
commit | edb13791bd6eda43ab3816c7697530b378680e61 (patch) | |
tree | 5ec736cb0e7b1299a47ed9d51d45825538312d6a | |
parent | 84b7a9ac34244a2d3f2356dbd9cebf1961281d42 (diff) | |
download | rneovim-edb13791bd6eda43ab3816c7697530b378680e61.tar.gz rneovim-edb13791bd6eda43ab3816c7697530b378680e61.tar.bz2 rneovim-edb13791bd6eda43ab3816c7697530b378680e61.zip |
clipboard: simplify handling of of put in visual mode.
When clipboard=unnamed and put over visual selection, reduces number of
provider calls from 6 to 2. Also add test.
-rw-r--r-- | src/nvim/edit.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 2 | ||||
-rw-r--r-- | src/nvim/normal.c | 33 | ||||
-rw-r--r-- | src/nvim/ops.c | 77 | ||||
-rw-r--r-- | test/functional/clipboard/clipboard_provider_spec.lua | 14 |
5 files changed, 57 insertions, 71 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 26665aa84c..790967469b 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -6762,7 +6762,7 @@ static void ins_reg(void) AppendCharToRedobuff(literally); AppendCharToRedobuff(regname); - do_put(regname, BACKWARD, 1L, + do_put(regname, NULL, BACKWARD, 1L, (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND); } else if (insert_reg(regname, literally) == FAIL) { vim_beep(); diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 33b1573259..dd844449b3 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6515,7 +6515,7 @@ static void ex_put(exarg_T *eap) eap->forceit = TRUE; } curwin->w_cursor.lnum = eap->line2; - do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L, + do_put(eap->regname, NULL, eap->forceit ? BACKWARD : FORWARD, 1L, PUT_LINE|PUT_CURSLINE); } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 4e0af3e0b1..aa617a20fa 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1995,7 +1995,7 @@ do_mouse ( if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) insert_reg(regname, true); else { - do_put(regname, BACKWARD, 1L, fixindent | PUT_CURSEND); + do_put(regname, NULL, BACKWARD, 1L, fixindent | PUT_CURSEND); /* Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r */ AppendCharToRedobuff(Ctrl_R); @@ -2280,7 +2280,7 @@ do_mouse ( */ if (restart_edit != 0) where_paste_started = curwin->w_cursor; - do_put(regname, dir, count, fixindent | PUT_CURSEND); + do_put(regname, NULL, dir, count, fixindent | PUT_CURSEND); } /* * Ctrl-Mouse click or double click in a quickfix window jumps to the @@ -5085,7 +5085,7 @@ static void nv_brackets(cmdarg_T *cap) curwin->w_cursor = (dir == BACKWARD ? start : end); } prep_redo_cmd(cap); - do_put(regname, dir, cap->count1, PUT_FIXINDENT); + do_put(regname, NULL, dir, cap->count1, PUT_FIXINDENT); if (was_visual) { VIsual = start; curwin->w_cursor = end; @@ -7221,7 +7221,7 @@ static void nv_join(cmdarg_T *cap) static void nv_put(cmdarg_T *cap) { int regname = 0; - void *reg1 = NULL, *reg2 = NULL; + yankreg_T *savereg = NULL; bool empty = false; bool was_visual = false; int dir; @@ -7252,11 +7252,9 @@ static void nv_put(cmdarg_T *cap) was_visual = true; regname = cap->oap->regname; if (regname == 0 || regname == '"' - || VIM_ISDIGIT(regname) || regname == '-' - ) { - /* The delete is going to overwrite the register we want to - * put, save it first. */ - reg1 = get_register(regname, true); + || VIM_ISDIGIT(regname) || regname == '-') { + // The delete might overwrite the register we want to put, save it first + savereg = copy_register(regname); } /* Now delete the selected text. */ @@ -7270,13 +7268,6 @@ static void nv_put(cmdarg_T *cap) /* delete PUT_LINE_BACKWARD; */ cap->oap->regname = regname; - if (reg1 != NULL) { - /* Delete probably changed the register we want to put, save - * it first. Then put back what was there before the delete. */ - reg2 = get_register(regname, false); - put_register(regname, reg1); - } - /* When deleted a linewise Visual area, put the register as * lines to avoid it joined with the next line. When deletion was * characterwise, split a line when putting lines. */ @@ -7297,11 +7288,13 @@ static void nv_put(cmdarg_T *cap) /* May have been reset in do_put(). */ VIsual_active = true; } - do_put(cap->oap->regname, dir, cap->count1, flags); + do_put(cap->oap->regname, savereg, dir, cap->count1, flags); - /* If a register was saved, put it back now. */ - if (reg2 != NULL) - put_register(regname, reg2); + // If a register was saved, free it + if (savereg != NULL) { + free_register(savereg); + xfree(savereg); + } /* What to reselect with "gv"? Selecting the just put text seems to * be the most useful, since the original text was removed. */ diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 637f353115..8446a943a0 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -800,46 +800,25 @@ static bool is_append_register(int regname) return ASCII_ISUPPER(regname); } -/* - * Obtain the contents of a "normal" register. The register is made empty. - * The returned pointer has allocated memory, use put_register() later. - */ -void * -get_register ( - int name, - int copy /* make a copy, if FALSE make register empty. */ -) FUNC_ATTR_NONNULL_RET +/// Returns a copy of contents in register `name` +/// for use in do_put. Should be freed by caller. +yankreg_T *copy_register(int name) + FUNC_ATTR_MALLOC + FUNC_ATTR_NONNULL_RET { yankreg_T *reg = get_yank_register(name, YREG_PASTE); - yankreg_T *tmpreg = xmalloc(sizeof(yankreg_T)); - *tmpreg = *reg; - if (copy) { - if (tmpreg->y_size == 0) { - tmpreg->y_array = NULL; - } else { - tmpreg->y_array = xmalloc(tmpreg->y_size * sizeof(char_u *)); - for (linenr_T i = 0; i < tmpreg->y_size; i++) { - tmpreg->y_array[i] = vim_strsave(reg->y_array[i]); - } - } + yankreg_T *copy = xmalloc(sizeof(yankreg_T)); + *copy = *reg; + if (copy->y_size == 0) { + copy->y_array = NULL; } else { - reg->y_array = NULL; + copy->y_array = xcalloc(copy->y_size, sizeof(char_u *)); + for (linenr_T i = 0; i < copy->y_size; i++) { + copy->y_array[i] = vim_strsave(reg->y_array[i]); + } } - - return (void *)tmpreg; -} - -/* - * Put "tmpreg" into register "name". Free any previous contents and "tmpreg". - */ -void put_register(int name, void *tmpreg) -{ - yankreg_T *reg = get_yank_register(name, YREG_PUT); - free_register(reg); - *reg = *(yankreg_T *)tmpreg; - xfree(tmpreg); - set_clipboard(name, reg); + return copy; } /* @@ -2299,11 +2278,12 @@ void clear_registers(void) #endif -/* - * Free contents of yankreg reg. - * Called for normal freeing and in case of error. - */ -static void free_register(yankreg_T *reg) + + /// Free contents of yankreg `reg`. + /// Called for normal freeing and in case of error. + /// `reg` must not be NULL (but `reg->y_array` might be) +void free_register(yankreg_T *reg) + FUNC_ATTR_NONNULL_ALL { if (reg->y_array != NULL) { long i; @@ -2562,14 +2542,8 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, long y_idx) * "flags": PUT_FIXINDENT make indent look nice * PUT_CURSEND leave cursor after end of new text * PUT_LINE force linewise put (":put") - */ -void -do_put ( - int regname, - int dir, /* BACKWARD for 'P', FORWARD for 'p' */ - long count, - int flags -) + dir: BACKWARD for 'P', FORWARD for 'p' */ +void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) { char_u *ptr; char_u *newp, *oldp; @@ -2672,7 +2646,12 @@ do_put ( y_array = &insert_string; } } else { - yankreg_T *reg = get_yank_register(regname, YREG_PASTE); + // in case of replacing visually selected text + // the yankreg might already have been saved to avoid + // just restoring the deleted text. + if (reg == NULL) { + reg = get_yank_register(regname, YREG_PASTE); + } y_type = reg->y_type; y_width = reg->y_width; diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua index c5d8f57008..52fdfaa8f4 100644 --- a/test/functional/clipboard/clipboard_provider_spec.lua +++ b/test/functional/clipboard/clipboard_provider_spec.lua @@ -73,6 +73,12 @@ local function basic_register_test(noblock) stuf, stuff and some more me tsome textsome some text, stuff and some more]]) end + + -- pasting in visual does unnamed delete of visual selection + feed('ggdG') + insert("one and two and three") + feed('"ayiwbbviw"ap^viwp$viw"-p') + expect("two and three and one") end describe('the unnamed register', function() @@ -241,6 +247,14 @@ describe('clipboard usage', function() eq('\02210', eval('getregtype()')) end) + it('yanks visual selection when pasting', function() + insert("indeed visual") + execute("let g:test_clip['*'] = [['clipboard'], 'c']") + feed("viwp") + eq({{'visual'}, 'v'}, eval("g:test_clip['*']")) + expect("indeed clipboard") + end) + end) it('supports :put', function() |