]> granicus.if.org Git - vim/commitdiff
patch 8.1.2350: other text for CTRL-V in Insert mode with modifyOtherKeys v8.1.2350
authorBram Moolenaar <Bram@vim.org>
Tue, 26 Nov 2019 18:33:22 +0000 (19:33 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 26 Nov 2019 18:33:22 +0000 (19:33 +0100)
Problem:    Other text for CTRL-V in Insert mode with modifyOtherKeys.
Solution:   Convert the Escape sequence back to key as if modifyOtherKeys is
            not set, and use CTRL-SHIFT-V to get the Escape sequence itself.
            (closes #5254)

runtime/doc/cmdline.txt
runtime/doc/insert.txt
src/edit.c
src/ex_getln.c
src/getchar.c
src/proto/edit.pro
src/proto/getchar.pro
src/proto/term.pro
src/term.c
src/testdir/test_termcodes.vim
src/version.c

index 092757a2befa398c46105c8b0f43aa8e2378a64e..ab0e682533ab6e343de0e90af37725124b3bb5df 100644 (file)
@@ -77,10 +77,17 @@ CTRL-V              Insert next non-digit literally.  Up to three digits form the
                way as in Insert mode (see above, |i_CTRL-V|).
                Note: Under Windows CTRL-V is often mapped to paste text.
                Use CTRL-Q instead then.
+               When |modifyOtherKeys| is enabled then special Escape sequence
+               is converted back to what it was without |modifyOtherKeys|,
+               unless the Shift key is also pressed.
                                                        *c_CTRL-Q*
 CTRL-Q         Same as CTRL-V.  But with some terminals it is used for
                control flow, it doesn't work then.
 
+CTRL-SHIFT-V                           *c_CTRL-SHIFT-V* *c_CTRL-SHIFT-Q*
+CTRL-SHIFT-Q   Works just like CTRL-V, unless |modifyOtherKeys| is active,
+               then it inserts the Escape sequence for a key with modifiers.
+
                                                        *c_<Left>* *c_Left*
 <Left>         cursor left
                                                        *c_<Right>* *c_Right*
index d28bf59984d31cd66cd2c708e4ebd8ebe7c92281..eac301aba96a7d630b7687580d3d8c76de293e79 100644 (file)
@@ -1,4 +1,4 @@
-*insert.txt*    For Vim version 8.1.  Last change: 2019 Oct 20
+*insert.txt*    For Vim version 8.1.  Last change: 2019 Nov 26
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -196,6 +196,13 @@ CTRL-V             Insert next non-digit literally.  For special keys, the
                mapping.
                Note: When CTRL-V is mapped (e.g., to paste text) you can
                often use CTRL-Q instead |i_CTRL-Q|.
+               When |modifyOtherKeys| is enabled then special Escape sequence
+               is converted back to what it was without |modifyOtherKeys|,
+               unless the Shift key is also pressed.
+
+                                               *i_CTRL-SHIFT-V*
+CTRL-SHIFT-V   Works just like CTRL-V, unless |modifyOtherKeys| is active,
+               then it inserts the Escape sequence for a key with modifiers.
 
                                                *i_CTRL-Q*
 CTRL-Q         Same as CTRL-V.
index c74f1bb3628e651782128a58115d4975a401de68..e1bf63db9317ab274c5fca275ddf26d5360bbbba 100644 (file)
@@ -1531,6 +1531,7 @@ ins_ctrl_v(void)
 {
     int                c;
     int                did_putchar = FALSE;
+    int                prev_mod_mask = mod_mask;
 
     /* may need to redraw when no more chars available now */
     ins_redraw(FALSE);
@@ -1554,6 +1555,12 @@ ins_ctrl_v(void)
 #ifdef FEAT_CMDL_INFO
     clear_showcmd();
 #endif
+
+    if ((c == ESC || c == CSI) && !(prev_mod_mask & MOD_MASK_SHIFT))
+       // Using CTRL-V: Change any modifyOtherKeys ESC sequence to a normal
+       // key.  Don't do this for CTRL-SHIFT-V.
+       c = decodeModifyOtherKeys(c);
+
     insert_special(c, FALSE, TRUE);
 #ifdef FEAT_RIGHTLEFT
     revins_chars++;
@@ -1561,6 +1568,59 @@ ins_ctrl_v(void)
 #endif
 }
 
+/*
+ * After getting an ESC or CSI for a literal key: If the typeahead buffer
+ * contains a modifyOtherKeys sequence then decode it and return the result.
+ * Otherwise return "c".
+ * Note that this doesn't wait for characters, they must be in the typeahead
+ * buffer already.
+ */
+    int
+decodeModifyOtherKeys(int c)
+{
+    char_u  *p = typebuf.tb_buf + typebuf.tb_off;
+    int            idx;
+    int            form = 0;
+    int            argidx = 0;
+    int            arg[2] = {0, 0};
+
+    // Recognize:
+    // form 0: {lead}{key};{modifier}u
+    // form 1: {lead}27;{modifier};{key}~
+    if ((c == CSI || (c == ESC && *p == '[')) && typebuf.tb_len >= 4)
+    {
+       idx = (*p == '[');
+       if (p[idx] == '2' && p[idx + 1] == '7' && p[idx + 2] == ';')
+       {
+           form = 1;
+           idx += 3;
+       }
+       while (idx < typebuf.tb_len && argidx < 2)
+       {
+           if (p[idx] == ';')
+               ++argidx;
+           else if (VIM_ISDIGIT(p[idx]))
+               arg[argidx] = arg[argidx] * 10 + (p[idx] - '0');
+           else
+               break;
+           ++idx;
+       }
+       if (idx < typebuf.tb_len
+               && p[idx] == (form == 1 ? '~' : 'u')
+               && argidx == 1)
+       {
+           // Match, consume the code.
+           typebuf.tb_off += idx + 1;
+           typebuf.tb_len -= idx + 1;
+
+           mod_mask = decode_modifiers(arg[!form]);
+           c = merge_modifyOtherKeys(arg[form]);
+       }
+    }
+
+    return c;
+}
+
 /*
  * Put a character directly onto the screen.  It's not stored in a buffer.
  * Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
index 6832158749c2d5008d101b1f6bf08f37aff06b92..4a4d76ec9de65c9c18589fcce47d46b84ab6f0ec 100644 (file)
@@ -2208,18 +2208,31 @@ getcmdline_int(
 
        case Ctrl_V:
        case Ctrl_Q:
-               ignore_drag_release = TRUE;
-               putcmdline('^', TRUE);
-               c = get_literal();          /* get next (two) character(s) */
-               do_abbr = FALSE;            /* don't do abbreviation now */
-               extra_char = NUL;
-               /* may need to remove ^ when composing char was typed */
-               if (enc_utf8 && utf_iscomposing(c) && !cmd_silent)
                {
-                   draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos);
-                   msg_putchar(' ');
-                   cursorcmd();
+                   int  prev_mod_mask = mod_mask;
+
+                   ignore_drag_release = TRUE;
+                   putcmdline('^', TRUE);
+                   c = get_literal();      // get next (two) character(s)
+                   do_abbr = FALSE;        // don't do abbreviation now
+                   extra_char = NUL;
+                   // may need to remove ^ when composing char was typed
+                   if (enc_utf8 && utf_iscomposing(c) && !cmd_silent)
+                   {
+                       draw_cmdline(ccline.cmdpos,
+                                               ccline.cmdlen - ccline.cmdpos);
+                       msg_putchar(' ');
+                       cursorcmd();
+                   }
+
+                   if ((c == ESC || c == CSI)
+                                         && !(prev_mod_mask & MOD_MASK_SHIFT))
+                       // Using CTRL-V: Change any modifyOtherKeys ESC
+                       // sequence to a normal key.  Don't do this for
+                       // CTRL-SHIFT-V.
+                       c = decodeModifyOtherKeys(c);
                }
+
                break;
 
 #ifdef FEAT_DIGRAPHS
index b086126d9aad1c70936e5da275ce353ddd179e70..a3af879991023cdf986528c400a40429cc7f658d 100644 (file)
@@ -1524,6 +1524,38 @@ updatescript(int c)
     }
 }
 
