Re: ctrl-o with a mapping

38 views
Skip to first unread message

ZyX

unread,
Feb 5, 2011, 11:57:00 AM2/5/11
to vim...@googlegroups.com, vim...@googlegroups.com
Reply to message «Re: ctrl-o with a mapping»,
sent 19:38:30 05 February 2011, Saturday
by Ben Fritz:

Perhaps a bug somewhere? It should be redirected to vim_dev, I think.

Original message:
> On Feb 5, 4:05 am, ZyX <zyx....@gmail.com> wrote:
> > Reply to message «Re: ctrl-o with a mapping»,
> > sent 23:56:30 05 February 2011, Saturday
> >
> > by AK:
> > > Well, this is a normal mode mapping (nnoremap), by definition all of
> > > its contents should run under normal mode or not at all.
> >
> > The fact that it is normal mode mapping means that {lhs} will be replaced
> > by {rhs} if you type {lhs} in normal mode. It never meant that it should
> > run under normal mode, the fact that first command is run under normal
> > mode is just a consequence of the fact that you press {lhs} in normal
> > mode.
>
> It seems strange to me that recorded macros behave differently from
> normal mode mappings, especially if you interpret them as above. :help
> @ even says "the register is executed like a mapping".
>
> For example:
>
> qa0:echo getfontname()<Enter>q
> i<C-O>@a
>
> This does not insert the :echo getfontname(), it does exactly as is
> done in normal mode.
>
> However,
>
> :nnoremap <F9> 0:echo getfontname()<CR>
>
> i<C-O><F9>
>
> This inserts the :echo command in the text.

signature.asc

James Vega

unread,
Feb 5, 2011, 1:44:54 PM2/5/11
to vim...@googlegroups.com
On Sat, Feb 05, 2011 at 07:57:00PM +0300, ZyX wrote:
> Reply to message «Re: ctrl-o with a mapping»,
> sent 19:38:30 05 February 2011, Saturday
> by Ben Fritz:
>
> Perhaps a bug somewhere? It should be redirected to vim_dev, I think.
>
> Original message:
> > On Feb 5, 4:05 am, ZyX <zyx....@gmail.com> wrote:
> > > Reply to message «Re: ctrl-o with a mapping»,
> > > sent 23:56:30 05 February 2011, Saturday
> > >
> > > by AK:
> > > > Well, this is a normal mode mapping (nnoremap), by definition all of
> > > > its contents should run under normal mode or not at all.
> > >
> > > The fact that it is normal mode mapping means that {lhs} will be replaced
> > > by {rhs} if you type {lhs} in normal mode. It never meant that it should
> > > run under normal mode, the fact that first command is run under normal
> > > mode is just a consequence of the fact that you press {lhs} in normal
> > > mode.
> >
> > It seems strange to me that recorded macros behave differently from
> > normal mode mappings, especially if you interpret them as above. :help
> > @ even says "the register is executed like a mapping".

Hmm, that was a very recent addition to the help and the behavior
doesn't agree with that. I wonder what the impetus was behind the
addition of that description.

> > For example:
> >
> > qa0:echo getfontname()<Enter>q
> > i<C-O>@a
> >
> > This does not insert the :echo getfontname(), it does exactly as is
> > done in normal mode.

This makes sense. <C-o> lets you execute one normal mode command. In
this case that command is @a.

> > However,
> >
> > :nnoremap <F9> 0:echo getfontname()<CR>
> >
> > i<C-O><F9>
> >
> > This inserts the :echo command in the text.

And in this case the one normal mode command is 0, since mappings are
treated just like a user typing.

--
James
GPG Key: 1024D/61326D40 2003-09-02 James Vega <jame...@jamessan.com>

signature.asc

Ingo Karkat

unread,
Feb 5, 2011, 1:57:59 PM2/5/11
to vim...@googlegroups.com

Not every normal mode-mapping is automatically suitable for execution via
i_CTRL-O; you need to explicitly design your mappings for that purpose. I
wouldn't call it a bug, rather a weakness in Vi(m)'s model of mode-based operation.


Here are some rules and guidelines from my personal "Vim scripting guide":

