Reputation: 77
I know this must be something simple.
Why does vnoremap <leader>rl di[<esc>pa]
wrap selected text in brackets, but:
vnoremap <leader>rl :call VisAddRefLink()<CR>
function! VisAddRefLink()
execute "normal! di[\<esc>pa]"
endfunction
doesn't?!
Any help appreciated!
Upvotes: 2
Views: 254
Reputation: 172530
Try this:
vnoremap <leader>rl :<C-u>call VisAddRefLink()<CR>
function! VisAddRefLink()
execute "normal! gvdi[\<esc>pa]"
endfunction
The <C-u>
in front of the call
avoids that the mapping inserts the '<,'>
visual range in front of it; we want the function called only one time, not once for every line in the range.
Inside the function, we need to re-establish the visual selection first before operating on it; the gv
does that.
Upvotes: 2
Reputation: 31040
You need to make your function handle a range. One way of accomplishing this would be like this:
vnoremap <leader>rl :call VisAddRefLink()<CR>
function! VisAddRefLink() range
exe a:firstline . "normal! ^i["
exe a:lastline . "normal! $a]"
endfunction
The reason your example isn't working is because the exe doesn't operate on a visual selection per say. For example, try visually selection something and then doing :norm d
. You'll notice it doesn't delete. If you add a range to your function like :help function-range-example
it helps with visual selections by operating in a similar fashion (line by line). However, it still isn't a true visual selection. The range addition does allow you the a:firstline
and a:lastline
variables though, which can be used to accomplish this. You can also accomplish this with a single like in this manner:
vnoremap <leader>rl <esc>:norm! '<^x2Phr['>$x2pr]<cr>
This first uses <esc>
to end the visual selection. Then it executes a normal command that will only run once. If the visual selection was left then it would run once for each line in the visual selection. Once it's run once it
'<^
jumps to the first line of the visual selection and to the first non-blank space on that line.
x2Phr[
deletes that character, pastes it twice in front, moves to the left so we're over the new character, and replaces it with the opening [
'>$
move to the last character on the last line of the visual selection
x2pr]
same as before but in the opposite direction
As usual, there's more than one way to skin a cat, especially with vimscript. As you learn more you see a lot of possibilities for accomplishing things.
Upvotes: 2