mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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.
This commit is contained in:
parent
84b7a9ac34
commit
edb13791bd
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user