Assume I am inside a function and currently in visual mode (mode() returns v or V or "\<c-v>", such as when you run vmap-expr)

How can I quit the visual mode? Should I call feedkeys("\<esc>", 'ni')?

How to run a mapping in the visual mode, like 4> to indent the lines 4 times. It seems normal 4> does not work.

  • > already works in visual mode, what you need the mapping for? – Christian Brabandt Nov 23 '18 at 11:53
  • I need to do a lot of other things after indentation. The question is actually general: how to type some keystroke or execute a visual mapping <Plug>xxx in function in visual mode. – Liu Sha Nov 23 '18 at 11:57
  • so have you tried using xmap? – Christian Brabandt Nov 23 '18 at 12:27
  • I have some vmaps that calls functions. I use something like vmap ,x :<C-U>call MyFunc()<CR>. Inside the function I could do normal gv4>. See help gv. How do you call your function? – Ralf Nov 25 '18 at 11:30
  • @Ralf : makes you in normal mode. I use vmap <express> Func() so that I am still in visual mode(). Or it is because I did “normal gv “. – Liu Sha Nov 25 '18 at 11:37

Instead of another comment:

As far as I understand you want to work with vmap <expr> Like mapping ," to a function:

vmap <expr> ," MyFunction()

In this case the the function has to return the keystrokes that should be executed by Vim. Lets assume you want to surround visually selected text with something (function hardly tested):

function! ExecSurround(pre, post)
    let mode = mode()
    if(mode == "V")
        " line: Put it above and below the selected lines
        return "V`>o" . a:post . "\e`<O" . a:pre . "\e"
    elseif(mode == "\<C-V>")
        " block: Put it before and after selection on every line
        return "A" . a:post . "\egvI" . a:pre . "\e"
        " char: put it before first and after last char
        return "v`>a" . a:post . "\e`<i" . a:pre . "\e"

vmap <expr> ," ExecSurround('"', '"')

As far as I understand :help :map-expression, the things you can do in the function are limited. You have to return the keystrokes, that change your text.

As said in my comment, I would choose another way:

function! Surround(pre, post)
    let mode = visualmode()
    if(mode == "V")
        call execute("normal `>o" . a:post . "\e`<O" . a:pre . "\e")
    elseif(mode == "\<C-V>")
        call execute("normal gvA" . a:post . "\egvI" . a:pre . "\e")
        call execute("normal `>a" . a:post . "\e`<i" . a:pre . "\e")

vmap ," :<C-U>call Surround('"', '"')<CR>

That way you are not limited by the restrictions from "map-expression" and could easily add additional functionality.

Whatever you want to do might be more complex than this, but perhaps it helps to go on.

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.