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>"

1 Answer 1


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

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

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

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 Oct 7, 2019 at 13:30

Your Answer

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

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