I have this

let command = "execute printf(\"echo '%s'\", 'foo')"

It works fine.

execute command

However, if I prep it for INSERT-mode escaping.

let command = "execute <ESC> printf(\"echo '%s'\", 'foo') <CR>"

imap . command

In insert mode, I hit . VIM blows up. What am I doing wrong?


Mappings are basically the same as typing the right-hand side when they are executed. This means that when you type ., it's the same as if you typed

executeEscprintf(\"echo '%s'\", 'foo')Esc

So what you'll get is the word execute followed by whatever normal-mode commands come after the <ESC>, which obviously isn't what you're after.

What you actually want to do is go to command line mode before typing execute. You can do so by using <C-o> to get out of insert mode, and then : to get into command line mode.

You're going to have problems with echoing to the command line because when you return to insert mode it will clear out the command line, but this technically works:

let command = "<C-o>:execute printf(\"echom '%s'\", 'foo')<CR>"
exe "imap . " . command

You can tell it works because if you do :mess after pressing . in insert mode you'll see your message.

One workaround is to set the cmdheight larger than one. This way you'll still be able to see a few lines back even after insert mode has "pushed" the command line back with the message:

-- INSERT --

See :help i_CTRL-O and :help 'cmdheight' for more info.

  • I want it to actually output "foo" in the status bar (like echo foo) in insert mode when . is typed. Your command inserts echo 'foo' in text rather than outputting "foo" May 2 '17 at 22:25
  • Ah, Ok sorry I'll update. I think you're just missing a :.
    – Tumbler41
    May 2 '17 at 22:29

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.