Describe the bug
:help E840 (under :help complete-items) reads
The function is not allowed to move to another window or delete text.
Previously, move to another window meant that after the completefunc finishes, the current window has to be the same as the original one (where the completion was triggered). Temporarily switching windows (and going back) used to work fine. Since this change:
commit ff06f28
Author: Bram Moolenaar Br...@vim.org
Date: 2020-04-21 22:01:14 +0200patch 8.2.0614: get ml_get error when deleting a line in 'completefunc' Problem: Get ml_get error when deleting a line in 'completefunc'. (Yegappan Lakshmanan) Solution: Lock the text while evaluating 'completefunc'.
any attempt to move to another window (e.g. via :wincmd w) raises E565: Not allowed to change text here.
I believe that this is an unintended side effect of using textlock for preventing the deletion of lines. (If this were an intended, compatibility-breaking tightening of rules, E840 should be raised instead of E565.)
To Reproduce
Detailed steps to reproduce the behavior:
vim --clean (or gvim --clean, etc.) fun! TestComplete(findstart, base)
wincmd w
wincmd w
return (a:findstart ? col('.') : ['foo'])
endfun
:set completefunc=TestComplete
:new " To have more than one window.
:execute "normal! a\<C-x>\<C-u>"
Error detected while processing function TestComplete:
line 1:
565: Not allowed to change text here
Expected behavior
I understand the motivation to prevent unexpected changes during completion. However, switching to other windows temporarily should be harmless, is convenient to implement custom completions [1], and sometimes even necessary [2].
:set complete+=w.getbufline()), but as matching in the current buffer usually is done via search(), it is convenient to reuse that simple implementation for other windows as well. I have some completions like the MotionComplete plugin that uses a queried {motion} to obtain matches. That could not be emulated via low-level string-matching functions, but really has to be executed in that buffer. (And in order to use other windows as sources, it has to go there.)Environment (please complete the following information):
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.![]()
Describe the bug
:help E840(under:help complete-items) readsThe function is not allowed to move to another window or delete text.
Previously, move to another window meant that after the completefunc finishes, the current window has to be the same as the original one (where the completion was triggered). Temporarily switching windows (and going back) used to work fine. Since this change:
commit ff06f28
Author: Bram Moolenaar Br...@vim.org
Date: 2020-04-21 22:01:14 +0200patch 8.2.0614: get ml_get error when deleting a line in 'completefunc'
Expected behavior
I understand the motivation to prevent unexpected changes during completion. However, switching to other windows temporarily should be harmless, is convenient to implement custom completions [1], and sometimes even necessary [2].
- In an attempt to simplify the implementation of custom completions, my CompleteHelper plugin searches other windows in order to offer the same functionality as
:set complete+=w.- In many cases, the matching of completion candidates could be done without going to the corresponding window (e.g. using
getbufline()), but as matching in the current buffer usually is done viasearch(), it is convenient to reuse that simple implementation for other windows as well. I have some completions like the MotionComplete plugin that uses a queried{motion}to obtain matches. That could not be emulated via low-level string-matching functions, but really has to be executed in that buffer. (And in order to use other windows as sources, it has to go there.)
—
You are receiving this because you commented.
Yegappan, win_execute() does not cause an error:
fun! TestComplete(findstart, base)
call win_execute(win_getid((winnr() == 1) + 1), 'let g:line = getline(1)')
return (a:findstart ? col('.') : [g:line])
endfun
However, it wouldn't be trivial to change the plugin, and both the translation of currently open windows to ids and the transfer of the data (above done via global variable) don't look very elegant. On the other hand, win_execute() seems to have at least one nice property that my current implementation has to work around: When entering a window, the height may increase from 0 (which can happen with Rolodex mode) to 1. Too bad that it's only been introduced in version 8.2.
Besides, what's the use of E839: Completion function changed window if this is now pre-empted by E565: Not allowed to change text here?!
—
You are receiving this because you commented.
Yegappan,
win_execute()does not cause an error:fun! TestComplete(findstart, base)
call win_execute(win_getid((winnr() == 1) + 1), 'let g:line = getline(1)')
return (a:findstart ? col('.') : [g:line]) endfunHowever, it wouldn't be trivial to change the plugin, and both the translation of currently open windows to ids and the transfer of the data (above done via global variable) don't look very elegant. On the other hand,
win_execute()seems to have at least one nice property that my current implementation has to work around: When entering a window, the height may increase from 0 (which can happen with Rolodex mode) to 1. Too bad that it's only been introduced in version 8.2.Besides, what's the use of
E839: Completion function changed windowif this is now pre-empted byE565: Not allowed to change text here?!
—
You are receiving this because you commented.
I'l make a change to relax this a bit. It's not trivial, I hope it will
allow enough without allowing too much.
That seems to have done the trick; my completion library can access other windows again without causing an error.
Thanks Bram for the prompt fix; this is highly appreciated! Also thanks to Yegappan for recommending the very interesting win_execute() alternative, which over the long term may simplify several of my plugin implementations!
—
You are receiving this because you commented.