clipboard: avoid clipboard during :global. #2809

This is equivalent to patches 7.4.396, 7.4.445 and 7.4.598.

vim-patch:7.4.396

Problem:    When 'clipboard' is "unnamed", :g/pat/d is very slow.
(Praful)
Solution:   Only set the clipboard after the last delete. (Christian
Brabandt)

1f285eb49a

vim-patch:7.4.445

Problem:    Clipboard may be cleared on startup.
Solution:   Set clip_did_set_selection to -1 during startup. (Christian
	    Brabandt)

1a19d37d90

vim-patch:7.4.598

Problem:    ":tabdo windo echo 'hi'" causes "* register not to be
changed.
	    (Salman Halim)
Solution:   Change how clip_did_set_selection is used and add
	    clipboard_needs_update and global_change_count.  (Christian
	    Brabandt)

af6a579263

Co-Author: @bfredl
This commit is contained in:
Felipe Morales 2015-06-08 16:47:10 -03:00 committed by Justin M. Keyes
parent 7ee94d2dd7
commit acdac914d5
10 changed files with 106 additions and 17 deletions

View File

@ -4433,8 +4433,11 @@ void ex_global(exarg_T *eap)
smsg(_("Pattern found in every line: %s"), pat);
else
smsg(_("Pattern not found: %s"), pat);
} else
} else {
start_global_changes();
global_exe(cmd);
end_global_changes();
}
ml_clearmarked(); /* clear rest of the marks */
vim_regfree(regmatch.regprog);

View File

@ -41,6 +41,7 @@
#include "nvim/memory.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/ops.h"
#include "nvim/option.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
@ -1838,6 +1839,8 @@ void ex_listdo(exarg_T *eap)
* great speed improvement. */
save_ei = au_event_disable(",Syntax");
start_global_changes();
if (eap->cmdidx == CMD_windo
|| eap->cmdidx == CMD_tabdo
|| P_HID(curbuf)
@ -1988,6 +1991,7 @@ void ex_listdo(exarg_T *eap)
apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
curbuf->b_fname, TRUE, curbuf);
}
end_global_changes();
}
/*

View File

@ -9380,6 +9380,8 @@ static void ex_folddo(exarg_T *eap)
{
linenr_T lnum;
start_global_changes();
/* First set the marks for all lines closed/open. */
for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed))
@ -9388,6 +9390,8 @@ static void ex_folddo(exarg_T *eap)
/* Execute the command on the marked lines. */
global_exe(eap->arg);
ml_clearmarked(); /* clear rest of the marks */
end_global_changes();
}
static void ex_terminal(exarg_T *eap)

View File

