In a filetype plugin, for example ~/.vim/after/ftplugin/php.vim
, you could try this code:
nno <buffer> <nowait> <silent> * :<c-u>exe <sid>wrap_star(1)<cr>
nno <buffer> <nowait> <silent> g* :<c-u>exe <sid>wrap_star(0)<cr>
fu! s:wrap_star(whole) abort
let isk_save = &l:isk
setl isk+=$
try
exe 'norm! '.v:count1.(a:whole ? '' : 'g').'*'
catch
return 'echoerr '.string(v:exception)
finally
let &l:isk = isk_save
endtry
return ''
endfu
As your original code did, the s:wrap_star()
function should temporarily add the $
character to the buffer-local value of the 'iskeyword'
option. The command responsible for moving the cursor is:
exe 'norm! '.v:count1.(a:whole ? '' : 'g').'*'
It's wrapped inside a try
conditional to handle a possible error. No matter what happens, that is even if an error occurs, the finally
clause should remove the $
character from 'iskeyword'
, before Vim finishes to process the function.
You can check this by adding a non-existing command, such as :abcd
, inside the try
conditional:
nno <buffer> <nowait> <silent> * :<c-u>exe <sid>wrap_star(1)<cr>
nno <buffer> <nowait> <silent> g* :<c-u>exe <sid>wrap_star(0)<cr>
fu! s:wrap_star(whole) abort
let isk_save = &l:isk
setl isk+=$
try
abcd
exe 'norm! '.v:count1.(a:whole ? '' : 'g').'*'
catch
return 'echoerr '.string(v:exception)
finally
let &l:isk = isk_save
endtry
return ''
endfu
If you hit *
on a word, it should raise the error E492
:
Vim:E492: Not an editor command: abcd
After that, if you look at the value of 'isk'
(:echo &l:isk
), you shouldn't find the $
character.
Edit:
The <c-u>
keycode removes all the characters between the cursor position and the beginning of the command-line. You are probably familiar with it, because it's a readline key binding which also works in a bash or zsh shell. When you have typed a wrong command, and you want to rewrite a new one, you can press C-u
to kill the text from the cursor position up to the beginning.
It's not an obligation to use it, but it's a good habit. Watch this:
nno cd :echo 'hello'<cr>
Hit cd
: it displays hello
. Now, hit 2cd
: it raises the error:
E481: No range allowed
This is because, the 2
key that you pressed, combined with the first colon in the right-hand-side of your mapping, caused the following automatic translation:
2: → :.,.+1
So, :echo
received the range .,.+1
which means from the current line, down to the next one. But :echo
doesn't accept a range, so it's an error.
In your case, it's the same thing, :exe
doesn't accept a range. So, if you hit a number, you don't want :exe
to be, wrongly, prefixed by a range.
If you press a number to repeat the motion, the function will still have access to it through the built-in variable v:count1
.
See :h c^u
for more info.