2

I want to have different behavior for the different visual modes. As an example if I wanted to vnoremap S{ so that it has the following behavior:

  • surrounds the selection in v mode, (puts { at the start of selection and and } at the end of selection)
  • surrounds the lines in V mode, (puts { above and } below the selected lines)
  • surrounds the block in ctrl-v mode, (puts{s on the left edge and and }s on the right edge)

what would that look like? I have this but its buggy (behavior isn't consistent, seems to toggle behavior on every attempt.

vnoremap <expr> S{ visualmode() ==# "v" ?
\ "<Esc>`>a}<Esc>`<i{<Esc>" : visualmode() ==# "V" ?
\ "<Esc>`>o}<Esc>`<O{<Esc>va{=" :
\ "A}<Esc>gvI{<Esc>"
4

You use visualmode() which returns the last used visual mode, not the current one.

                   vvvvvvvvvvvv
vnoremap <expr> S{ visualmode() ==# "v" ?
\ "<Esc>`>a}<Esc>`<i{<Esc>" : visualmode() ==# "V" ?
                              ^^^^^^^^^^^^

You need the current one, which is given by mode():

                   vvvvvv
vnoremap <expr> S{ mode() ==# "v" ?
\ "<Esc>`>a}<Esc>`<i{<Esc>" : mode() ==# "V" ?
                              ^^^^^^

Unrelated to the issue, but you don't need to call [visual]mode() several times, and xnoremap is better than vnoremap:

xno <expr> S{ {
\  'v': "\e`>a}\e`<i{\e",
\  'V': "\e`>o}\e`<O{\eva{=",
\  '<c-v>': "A}\egvI{\e",
\ }[mode()]
  • "which returns the last used visual mode" That explains the toggling behavior of what I had. Thanks. Also, thanks for suggesting a cleaner way to map it – Josh Lawrence Oct 7 at 13:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.