Reputation: 806
I am writing a plugin to enhance lexics (e.g. automatically close brackets/quotes, filetype specific rules, etc) and some things have unexpected behavior for me. The plugin rule looks like this one:
{"key": "'", "pattern": '...', "keys": "'\<Left>"}
Since I am listening to InsertCharPre event to detect what key has been pressed, there is some restrictions in editing buffer directly using setline
, for instance (:help textlock). So I have to change v:char
variable or call feedkeys
instead of. The problem with v:char
is it cannot operate with special keys (it just inserts an escaped sequence) like "\", "\" and others (however, "\" seems to be handled correctly) which are frequently used in the plugin. So my only option is feedkeys, but if there is a key
in the keys
(see above), vim starts a recursion. I know about <C-v>
insert mode mapping but there can be a lot of such keys that will make adding new rules more complex. If there is no other option, I think, the best decision would be use set paste
option but as subject indicates I have some troubles with it.
...
set paste
call feedkeys("'\<Left>")
set nopaste
...
It seems that the whole body of the function is executed firstly and then the characters are inserted to the buffer at the moment when paste
is already nopaste
. Further reading of feedkeys
help was not successful (I tried different modes). You can try this simple code to see what I am talking about:
function! s:Foo()
startinsert
call feedkeys("ff")
stopinsert
endfunction
nnoremap <silent><CR> :call <SID>Foo()<CR>
Buffer should not contain any text after pressing Enter but if you comment stopinsert
command, everything goes as expected.
Ps: I know about lexima plugin but do not want to use it. I tried to solve the problem exploring the source code of lexima but there is inoremap <expr>
which I also do not want to use :).
Upvotes: 2
Views: 911
Reputation: 172688
feedkeys()
is about inserting keys into the typeahead buffer. Keys from this buffer are only consumed after the current command / function has ended (or if you explicitly read keys, e.g. via getchar()
). That explains you struggles to have the keys processed immediately; the function isn't meant for that :-) To submit keys immediately, you'd use :normal
. Yes, that doesn't work with textlock.
Based on your problem, I think using feedkeys()
with the n
mode (i.e. do not remap keys) should work. The keys won't be affected by user mappings, so you know exact which (built-in) keys need to be escaped. If you really needed to brace your keys with e.g. changing 'paste'
, you'd have to put the toggle commands inside feedkeys()
as well:
:call feedkeys(":set paste\<CR>\<Left>:set nopaste\<CR>")
Upvotes: 3