mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
clipboard: remove start_batch_changes() in redir_write()
start_batch_changes() doesn't avoid invoking the clipboard once-per-line, because the loop is actually in ex_echo(), which calls redir_write() for each message. But we've already entered start_batch_changes() by then, so that was never the problem. redir_write at /home/vagrant/old.neovim/build/../src/nvim/message.c:2523 msg_puts_attr_len at /home/vagrant/old.neovim/build/../src/nvim/message.c:1600 msg_outtrans_len_attr at /home/vagrant/old.neovim/build/../src/nvim/message.c:1221 ex_echo at /home/vagrant/old.neovim/build/../src/nvim/eval.c:19433 do_one_cmd at /home/vagrant/old.neovim/build/../src/nvim/ex_docmd.c:2242 Trying to defer _explicit_ clipboard updates is difficult. :redir @+ | silent echo system('cat foo') | redir END is essentially equivalent to: for l in readfile('foo') let @+ .= l endfor We cannot make judgements about when to ignore a script's bad decisions. start_batch_changes() only works around the case of clipboard=unnamed, i.e. _implicit_ clipboard updates (`:g/foo/d`). Not explicit assignment.
This commit is contained in:
parent
9882e25dc4
commit
cc7e344f83
@ -2519,7 +2519,6 @@ static void redir_write(const char *const str, const ptrdiff_t maxlen)
|
|||||||
if (redirecting()) {
|
if (redirecting()) {
|
||||||
/* If the string doesn't start with CR or NL, go to msg_col */
|
/* If the string doesn't start with CR or NL, go to msg_col */
|
||||||
if (*s != '\n' && *s != '\r') {
|
if (*s != '\n' && *s != '\r') {
|
||||||
start_batch_changes();
|
|
||||||
while (cur_col < msg_col) {
|
while (cur_col < msg_col) {
|
||||||
if (capture_ga) {
|
if (capture_ga) {
|
||||||
ga_concat_len(capture_ga, " ", 1);
|
ga_concat_len(capture_ga, " ", 1);
|
||||||
@ -2536,7 +2535,6 @@ static void redir_write(const char *const str, const ptrdiff_t maxlen)
|
|||||||
}
|
}
|
||||||
cur_col++;
|
cur_col++;
|
||||||
}
|
}
|
||||||
end_batch_changes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen;
|
size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen;
|
||||||
|
@ -5558,7 +5558,7 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
|
|||||||
msg((char_u *)MSG_NO_CLIP);
|
msg((char_u *)MSG_NO_CLIP);
|
||||||
clipboard_didwarn_unnamed = true;
|
clipboard_didwarn_unnamed = true;
|
||||||
}
|
}
|
||||||
// ... else, be silent (avoid a flood of messages).
|
// ... else, be silent (don't flood during :while, :redir, etc.).
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5567,10 +5567,12 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
|
|||||||
goto end;
|
goto end;
|
||||||
} else { // unnamed register: "implicit" clipboard
|
} else { // unnamed register: "implicit" clipboard
|
||||||
if (writing && clipboard_delay_update) {
|
if (writing && clipboard_delay_update) {
|
||||||
|
// For "set" (copy), defer the clipboard call.
|
||||||
clipboard_needs_update = true;
|
clipboard_needs_update = true;
|
||||||
goto end;
|
goto end;
|
||||||
} else if (!writing && clipboard_needs_update) {
|
} else if (!writing && clipboard_needs_update) {
|
||||||
goto end; // use the internal value
|
// For "get" (paste), use the internal value.
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb_flags & CB_UNNAMEDPLUS) {
|
if (cb_flags & CB_UNNAMEDPLUS) {
|
||||||
@ -5772,6 +5774,7 @@ void end_batch_changes(void)
|
|||||||
}
|
}
|
||||||
clipboard_delay_update = false;
|
clipboard_delay_update = false;
|
||||||
if (clipboard_needs_update) {
|
if (clipboard_needs_update) {
|
||||||
|
// unnamed ("implicit" clipboard)
|
||||||
set_clipboard(NUL, y_previous);
|
set_clipboard(NUL, y_previous);
|
||||||
clipboard_needs_update = false;
|
clipboard_needs_update = false;
|
||||||
}
|
}
|
||||||
|
@ -93,17 +93,16 @@ describe('clipboard', function()
|
|||||||
local screen = Screen.new(72, 8)
|
local screen = Screen.new(72, 8)
|
||||||
screen:attach()
|
screen:attach()
|
||||||
command("let g:clipboard = 'bogus'")
|
command("let g:clipboard = 'bogus'")
|
||||||
feed_command('redir @+> | :call system("cat CONTRIBUTING.md") | redir END')
|
feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END')
|
||||||
-- it is made empty
|
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
~ |
|
~ |
|
||||||
~ |
|
~ |
|
||||||
~ |
|
~ |
|
||||||
Error detected while processing function provider#clipboard#Executable: |
|
|
||||||
line 5: |
|
|
||||||
clipboard: invalid g:clipboard |
|
|
||||||
clipboard: No provider. Try ":CheckHealth" or ":h clipboard". |
|
clipboard: No provider. Try ":CheckHealth" or ":h clipboard". |
|
||||||
Press ENTER or type command to continue^ |
|
|
||||||
]], nil, {{bold = true, foreground = Screen.colors.Blue}})
|
]], nil, {{bold = true, foreground = Screen.colors.Blue}})
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -118,7 +117,23 @@ describe('clipboard', function()
|
|||||||
feed_command('call getreg("*")') -- force load of provider
|
feed_command('call getreg("*")') -- force load of provider
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('has independent "* and unnamed registers per default', function()
|
it('`:redir @+>` invokes clipboard once-per-message', function()
|
||||||
|
eq(0, eval("g:clip_called_set"))
|
||||||
|
feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END')
|
||||||
|
-- Assuming CONTRIBUTING.md has >100 lines.
|
||||||
|
assert(eval("g:clip_called_set") > 100)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('`:redir @">` does not invoke clipboard', function()
|
||||||
|
-- :redir to a non-clipboard register, with `:set clipboard=unnamed`.
|
||||||
|
-- Does _not_ propagate to the clipboard (complies with Vim behavior).
|
||||||
|
command("set clipboard=unnamedplus")
|
||||||
|
eq(0, eval("g:clip_called_set"))
|
||||||
|
feed_command('redir @"> | :silent echo system("cat CONTRIBUTING.md") | redir END')
|
||||||
|
eq(0, eval("g:clip_called_set"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('has independent "* and unnamed registers per default', function()
|
||||||
insert("some words")
|
insert("some words")
|
||||||
feed('^"*dwdw"*P')
|
feed('^"*dwdw"*P')
|
||||||
expect('some ')
|
expect('some ')
|
||||||
@ -325,7 +340,7 @@ describe('clipboard', function()
|
|||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with clipboard=unnamedplus', function()
|
describe('clipboard=unnamedplus', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
feed_command('set clipboard=unnamedplus')
|
feed_command('set clipboard=unnamedplus')
|
||||||
end)
|
end)
|
||||||
@ -369,6 +384,7 @@ describe('clipboard', function()
|
|||||||
really unnamed
|
really unnamed
|
||||||
the plus]])
|
the plus]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('is updated on global changes', function()
|
it('is updated on global changes', function()
|
||||||
insert([[
|
insert([[
|
||||||
text
|
text
|
||||||
|
@ -5,7 +5,13 @@ let s:methods = {}
|
|||||||
let g:cliplossy = 0
|
let g:cliplossy = 0
|
||||||
let g:cliperror = 0
|
let g:cliperror = 0
|
||||||
|
|
||||||
|
" Count how many times the clipboard was invoked.
|
||||||
|
let g:clip_called_get = 0
|
||||||
|
let g:clip_called_set = 0
|
||||||
|
|
||||||
function! s:methods.get(reg)
|
function! s:methods.get(reg)
|
||||||
|
let g:clip_called_get += 1
|
||||||
|
|
||||||
if g:cliperror
|
if g:cliperror
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
@ -19,6 +25,8 @@ function! s:methods.get(reg)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:methods.set(lines, regtype, reg)
|
function! s:methods.set(lines, regtype, reg)
|
||||||
|
let g:clip_called_set += 1
|
||||||
|
|
||||||
if a:reg == '"'
|
if a:reg == '"'
|
||||||
call s:methods.set(a:lines,a:regtype,'+')
|
call s:methods.set(a:lines,a:regtype,'+')
|
||||||
call s:methods.set(a:lines,a:regtype,'*')
|
call s:methods.set(a:lines,a:regtype,'*')
|
||||||
|
Loading…
Reference in New Issue
Block a user