The |i_CTRL-O| command allows execution of one normal mode command, then
returns to insert mode. If a normal mode mapping concatenates multiple normal
mode commands, this breaks down in temporary normal mode and literally inserts
the second part of the command into the buffer instead.
To support execution of normal mode mappings from within insert mode (via
|i_CTRL-O|), these strategies can be used:
a) Instead of concatenating multiple normal mode commands, use one :normal
mapping: >
"nnoremap zC zCVzC
nnoremap <silent> zC :<C-U>normal! zCVzC<CR>
b) Concatenate multiple Ex commands via <Bar>, not >
:<C-U>call FirstCommand()<CR>:<C-U>call SecondCommand()<CR>
c) Shadow normal mode mappings are by insert mode mappings that re-enter
normal mode, then invoke the normal mode mapping. >
inoremap <silent> <script> <SID>MyMapping <C-\><C-O><SID>MyMapping
d) Normal mode mappings that consist of multiple Ex command lines (and where
Ex commands cannot be concatenated via <Bar>) use <SID>NM instead of
':<C-U>'; the insert mode variant of <SID>NM re-enter command mode for one
ex command line. >
" Handle execution from insert mode via |i_CTRL-O|.
nnoremap <silent> <SID>NM :<C-U>
inoremap <silent> <SID>NM <C-\><C-O>:
"nnoremap <silent> <script> <SID>MyMap1:<C-U>call MySecondCommand()<CR>
nnoremap <silent> <script> <SID>MyMap1<SID>NMcall MySecondCommand()<CR>
e) If none of the above is possible, at least force normal mode for
subsequent commands via |CTRL-\_CTRL-N| to avoid accidental insertion of
the remainder of the mapping. >
nnoremap zC zC<C-\><C-N>VzCzz

If you rewrite your mapping as follows, it'll also work in temporary insert mode:
:nnoremap <F9> :execute 'normal! 0'<Bar>echo getfontname()<CR>

-- regards, ingo

Christian Brabandt

unread,
Feb 7, 2011, 6:06:14 PM2/7/11
to vim...@googlegroups.com
Hi Ingo!

Good information. I took your text, reworked it a little bit and put it
into the faq� It's question 20.20 and it should be in the web tomorrow
or the day after tomorrow. Please check.

�) http://www.github.com/chrisbra/vim_faq
and on the web at:
http://vimhelp.appspot.com/vim_faq.txt.html

Mit freundlichen Gr��en
Christian
--

Milan Vancura

unread,
Feb 9, 2011, 6:14:22 AM2/9/11
to vim...@googlegroups.com
> Here are some rules and guidelines from my personal "Vim scripting guide":
...snip
> -- regards, ingo

Hi Ingo.

Thank you for a very precise description. I must say there much of interesting
even for ~15 years user of vim like me :-) However, it's quite hard to read,
esp. as a FAQ entry. What about the following, wouldn't it be more readable for
beginners? Even I _know_ it is not the simplest or shortest solution for those
who know all details and special characters:

-------------------------------------------------------------------------------
Mapping in normal mode could be executed after Ctrl-O from insert mode as well
but if there are more commands included in the mapping {rhs}, only the first
one will be executed in normal mode and the rest of {rhs} will be printed
literally in insert mode. One of ways to workaround this problem is to make
{rhs} be one command, via wrapping it to the function. For example:

function GetFontNameOfFirstChar()
normal 0
echo getfontname()
endfunction

:nmap <F9> :call GetFontNameOfFirstChar()<CR>

For more solutions of this problem look <a href="Ingo's mail">here</a>.
-------------------------------------------------------------------------------

Milan

--
Milan Vancura, Prague, Czech Republic, Europe

Ingo Karkat

unread,
Feb 9, 2011, 9:46:45 AM2/9/11
to Christian Brabandt, vim...@googlegroups.com
On 08-Feb-2011 00:06, Christian Brabandt wrote:

> On Sa, 05 Feb 2011, Ingo Karkat wrote:
>
>> Here are some rules and guidelines from my personal "Vim scripting guide":
>

> Good information. I took your text, reworked it a little bit and put it

> into the faqı It's question 20.20 and it should be in the web tomorrow

> or the day after tomorrow. Please check.
>

