I can't seem to figure out how to set a variable equal to the number of matches in a file.
I have tried this
let a=execute('%s/<++>//ne')
but it won't work (throws this error:
Error detected while processing function myfunctions#Tab:
line 2:
E523: Not allowed here
). I want a variable with the number of matches for a regular expression and I can't seem to find a way to use the execute() function with the substitute command. (execute('%s/test//ne')
throws an error too).
EDIT: I am trying to run this inside a function that is called as an <expr>
mapping. The full function body is this (control characters properly inserted):
function! myfunctions#Tab()
let a=execute('%s/<++>//ne')
if a > 0
return "/<++>^M:noh^Mc4l"
else
return "^I"
endif
endfunction
The goal is to insert a tab if the pattern <++> doesn't exist, and if it does, then find it and replace it. I mapped it like this:
inoremap <expr> <tab> myfunctions#Tab()
The reason why you're hitting this error is that a function called in an <expr>
mapping is restricted and can't modify the current buffer.
From :help :map-expression
:
Be very careful about side effects! The expression is evaluated while obtaining characters, you may very well make the command dysfunctional.
For this reason the following is blocked:
- Changing the buffer text
textlock
.- Editing another buffer.
- The
:normal
command.- Moving the cursor is allowed, but it is restored afterwards.
What is triggering this situation is your :s
command. Even though you're using the /n
flag, which does not modify the buffer, the :s
command generally introduces modification and as such is completely blocked under textlock
.
If what you're trying to do is jump to the next <++>
on tab, then the best option is to use the search()
function, which will move your cursor to the next match and return the line number (non-zero) if a match was found.
Since an <expr>
mapping doesn't preserve cursor movement, you should use a normal mapping instead.
This gets tricky quickly though... It turns out this is one of the hardest mappings to get right...
But the gist of it is: you'll want to escape Insert mode temporarily with CTRL-\ CTRL-O
and call your function. There, you can do your search()
. If the search matches, you'll need to call :stopinsert
to interrupt the temporary escape from Insert mode (essentially making it permanent). Then you can run the c4l
command, but you need to do so using feedkeys()
, since it will leave you in Normal mode at the end.
If there's no match and you want a tab character inserted, you can then use feedkeys()
to insert the tab character.
Putting it all together:
function! myfunctions#Tab()
if search('<++>')
stopinsert
call feedkeys('c4l', 'n')
else
call feedkeys("\t", 'n')
endif
endfunction
inoremap <silent> <Tab> <C-\><C-o>:call myfunctions#Tab()<CR>
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments