aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2015-04-11 17:49:47 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2015-04-17 11:34:06 +0200
commitedb13791bd6eda43ab3816c7697530b378680e61 (patch)
tree5ec736cb0e7b1299a47ed9d51d45825538312d6a
parent84b7a9ac34244a2d3f2356dbd9cebf1961281d42 (diff)
downloadrneovim-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.c2
-rw-r--r--src/nvim/ex_docmd.c2
-rw-r--r--src/nvim/normal.c33
-rw-r--r--src/nvim/ops.c77
-rw-r--r--test/functional/clipboard/clipboard_provider_spec.lua14
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()