> ı) http://www.github.com/chrisbra/vim_faq

Hello Christian,

I'm glad you have found the information useful and have added it to the VIM FAQ.
Thanks for maintaining this FAQ; I guess I will find some good nuggets there.

So far, I've reviewed only the added question 20.20; here's my list of
corrections. (Excuse the plain diff; I'll fork and send a pull request in case I
find additional corrections.)

-- regards, ingo

#v+
--- vim_faq.txt.orig 2011-02-09 15:24:31.798020200 +0100
+++ vim_faq.txt 2011-02-09 15:36:25.059282500 +0100
@@ -5122,7 +5122,7 @@
From https://groups.google.com/group/vim_dev/msg/75f1f2dfc00908bb

Not every normal mode-mapping is automatically suitable for execution via

-<Ctrl-O> from within inser mode; you need to explicitly design your mappings
+<Ctrl-O> from within insert mode; you need to explicitly design your mappings
for that purpose.

The <Ctrl-O> command allows execution of one normal mode command from
@@ -5139,17 +5139,19 @@

b) Concatenate multiple Ex commands via <Bar> on the rhs:

- :nnoremap zC :<C-U>call MyMap1()<CR><Bar>call MyMap2()<CR>
+ :nnoremap zC :<C-U>call MyMap1()<Bar>call MyMap2()<CR>

c) Shadow normal mode mappings by insert mode mappings that
re-enter normal mode, then invoke the normal mode mapping:

- :inoremap <silent> <script> zC <SID>MyMap1<C-\><C-O><SID>MyMap2
+ :nnoremap <silent> <SID>MyMap2 :<C-U>call MyMap2()<CR>
+ :inoremap <silent> <script> <SID>MyMap2 <C-\><C-O><SID>MyMap2
+ :nnoremap <silent> <script> zC <SID>MyMap1<SID>MyMap2

d) Normal mode mappings that consist of multiple Ex command lines (and

- where Ex commands cannot be concatenated via <Bar>) use <SID>NM
- instead of ':<C-U>'; use the <SID>NM Mapping that enters normal mode
- for one ex command line:
+ where Ex commands cannot be concatenated via <Bar>) replace ':<C-U>'
+ with <SID>NM; the <SID>NM mapping enters normal mode for one ex command
+ line:

:nnoremap <silent> <SID>NM :<C-U>


:inoremap <silent> <SID>NM <C-\><C-O>:

#v-

Ingo Karkat

unread,
Feb 9, 2011, 9:59:22 AM2/9/11
to mi...@ucw.cz, Christian Brabandt, vim...@googlegroups.com

Hi Milan,

On the one hand I fully agree that this entry is too detailed; I wrote it as my
personal notes in case I would encounter this problem again in the far future,
and I wanted to have all the options at hand.

Your suggested entry perfectly captures the essence of the problem and a
possible solution. I am not sure whether an added function is always the best
way to solve the problem, though. It really depends on the kind of mappings that
one wants to combine.

I guess I'll leave it to Christian, the FAQ maintainer, to decide whether he
wants to keep the full details or replace it with your shorter suggestion and
the link to this archived entry on vim_dev.

-- regards, ingo

Milan Vancura

unread,
Feb 9, 2011, 12:19:16 PM2/9/11
to vim...@googlegroups.com
> Your suggested entry perfectly captures the essence of the problem and a
> possible solution. I am not sure whether an added function is always the best
> way to solve the problem, though. It really depends on the kind of mappings that
> one wants to combine.

Hi Ingo,

I think your list is much better from the technical point of view - and thanks
for it! I saved it for my purposes, too. I just wanted to write something
shorter and easier to read as this should go to FAQ - to not discourage the
reader. In practice, your solutions are faster to do if one understands the
background - this is why I suggested to link them at the end of the answer,
too.

We'll see what does Christian do with our texts :-)

Thanks once again for your help-text, it was usable even for ~15 years user of
vim like me,

Milan

BTW: Do you know the example with echo does not work as user expect? Because
the output is immediately overwritten with "--INSERT--" - so it's questionable
if this example is good to mention in FAQ, probably not...

Reply all
Reply to author
Forward
0 new messages