]> granicus.if.org Git - vim/commitdiff
patch 8.2.0916: mapping with partly modifyOtherKeys code does not work v8.2.0916
authorBram Moolenaar <Bram@vim.org>
Sat, 6 Jun 2020 20:36:24 +0000 (22:36 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 6 Jun 2020 20:36:24 +0000 (22:36 +0200)
Problem:    Mapping with partly modifyOtherKeys code does not work.
Solution:   If there is no mapping with a separate modifier include the
            modifier in the key and then try mapping again. (closes #6200)

src/edit.c
src/getchar.c
src/proto/getchar.pro
src/proto/term.pro
src/term.c
src/testdir/test_termcodes.vim
src/version.c

index 5252334ce5c9557da27ab85fee5152cd8d806ebd..dc0b45082d355e7bd0762885c8d20e0ba28fca80 100644 (file)
@@ -1609,7 +1609,7 @@ decodeModifyOtherKeys(int c)
 #endif
 
            mod_mask = decode_modifiers(arg[!form]);
-           c = merge_modifyOtherKeys(arg[form]);
+           c = merge_modifyOtherKeys(arg[form], &mod_mask);
        }
     }
 
index fcfad9dc0fe4b85b93f097dc885796f60bd992af..de814ccc68622fcc4474587f4590c78b00e38250 100644 (file)
@@ -1582,15 +1582,15 @@ updatescript(int c)
 }
 
 /*
- * Convert "c" plus "mod_mask" to merge the effect of modifyOtherKeys into the
+ * Convert "c" plus "modifiers" to merge the effect of modifyOtherKeys into the
  * character.
  */
     int
-merge_modifyOtherKeys(int c_arg)
+merge_modifyOtherKeys(int c_arg, int *modifiers)
 {
     int c = c_arg;
 
-    if (mod_mask & MOD_MASK_CTRL)
+    if (*modifiers & MOD_MASK_CTRL)
     {
        if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_'))
            c &= 0x1f;
@@ -1612,13 +1612,13 @@ merge_modifyOtherKeys(int c_arg)
            c = DEL;
 #endif
        if (c != c_arg)
-           mod_mask &= ~MOD_MASK_CTRL;
+           *modifiers &= ~MOD_MASK_CTRL;
     }
-    if ((mod_mask & (MOD_MASK_META | MOD_MASK_ALT))
+    if ((*modifiers & (MOD_MASK_META | MOD_MASK_ALT))
            && c >= 0 && c <= 127)
     {
        c += 0x80;
-       mod_mask &= ~(MOD_MASK_META|MOD_MASK_ALT);
+       *modifiers &= ~(MOD_MASK_META|MOD_MASK_ALT);
     }
     return c;
 }
@@ -1866,7 +1866,7 @@ vgetc(void)
                // cases they are put back in the typeahead buffer.
                vgetc_mod_mask = mod_mask;
                vgetc_char = c;
-               c = merge_modifyOtherKeys(c);
+               c = merge_modifyOtherKeys(c, &mod_mask);
            }
 
            break;
@@ -2254,6 +2254,44 @@ at_ctrl_x_key(void)
     return vim_is_ctrl_x_key(c);
 }
 
