cnoremap <C-\>e maps within the expression register

138 views
Skip to first unread message

Marcin Szamotulski

unread,
Sep 23, 2012, 4:20:39 AM9/23/12
to Vim Dev
Hello

The c_CTRL-\_e (<C-\>e) maps inside expression register are not working.
There is a very nice emacscommandline (http://www.vim.org/scripts/script.php?script_id=3554)
plugin which defines lots of nice maps in this way, but then when one
tries to write to expression register one gets errors. The minimal setup
to reproduce this is:

fun X()
return 'echo "X"'
endfun
cnoremap X <C-\>eX()<CR>

Now please try in insert mode:
<c-r>=X
and after pressing X I get the following error:
E15: invalid expression: ^eX()
E15: invalid expression: ^eX()

I got it twice. I think it would be nice to have the <C-\>e maps
working inside expression register (and in this case it would be nice of
vim script knew it, for example through including the '=' into to
getcmdline()) or to disable the <C-\>e maps inside the expression
register.

Best regards,
Marcin

Marcin Szamotulski

unread,
Oct 1, 2012, 7:16:24 AM10/1/12
to Vim Dev
In case somebody will stumble across this post, the solution that
I found for this is to define another map:
cnoremap <C-b> <C-R>
etc ... . It will not trigger the emacscommand line maps. One just has
to remember to not to use <C-W> while entering things into the
expression register (which is used rarely, so there is not much
opportunity to learn it, and lots of chances to forget it ;)

But this is far from perfect.

Best regards,
Marcin

Christian Brabandt

unread,
Oct 1, 2012, 8:49:14 AM10/1/12
to vim...@googlegroups.com
Would it be enough to simply disallow mappings in expression evalution mode?

diff --git a/src/ex_getln.c b/src/ex_getln.c
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1128,7 +1128,6 @@
i = Ctrl_R; /* CTRL-R CTRL-O == CTRL-R CTRL-R */
if (i == Ctrl_R)
c = plain_vgetc(); /* CTRL-R CTRL-R <char> */
- --no_mapping;
#ifdef FEAT_EVAL
/*
* Insert the result of an expression.
@@ -1136,6 +1135,10 @@
* a new one...
*/
new_cmdpos = -1;
+ /* allow special keys like BS, but don't allow mappings.
+ * prevents from trying to evaluate c_Ctrl-\_e mappings
+ * where the ctrl-\ e makes the following expression invalid */
+ ++allow_keys;
if (c == '=')
{
if (ccline.cmdfirstc == '=')/* can't do this recursively */
@@ -1150,7 +1153,10 @@
restore_cmdline(&save_ccline);
}
}
-#endif
+ --allow_keys;
+#endif
+ --no_mapping;
+
if (c != ESC) /* use ESC to cancel inserting register */
{
cmdline_paste(c, i == Ctrl_R, FALSE);


regards,
Christian

Marcin Szamotulski

unread,
Oct 1, 2012, 11:35:22 AM10/1/12
to vim...@googlegroups.com
Thanks! It works like a charm.

Best,
Marcin Szamotulski

Bram Moolenaar

unread,
Oct 3, 2012, 8:48:24 AM10/3/12
to Christian Brabandt, vim...@googlegroups.com
Would this not stop other mappings from working, e.g.:

cnoremap <C-Y> yank()


--
A special law prohibits unmarried women from parachuting on Sunday or she
shall risk arrest, fine, and/or jailing.
[real standing law in Florida, United States of America]

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Christian Brabandt

unread,
Oct 3, 2012, 8:53:21 AM10/3/12
to vim...@googlegroups.com
Hi Bram!
Yes, in Expression evaluation mode (i.e. when doing <c-r>=)

regards,
Christian
--
Eine freie Seele, wie die seine, kommt in Gefahr, frech zu
werden, wenn nicht ein edles Wohlwollen das sittliche Gleichgewicht
herstellt.
-- Goethe, Maximen und Reflektionen, Nr. 190

Bram Moolenaar

unread,
Oct 3, 2012, 10:21:16 AM10/3/12
to Christian Brabandt, vim...@googlegroups.com
Well, that's not nice, users should be able to type the expression with
their favorite mappings.

--
Any sufficiently advanced technology is indistinguishable from magic.
Arthur C. Clarke
Any sufficiently advanced bug is indistinguishable from a feature.
Rich Kulawiec

Christian Brabandt

unread,
Oct 3, 2012, 3:55:21 PM10/3/12
to vim...@googlegroups.com
Hi Bram!
Okay, this seems to fix it:

diff --git a/src/ex_getln.c b/src/ex_getln.c
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -668,8 +668,7 @@
--no_mapping;
--allow_keys;
/* CTRL-\ e doesn't work when obtaining an expression. */
- if (c != Ctrl_N && c != Ctrl_G
- && (c != 'e' || ccline.cmdfirstc == '='))
+ if (c != Ctrl_N && c != Ctrl_G && c != 'e')
{
vungetc(c);
c = Ctrl_BSL;


regards,
Christian
--
Ein junger Igel verirrt sich im Botanischen Garten.
Er hat schreckliche Angst und fragt jeden Kaktus:
"Bist du es, Mami?"

ZyX

unread,
Oct 3, 2012, 4:11:24 PM10/3/12
to vim...@googlegroups.com, cbl...@256bit.org
среда, 3 октября 2012 г., 23:55:28 UTC+4 пользователь Christian Brabandt написал:
> diff --git a/src/ex_getln.c b/src/ex_getln.c
> --- a/src/ex_getln.c
> +++ b/src/ex_getln.c
> @@ -668,8 +668,7 @@
> --no_mapping;
> --allow_keys;
> /* CTRL-\ e doesn't work when obtaining an expression. */
> - if (c != Ctrl_N && c != Ctrl_G
> - && (c != 'e' || ccline.cmdfirstc == '='))
> + if (c != Ctrl_N && c != Ctrl_G && c != 'e')
> {
> vungetc(c);
> c = Ctrl_BSL;
>
I guess it needs to be
diff --git a/src/ex_getln.c b/src/ex_getln.c
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -668,8 +668,7 @@
--no_mapping;
--allow_keys;
- /* CTRL-\ e doesn't work when obtaining an expression. */
- if (c != Ctrl_N && c != Ctrl_G
- && (c != 'e' || ccline.cmdfirstc == '='))
+ if (c != Ctrl_N && c != Ctrl_G && c != 'e')
{
vungetc(c);
c = Ctrl_BSL;
as the comment is no longer valid in this case.

ZyX

unread,
Oct 3, 2012, 4:21:49 PM10/3/12
to vim...@googlegroups.com, cbl...@256bit.org
> diff --git a/src/ex_getln.c b/src/ex_getln.c
> --- a/src/ex_getln.c
> +++ b/src/ex_getln.c
> @@ -668,8 +668,7 @@
> --no_mapping;
> --allow_keys;
> /* CTRL-\ e doesn't work when obtaining an expression. */
> - if (c != Ctrl_N && c != Ctrl_G
> - && (c != 'e' || ccline.cmdfirstc == '='))
> + if (c != Ctrl_N && c != Ctrl_G && c != 'e')
> {
> vungetc(c);
> c = Ctrl_BSL;
>
Wondering what behavior do you see when doing C-\e inside C-\e? I guess (have not tested) this check is there for a reason and you either have to check the nesting level or purge out the reason (globals?): because expression register is the only way I see to launch a command-line mode from within a command-line mode, and the other way to increase nesting (<C-r>=) is also forbidden.

Bram Moolenaar

unread,
Oct 3, 2012, 5:44:56 PM10/3/12
to Christian Brabandt, vim...@googlegroups.com
Thanks. Thus this fixes the reported problem without side effects?

--
Beer & pretzels can't be served at the same time in any bar or restaurant.
[real standing law in North Dakota, United States of America]

Marcin Szamotulski

unread,
Oct 4, 2012, 4:24:59 AM10/4/12
to vim...@googlegroups.com
>
> Thanks. Thus this fixes the reported problem without side effects?

I have tested it and it works fine in general. I only found a strange
behaviour in one case. I have a script which defines a cmap to <CR> and
calls a function via <C-\>e. When the function name is XX() everything
works fine, when the function name is WrapCmdLine() after pressing enter
in the expression register command line is not redraw, though it has
changes, since when I press <space><bs> it gets redrawn with the value
of the expression in the right place. You can test it with the attached
script. The function XX()=WrapCmdLine() only modifies the behaviour of
the cmdline when the cmdline starts with "! " sending the command line
to system() function rather than to the terminal directly.

I was testing with:
./vim -u NONE -i NONE --noplugin

Best regards,
Marcin Szamotulski
cmap.vim

Marcin Szamotulski

unread,
Oct 5, 2012, 8:35:12 AM10/5/12
to vim...@googlegroups.com
I found that the problem was caused by a <silent> keyword in a cmap:

fun! X()
return getcmdline()
endfun

" This map will not redraw the command line:
cnoremap <silent> <CR> <C-\>eX()<CR><CR>

" This map will redraw the command line:
cnoremap <CR> <C-\>eX()<CR><CR>

And actually all cmaps behave like that. Maybe we should add
:cmap-<silent> just after ":help :map-<silent>" in the help file. If so
I can write a patch for the documentation.

Best regards,
Marcin Szamotulski
Reply all
Reply to author
Forward
0 new messages