+/*
+ * Convert "c" plus "mod_mask" to merge the effect of modifyOtherKeys into the
+ * character.
+ */
+    int
+merge_modifyOtherKeys(int c_arg)
+{
+    int c = c_arg;
+
+    if (mod_mask & MOD_MASK_CTRL)
+    {
+       if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_'))
+       {
+           c &= 0x1f;
+           mod_mask &= ~MOD_MASK_CTRL;
+       }
+       else if (c == '6')
+       {
+           // CTRL-6 is equivalent to CTRL-^
+           c = 0x1e;
+           mod_mask &= ~MOD_MASK_CTRL;
+       }
+    }
+    if ((mod_mask & (MOD_MASK_META | MOD_MASK_ALT))
+           && c >= 0 && c <= 127)
+    {
+       c += 0x80;
+       mod_mask &= ~(MOD_MASK_META|MOD_MASK_ALT);
+    }
+    return c;
+}
+
 /*
  * Get the next input character.
  * Can return a special key or a multi-byte character.
@@ -1765,30 +1797,9 @@ vgetc(void)
            }
 
            if (!no_reduce_keys)
-           {
                // A modifier was not used for a mapping, apply it to ASCII
                // keys.  Shift would already have been applied.
-               if (mod_mask & MOD_MASK_CTRL)
-               {
-                   if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_'))
-                   {
-                       c &= 0x1f;
-                       mod_mask &= ~MOD_MASK_CTRL;
-                   }
-                   else if (c == '6')
-                   {
-                       // CTRL-6 is equivalent to CTRL-^
-                       c = 0x1e;
-                       mod_mask &= ~MOD_MASK_CTRL;
-                   }
-               }
-               if ((mod_mask & (MOD_MASK_META | MOD_MASK_ALT))
-                       && c >= 0 && c <= 127)
-               {
-                   c += 0x80;
-                   mod_mask &= ~(MOD_MASK_META|MOD_MASK_ALT);
-               }
-           }
+               c = merge_modifyOtherKeys(c);
 
            break;
        }
index bc69b41e830ca914b8ea65060b89f0ff0bf0f50e..49b9f4cff075ae7d1e15503da9500a9fefba8cb1 100644 (file)
@@ -2,6 +2,7 @@
 int edit(int cmdchar, int startln, long count);
 int ins_need_undo_get(void);
 void ins_redraw(int ready);
+int decodeModifyOtherKeys(int c);
 void edit_putchar(int c, int highlight);
 char_u *prompt_text(void);
 int prompt_curpos_editable(void);
index cfb3ab4ab76a6ec0f094b8f81f871d201ad46d5b..0e24bd392cae0cde29c0e679b704a7dcc85f7488 100644 (file)
@@ -37,6 +37,7 @@ void openscript(char_u *name, int directly);
 void close_all_scripts(void);
 int using_script(void);
 void before_blocking(void);
+int merge_modifyOtherKeys(int c_arg);
 int vgetc(void);
 int safe_vgetc(void);
 int plain_vgetc(void);
index 5af1996147ac19c03edcb5bf663e987a158f1aa2..8f1d33c4e61f13a6e47fda689ecd49e1fab83076 100644 (file)
@@ -65,6 +65,7 @@ int get_termcode_len(int idx);
 void del_termcode(char_u *name);
 void set_mouse_topline(win_T *wp);
 int is_mouse_topline(win_T *wp);
+int decode_modifiers(int n);
 int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen);
 void term_get_fg_color(char_u *r, char_u *g, char_u *b);
 void term_get_bg_color(char_u *r, char_u *g, char_u *b);
index 83268c71c509375162f390d8f2760a8d00149294..c7ac81c9c4b5a1969fbcb0482e76198fe08cf1d9 100644 (file)
@@ -4277,7 +4277,7 @@ put_string_in_typebuf(
 /*
  * Decode a modifier number as xterm provides it into MOD_MASK bits.
  */
