aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/ex_cmds.c5
-rw-r--r--src/nvim/ex_cmds2.c4
-rw-r--r--src/nvim/ex_docmd.c4
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/ops.c46
-rw-r--r--src/nvim/option.c8
-rw-r--r--src/nvim/testdir/test_eval.in17
-rw-r--r--src/nvim/testdir/test_eval.okbin10578 -> 11106 bytes
-rw-r--r--src/nvim/version.c6
-rw-r--r--test/functional/clipboard/clipboard_provider_spec.lua31
10 files changed, 106 insertions, 17 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 802a378b07..1e150444d0 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -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);
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index efa18aa681..f172ea54c2 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -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();
}
/*
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 3c57537397..d69d106dc6 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -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)
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 5126195841..e5a993aa5a 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -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
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 766b5720d9..3163132b8a 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -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;
+ }
+}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 38682f3142..ee50567728 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -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.
diff --git a/src/nvim/testdir/test_eval.in b/src/nvim/testdir/test_eval.in
index 95a59ee42a..328ee2e127 100644
--- a/src/nvim/testdir/test_eval.in
+++ b/src/nvim/testdir/test_eval.in
@@ -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)')
diff --git a/src/nvim/testdir/test_eval.ok b/src/nvim/testdir/test_eval.ok
index 061e0cfd2f..2cdb8f5da8 100644
--- a/src/nvim/testdir/test_eval.ok
+++ b/src/nvim/testdir/test_eval.ok
Binary files differ
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 4bdc0ba290..9a8a50ea58 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -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
diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua
index 0550d22fa6..98b8d2dd45 100644
--- a/test/functional/clipboard/clipboard_provider_spec.lua
+++ b/test/functional/clipboard/clipboard_provider_spec.lua
@@ -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()