+/*
+ * Check if typebuf.tb_buf[] contains a modifer plus key that can be changed
+ * into just a key, apply that.
+ * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off
+ * + "max_offset"].
+ * Return the length of the replaced bytes, zero if nothing changed.
+ */
+    static int
+check_simplify_modifier(int max_offset)
+{
+    int                offset;
+    char_u     *tp;
+
+    for (offset = 0; offset < max_offset; ++offset)
+    {
+       if (offset + 3 >= typebuf.tb_len)
+           break;
+       tp = typebuf.tb_buf + typebuf.tb_off + offset;
+       if (tp[0] == K_SPECIAL && tp[1] == KS_MODIFIER)
+       {
+           int modifier = tp[2];
+           int new_c = merge_modifyOtherKeys(tp[3], &modifier);
+
+           if (new_c != tp[3] && modifier == 0)
+           {
+               char_u  new_string[MB_MAXBYTES];
+               int     len = mb_char2bytes(new_c, new_string);
+
+               if (put_string_in_typebuf(offset, 4, new_string, len,
+                                                          NULL, 0, 0) == FAIL)
+                   return -1;
+               return len;
+           }
+       }
+    }
+    return 0;
+}
+
 /*
  * Handle mappings in the typeahead buffer.
  * - When something was mapped, return map_result_retry for recursive mappings.
@@ -2519,6 +2557,11 @@ handle_mapping(
            if (keylen == 0 && save_keylen == KEYLEN_PART_KEY)
                keylen = KEYLEN_PART_KEY;
 
+           // If no termcode matched, try to include the modifier into the
+           // key.  This for when modifyOtherKeys is working.
+           if (keylen == 0)
+               keylen = check_simplify_modifier(max_mlen + 1);
+
            // When getting a partial match, but the last characters were not
            // typed, don't wait for a typed character to complete the
            // termcode.  This helps a lot when a ":normal" command ends in an
index 57d78b594e26f04ba66f496eec08a5103d9c5b56..bf131a5acea75d3b04f96dbc3422a6ce5b231196 100644 (file)
@@ -37,7 +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 merge_modifyOtherKeys(int c_arg, int *modifiers);
 int vgetc(void);
 int safe_vgetc(void);
 int plain_vgetc(void);
index d84823cc660e7ec1675beb408bbf9d5e8342865a..88fdcb89f75a6cd251e268709e798db70aeab86d 100644 (file)
@@ -68,6 +68,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 put_string_in_typebuf(int offset, int slen, char_u *string, int new_slen, char_u *buf, int bufsize, int *buflen);
 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);
index b4b5c091a83836b9a6de2c58c8071adadff17d56..70822195b0b829abded28479d177951b34ed4488 100644 (file)
@@ -4251,7 +4251,7 @@ is_mouse_topline(win_T *wp)
  * Remove "slen" bytes.
  * Returns FAIL for error.
  */
-    static int
+    int
 put_string_in_typebuf(
        int     offset,
        int     slen,
@@ -4342,7 +4342,7 @@ modifiers2keycode(int modifiers, int *key, char_u *string)
 /*
  * Check if typebuf.tb_buf[] contains a terminal key code.
  * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off
- * + max_offset].
+ * + "max_offset"].
  * Return 0 for no match, -1 for partial match, > 0 for full match.
  * Return KEYLEN_REMOVED when a key code was deleted.
  * With a match, the match is removed, the replacement code is inserted in
index 49262f529b816fa4b98cd853e4cdef049a5105c1..86589b28d09e13b7d3612e4e22893a7a50ffd3c5 100644 (file)
@@ -1222,6 +1222,23 @@ func RunTest_mapping_shift(key, func)
   endif
 endfunc
 
+func Test_modifyOtherKeys_mapped()
+  set timeoutlen=10
+  imap ' <C-W>
+  imap <C-W><C-A> c-a
+  call setline(1, '')
+
+  " single quote is turned into single byte CTRL-W
+  " CTRL-A is added with a separate modifier, and needs to be simplified before
+  " the mapping can match.
+  call feedkeys("a'" .. GetEscCodeCSI27('A', 5) .. "\<Esc>", 'Lx!')
+  call assert_equal('c-a', getline(1))
+
+  iunmap '
+  iunmap <C-W><C-A>
+  set timeoutlen&
+endfunc
+
 func RunTest_mapping_works_with_shift(func)
   new
   set timeoutlen=10
index 965877dbf0e4bfeb65924b0948ffd23221d23c65..6466000f5261ded96c04ca145d5d763eb3a79215 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    916,
 /**/
     915,
 /**/