-    static int
+    int
 decode_modifiers(int n)
 {
     int            code = n - 1;
index 05f0d18df40059bd8d4de6bb377a510b4a947469..298244e4301b342876d8069d9af40af65842dd4c 100644 (file)
@@ -1349,3 +1349,48 @@ func Test_mapping_works_with_shift_ctrl_alt()
   call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8)
   call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
 endfunc
+
+func Test_insert_literal()
+  set timeoutlen=10
+  new
+  " CTRL-V CTRL-X inserts a ^X
+  call feedkeys('a' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
+  call assert_equal("\<C-X>", getline(1))
+
+  call setline(1, '')
+  call feedkeys('a' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
+  call assert_equal("\<C-X>", getline(1))
+
+  " CTRL-SHIFT-V CTRL-X inserts escape sequencd
+  call setline(1, '')
+  call feedkeys('a' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
+  call assert_equal("\<Esc>[88;5u", getline(1))
+
+  call setline(1, '')
+  call feedkeys('a' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
+  call assert_equal("\<Esc>[27;5;88~", getline(1))
+
+  bwipe!
+  set timeoutlen&
+endfunc
+
+func Test_cmdline_literal()
+  set timeoutlen=10
+
+  " CTRL-V CTRL-Y inserts a ^Y
+  call feedkeys(':' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
+  call assert_equal("\"\<C-Y>", @:)
+
+  call feedkeys(':' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
+  call assert_equal("\"\<C-Y>", @:)
+
+  " CTRL-SHIFT-V CTRL-Y inserts escape sequencd
+  call feedkeys(':' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
+  call assert_equal("\"\<Esc>[89;5u", @:)
+
+  call setline(1, '')
+  call feedkeys(':' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
+  call assert_equal("\"\<Esc>[27;5;89~", @:)
+
+  set timeoutlen&
+endfunc
index 36e43a849c65de7e91450b81875035ead40de482..6c9ac22955f65f005257c4a1a79136c12e1a7ce1 100644 (file)
@@ -737,6 +737,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2350,
 /**/
     2349,
 /**/