ZyX wrote:
Consider the following command:

     vim -u NONE -c 'noremap!<expr>  - "‘"' \
                 -c 'normal i-' \
                 -c 'wq! result.out'

result.out:
     $ cat result.out | hexdump -C
     00000000  c3 a2 c2 80 c2 98 0a                              |.......|
     00000007

Tested on vim-7.3 from gentoo repos and on vim-7.3.94 (revision f987220caa57).
Everything works fine if it is not expr mapping or if I replace «"‘"» with
«"\u2018"». Same issue with opening double english quote (u201C) and second
level opening russian quote (u201E).

See :help :map-<expr> and search CSI.  This applies to 0x80 byte, too.

map.txt:
Note that there are some tricks to make special keys work and escape CSI bytes
in the text.  The |:map| command also does this, thus you must avoid that it
is done twice.  This does not work: >
        :imap <expr> <F3> "<Char-0x611B>"
Because the <Char- sequence is escaped for being a |:imap| argument and then
again for using <expr>.  This does work: >
        :imap <expr> <F3> "\u611B"
Using 0x80 as a single byte before other text does not work, it will be seen
as a special key.


What happened is

:noremap! <expr> - "<Char-0x2018>"

map rhs: " <e2> <80> <98> "
  |
  | When creating mapping 0x80 and 0x9b (CSI) are escaped.
  |   <80>           => <80> <fe> X
  v
mapblock.m_str: " <e2> <80> <fe> X <98> "
  |
  | When mapping is used it is evaluated. (eval_map_expr())
  | In this case, eval('"\xe2\x80\xfeX\x98"').
  v
evaluated result: <e2> <80> <fe> X <98>
  |
  | To insert to the typeahead buffer, 0x80 and 0x9b are escaped again.
  | Since the result is an invalid sequence it is interpreted as three
  | characters. (vim_strsave_escape_csi())
  |   <e2>           => U+00e2 => <c3> <a2>
  |   <80> <fe> X    => not changed because it is interpreted as
  |                     special key like <Left> (<80> k l)
  |   <98>           => U+0098 => <c2> <98>
  v
typeahead: <c3> <a2> <80> <fe> X <c2> <98>
  |
  | unescaped and inserted to the buffer
  |   <80> <fe> X    => <80> => U+0080 => <c2> <80>
  v
buffer: <c3> <a2> <c2> <80> <c2> <98>


Perhaps this could be fixed by unescaping the rhs before evaluating it.
But I'm not sure there is no side effect.

diff --git a/src/getchar.c b/src/getchar.c
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -4491,37 +4491,49 @@
     static char_u *
 eval_map_expr(str, c)
     char_u     *str;
     int                c;          /* NUL or typed character for abbreviation 
*/
 {
     char_u     *res;
     char_u     *p;
+    char_u     *expr;
     char_u     *save_cmd;
     pos_T      save_cursor;

+    expr = vim_strsave(str);
+    if (expr == NULL)
+       return NULL;
+    vim_unescape_csi(expr);
+
     save_cmd = save_cmdline_alloc();
     if (save_cmd == NULL)
+    {
+       vim_free(expr);
        return NULL;
+    }

     /* Forbid changing text or using ":normal" to avoid most of the bad side
      * effects.  Also restore the cursor position. */
     ++textlock;
 #ifdef FEAT_EX_EXTRA
     ++ex_normal_lock;
 #endif
     set_vim_var_char(c);  /* set v:char to the typed character */
     save_cursor = curwin->w_cursor;
-    p = eval_to_string(str, NULL, FALSE);
+    p = eval_to_string(expr, NULL, FALSE);
     --textlock;
 #ifdef FEAT_EX_EXTRA
     --ex_normal_lock;
 #endif
     curwin->w_cursor = save_cursor;

     restore_cmdline_alloc(save_cmd);
+
+    vim_free(expr);
+
     if (p == NULL)
        return NULL;
     res = vim_strsave_escape_csi(p);
     vim_free(p);

     return res;
 }




--
Yukihiro Nakadaira - [email protected]

--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

Raspunde prin e-mail lui