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
printf(\"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 --
:help i_CTRL-O and
:help 'cmdheight' for more info.