@ -519,8 +519,6 @@ EXTERN int sys_menu INIT(= FALSE);
* ('lines' and 'rows') must not be changed. */
EXTERN int updating_screen INIT(= FALSE);
/*
* All windows are linked in a list. firstwin points to the first entry,
* lastwin to the last entry (can be the same as firstwin) and curwin to the

View File

@ -72,6 +72,12 @@ static yankreg_T y_regs[NUM_REGISTERS];
static yankreg_T *y_previous = NULL; /* ptr to last written yankreg */
static bool clipboard_didwarn_unnamed = false;
// for behavior between start_global_changes() and end_global_changes())
static bool clipboard_delay_update = false; // delay clipboard update
static int global_change_count = 0; // if set, inside global changes
static bool clipboard_needs_update = false; // the clipboard was updated
/*
* structure used by block_prep, op_delete and op_yank for blockwise operators
* also op_change, op_shift, op_insert, op_replace - AKelly
@ -5244,7 +5250,7 @@ void cursor_pos_info(void)
int get_default_register_name(void)
{
int name = NUL;
adjust_clipboard_name(&name, true);
adjust_clipboard_name(&name, true, false);
return name;
}
@ -5258,7 +5264,7 @@ int get_default_register_name(void)
///
/// @returns the yankreg that should be written into, or `NULL`
/// if the register isn't a clipboard or provider isn't available.
static yankreg_T *adjust_clipboard_name(int *name, bool quiet)
static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
{
if (*name == '*' || *name == '+') {
if(!eval_has_provider("clipboard")) {
@ -5276,6 +5282,14 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet)
}
return NULL;
}
if (writing && clipboard_delay_update) {
clipboard_needs_update = true;
return NULL;
} else if (!writing && clipboard_needs_update) {
// use the internal value
return NULL;
}
yankreg_T *target;
if (cb_flags & CB_UNNAMEDPLUS) {
*name = cb_flags & CB_UNNAMED ? '"': '+';
@ -5295,7 +5309,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
// show message on error
bool errmsg = true;
yankreg_T *reg = adjust_clipboard_name(&name, quiet);
yankreg_T *reg = adjust_clipboard_name(&name, quiet, false);
if (reg == NULL) {
return false;
}
@ -5406,7 +5420,7 @@ err:
static void set_clipboard(int name, yankreg_T *reg)
{
if(!adjust_clipboard_name(&name, false)) {
if (!adjust_clipboard_name(&name, false, true)) {
return;
}
@ -5440,3 +5454,27 @@ static void set_clipboard(int name, yankreg_T *reg)
(void)eval_call_provider("clipboard", "set", args);
}
/// Avoid clipboard (slow) during batch operations (:global).
void start_global_changes(void)
{
if (++global_change_count > 1) {
return;
}
clipboard_delay_update = true;
clipboard_needs_update = false;
}
/// Update the clipboard after :global changes finished.
void end_global_changes(void)
{
if (--global_change_count > 0) {
// recursive
return;
}
clipboard_delay_update = false;
if (clipboard_needs_update) {
set_clipboard(NUL, y_previous);
clipboard_needs_update = false;
}
}

View File

@ -2583,11 +2583,11 @@ did_set_string_option (
else if (varp == &p_ead) {
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)
} else if (varp == &p_cb) { // 'clipboard'
if (opt_strings_flags(p_cb, p_cb_values, &cb_flags, true) != OK) {
errmsg = e_invarg;
} else if (varp == &(curwin->w_s->b_p_spl)
}
} else if (varp == &(curwin->w_s->b_p_spl) // 'spell'
|| varp == &(curwin->w_s->b_p_spf)) {
// When 'spelllang' or 'spellfile' is set and there is a window for this
// buffer in which 'spell' is set load the wordlists.

View File

@ -1,7 +1,6 @@
Test for various eval features. vim: set ft=vim :
Note: system clipboard support is not tested. I do not think anybody will thank
me for messing with clipboard.
Note: system clipboard is saved, changed and restored.
STARTTEST
:so small.vim
@ -122,7 +121,19 @@ call SetReg('/', ['abc/'])
call SetReg('/', ["abc/\n"])
call SetReg('=', ['"abc/"'])
call SetReg('=', ["\"abc/\n\""])
$put ='{{{1 System clipboard'
" Save and restore system clipboard.
" If no connection to X-Server is possible, test should succeed.
:let _clipreg = ['+', getreg('+'), getregtype('+')]
:let _clipopt = &cb
:let &cb='unnamedplus'
:1y
:AR +
:tabdo :windo :echo "hi"
:3y
:AR +
:let &cb=_clipopt
:call call('setreg', _clipreg)
$put ='{{{1 Errors'
call ErrExe('call setreg()')
call ErrExe('call setreg(1)')

Binary file not shown.

View File

@ -323,7 +323,7 @@ static int included_patches[] = {
601,
600,
599,
// 598,
598,
597,
// 596 NA
595,
@ -476,7 +476,7 @@ static int included_patches[] = {
// 448 NA
447,
446,
// 445,
445,
444,
// 443 NA
442,
@ -525,7 +525,7 @@ static int included_patches[] = {
// 399 NA
// 398 NA
397,
// 396,
396,
395,
// 394 NA
// 393 NA

View File

@ -285,6 +285,22 @@ describe('clipboard usage', function()
the text]])
end)
it('is updated on global changes', function()
insert([[
text
match
match
text
]])
execute('g/match/d')
eq('match\n', eval('getreg("*")'))
feed('u')
eval('setreg("*", "---")')
execute('g/test/')
feed('<esc>')
eq('---', eval('getreg("*")'))
end)
end)
describe('with clipboard=unnamedplus', function()
@ -329,6 +345,21 @@ describe('clipboard usage', function()
really unnamed
the plus]])
end)
it('is updated on global changes', function()
insert([[
text
match
match
text
]])
execute('g/match/d')
eq('match\n', eval('getreg("+")'))
feed('u')
eval('setreg("+", "---")')
execute('g/test/')
feed('<esc>')
eq('---', eval('getreg("+")'))
end)
end)
it('supports :put', function()