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); smsg(_("Pattern found in every line: %s"), pat);
else else
smsg(_("Pattern not found: %s"), pat); smsg(_("Pattern not found: %s"), pat);
} else } else {
start_global_changes();
global_exe(cmd); global_exe(cmd);
end_global_changes();
}
ml_clearmarked(); /* clear rest of the marks */ ml_clearmarked(); /* clear rest of the marks */
vim_regfree(regmatch.regprog); vim_regfree(regmatch.regprog);

View File

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

View File

@ -9380,6 +9380,8 @@ static void ex_folddo(exarg_T *eap)
{ {
linenr_T lnum; linenr_T lnum;
start_global_changes();
/* First set the marks for all lines closed/open. */ /* First set the marks for all lines closed/open. */
for (lnum = eap->line1; lnum <= eap->line2; ++lnum) for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed)) 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. */ /* Execute the command on the marked lines. */
global_exe(eap->arg); global_exe(eap->arg);
ml_clearmarked(); /* clear rest of the marks */ ml_clearmarked(); /* clear rest of the marks */
end_global_changes();
} }
static void ex_terminal(exarg_T *eap) 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. */ * ('lines' and 'rows') must not be changed. */
EXTERN int updating_screen INIT(= FALSE); EXTERN int updating_screen INIT(= FALSE);
/* /*
* All windows are linked in a list. firstwin points to the first entry, * 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 * 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 yankreg_T *y_previous = NULL; /* ptr to last written yankreg */
static bool clipboard_didwarn_unnamed = false; 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 * structure used by block_prep, op_delete and op_yank for blockwise operators
* also op_change, op_shift, op_insert, op_replace - AKelly * 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 get_default_register_name(void)
{ {
int name = NUL; int name = NUL;
adjust_clipboard_name(&name, true); adjust_clipboard_name(&name, true, false);
return name; return name;
} }
@ -5258,7 +5264,7 @@ int get_default_register_name(void)
/// ///
/// @returns the yankreg that should be written into, or `NULL` /// @returns the yankreg that should be written into, or `NULL`
/// if the register isn't a clipboard or provider isn't available. /// 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 (*name == '*' || *name == '+') {
if(!eval_has_provider("clipboard")) { if(!eval_has_provider("clipboard")) {
@ -5276,6 +5282,14 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet)
} }
return NULL; 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; yankreg_T *target;
if (cb_flags & CB_UNNAMEDPLUS) { if (cb_flags & CB_UNNAMEDPLUS) {
*name = cb_flags & CB_UNNAMED ? '"': '+'; *name = cb_flags & CB_UNNAMED ? '"': '+';
@ -5295,7 +5309,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
// show message on error // show message on error
bool errmsg = true; bool errmsg = true;
yankreg_T *reg = adjust_clipboard_name(&name, quiet); yankreg_T *reg = adjust_clipboard_name(&name, quiet, false);
if (reg == NULL) { if (reg == NULL) {
return false; return false;
} }
@ -5406,7 +5420,7 @@ err:
static void set_clipboard(int name, yankreg_T *reg) static void set_clipboard(int name, yankreg_T *reg)
{ {
if(!adjust_clipboard_name(&name, false)) { if (!adjust_clipboard_name(&name, false, true)) {
return; return;
} }
@ -5440,3 +5454,27 @@ static void set_clipboard(int name, yankreg_T *reg)
(void)eval_call_provider("clipboard", "set", args); (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) { else if (varp == &p_ead) {
if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK) if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK)
errmsg = e_invarg; errmsg = e_invarg;
} } else if (varp == &p_cb) { // 'clipboard'
else if (varp == &p_cb) { if (opt_strings_flags(p_cb, p_cb_values, &cb_flags, true) != OK) {
if (opt_strings_flags(p_cb, p_cb_values, &cb_flags, TRUE) != OK)
errmsg = e_invarg; 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)) { || varp == &(curwin->w_s->b_p_spf)) {
// When 'spelllang' or 'spellfile' is set and there is a window for this // When 'spelllang' or 'spellfile' is set and there is a window for this
// buffer in which 'spell' is set load the wordlists. // buffer in which 'spell' is set load the wordlists.

View File

@ -1,7 +1,6 @@
Test for various eval features. vim: set ft=vim : Test for various eval features. vim: set ft=vim :
Note: system clipboard support is not tested. I do not think anybody will thank Note: system clipboard is saved, changed and restored.
me for messing with clipboard.
STARTTEST STARTTEST
:so small.vim :so small.vim
@ -122,7 +121,19 @@ call SetReg('/', ['abc/'])
call SetReg('/', ["abc/\n"]) call SetReg('/', ["abc/\n"])
call SetReg('=', ['"abc/"']) call SetReg('=', ['"abc/"'])
call SetReg('=', ["\"abc/\n\""]) 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' $put ='{{{1 Errors'
call ErrExe('call setreg()') call ErrExe('call setreg()')
call ErrExe('call setreg(1)') call ErrExe('call setreg(1)')

Binary file not shown.

View File

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

View File

@ -285,6 +285,22 @@ describe('clipboard usage', function()
the text]]) the text]])
end) 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) end)
describe('with clipboard=unnamedplus', function() describe('with clipboard=unnamedplus', function()
@ -329,6 +345,21 @@ describe('clipboard usage', function()
really unnamed really unnamed
the plus]]) the plus]])
end) 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) end)
it('supports :put', function() it('supports :put', function()