2

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!

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Likewise, you could use <esc>: instead of :<C-u> as in the other example. I probably overcomplicated things! :)
2

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.

1 Comment

Thanks very much for your input Conner, it works, but I've used Ingo's solution as it seems a little simpler.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.