Patch 9.0.1516
Problem:    Cannot use special keys in <Cmd> mapping.
Solution:   Do allow for special keys in <Cmd> and <ScriptCmd> mappings.
            (closes #12326)
Files:      runtime/doc/map.txt, src/errors.h, src/getchar.c,
            src/proto/getchar.pro, src/ops.c, src/testdir/test_mapping.vim


*** ../vim-9.0.1515/runtime/doc/map.txt 2023-02-03 12:28:00.299287568 +0000
--- runtime/doc/map.txt 2023-05-06 16:14:43.522945467 +0100
***************
*** 406,415 ****
  by <CR> in the {rhs} of the mapping definition.  |Command-line| mode is never
  entered.
  
-                                                       *E1137*
- <Cmd> and <ScriptCmd> commands can have only normal characters and cannot
- contain special characters like function keys.
- 
  
  1.3 MAPPING AND MODES                                 *:map-modes*
                        *mapmode-nvo* *mapmode-n* *mapmode-v* *mapmode-o*
--- 408,413 ----
*** ../vim-9.0.1515/src/errors.h        2023-05-05 22:58:30.805061562 +0100
--- src/errors.h        2023-05-06 16:14:43.522945467 +0100
***************
*** 2894,2901 ****
  #endif
  EXTERN char e_cmd_mapping_must_end_with_cr_before_second_cmd[]
        INIT(= N_("E1136: <Cmd> mapping must end with <CR> before second 
<Cmd>"));
! EXTERN char e_cmd_mapping_must_not_include_str_key[]
!       INIT(= N_("E1137: <Cmd> mapping must not include %s key"));
  #ifdef FEAT_EVAL
  EXTERN char e_using_bool_as_number[]
        INIT(= N_("E1138: Using a Bool as a Number"));
--- 2894,2900 ----
  #endif
  EXTERN char e_cmd_mapping_must_end_with_cr_before_second_cmd[]
        INIT(= N_("E1136: <Cmd> mapping must end with <CR> before second 
<Cmd>"));
! // E1137 unused
  #ifdef FEAT_EVAL
  EXTERN char e_using_bool_as_number[]
        INIT(= N_("E1138: Using a Bool as a Number"));
*** ../vim-9.0.1515/src/getchar.c       2023-04-22 22:54:28.049802336 +0100
--- src/getchar.c       2023-05-06 16:20:06.574629402 +0100
***************
*** 603,608 ****
--- 603,628 ----
  }
  
  /*
+  * Append "s" to the redo buffer, leaving 3-byte special key codes unmodified
+  * and escaping other K_SPECIAL and CSI bytes.
+  */
+     void
+ AppendToRedobuffSpec(char_u *s)
+ {
+     while (*s != NUL)
+     {
+       if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL)
+       {
+           // insert special key literally
+           add_buff(&redobuff, s, 3L);
+           s += 3;
+       }
+       else
+           add_char_buff(&redobuff, mb_cptr2char_adv(&s));
+     }
+ }
+ 
+ /*
   * Append a character to the redo buffer.
   * Translates special keys, NUL, CSI, K_SPECIAL and multibyte characters.
   */
***************
*** 3941,3954 ****
            if (c1 == K_ESC)
                c1 = ESC;
        }
-       if (c1 == Ctrl_V)
-       {
-           // CTRL-V is followed by octal, hex or other characters, reverses
-           // what AppendToRedobuffLit() does.
-           ++no_reduce_keys;  //  don't merge modifyOtherKeys
-           c1 = get_literal(TRUE);
-           --no_reduce_keys;
-       }
  
        if (got_int)
            aborted = TRUE;
--- 3961,3966 ----
***************
*** 3962,3980 ****
            emsg(_(e_cmd_mapping_must_end_with_cr_before_second_cmd));
            aborted = TRUE;
        }
!       else if (IS_SPECIAL(c1))
        {
!           if (c1 == K_SNR)
!               ga_concat(&line_ga, (char_u *)"<SNR>");
!           else
            {
!               semsg(e_cmd_mapping_must_not_include_str_key,
!                                              get_special_key_name(c1, cmod));
!               aborted = TRUE;
            }
        }
-       else
-           ga_append(&line_ga, c1);
  
        cmod = 0;
      }
--- 3974,4000 ----
            emsg(_(e_cmd_mapping_must_end_with_cr_before_second_cmd));
            aborted = TRUE;
        }
!       else if (c1 == K_SNR)
        {
!           ga_concat(&line_ga, (char_u *)"<SNR>");
!       }
!       else
!       {
!           if (cmod != 0)
!           {
!               ga_append(&line_ga, K_SPECIAL);
!               ga_append(&line_ga, KS_MODIFIER);
!               ga_append(&line_ga, cmod);
!           }
!           if (IS_SPECIAL(c1))
            {
!               ga_append(&line_ga, K_SPECIAL);
!               ga_append(&line_ga, K_SECOND(c1));
!               ga_append(&line_ga, K_THIRD(c1));
            }
+           else
+               ga_append(&line_ga, c1);
        }
  
        cmod = 0;
      }
*** ../vim-9.0.1515/src/proto/getchar.pro       2022-09-05 16:53:17.115566769 
+0100
--- src/proto/getchar.pro       2023-05-06 16:17:49.110752774 +0100
***************
*** 11,16 ****
--- 11,17 ----
  void restoreRedobuff(save_redo_T *save_redo);
  void AppendToRedobuff(char_u *s);
  void AppendToRedobuffLit(char_u *str, int len);
+ void AppendToRedobuffSpec(char_u *s);
  void AppendCharToRedobuff(int c);
  void AppendNumberToRedobuff(long n);
  void stuffReadbuff(char_u *s);
*** ../vim-9.0.1515/src/ops.c   2023-03-04 20:47:32.304617857 +0000
--- src/ops.c   2023-05-06 16:14:43.522945467 +0100
***************
*** 3701,3707 ****
                    ResetRedobuff();
                else
                {
!                   AppendToRedobuffLit(repeat_cmdline, -1);
                    AppendToRedobuff(NL_STR);
                    VIM_CLEAR(repeat_cmdline);
                }
--- 3701,3707 ----
                    ResetRedobuff();
                else
                {
!                   AppendToRedobuffSpec(repeat_cmdline);
                    AppendToRedobuff(NL_STR);
                    VIM_CLEAR(repeat_cmdline);
                }
*** ../vim-9.0.1515/src/testdir/test_mapping.vim        2023-04-16 
17:17:33.052497158 +0100
--- src/testdir/test_mapping.vim        2023-05-06 16:14:43.526945461 +0100
***************
*** 1001,1010 ****
    call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
    call assert_equal(0, x)
  
-   noremap <F3> <Cmd><F3>let x = 2<CR>
-   call assert_fails('call feedkeys("\<F3>", "xt")', 'E1137:')
-   call assert_equal(0, x)
- 
    noremap <F3> <Cmd>let x = 3
    call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
    call assert_equal(0, x)
--- 1001,1006 ----
***************
*** 1104,1114 ****
    unmap <F3>
    unmap! <F3>
    %bw!
- 
-   " command line ending in "0" is handled without errors
-   onoremap ix <cmd>eval 0<cr>
-   call feedkeys('dix.', 'xt')
-   ounmap ix
  endfunc
  
  " text object enters visual mode
--- 1100,1105 ----
***************
*** 1495,1500 ****
--- 1486,1509 ----
    call delete('Xcmdtext')
    delfunc SelectDash
    ounmap i-
+ 
+   new
+   call setline(1, 'aaa bbb ccc ddd')
+ 
+   " command can contain special keys
+   onoremap ix <Cmd>let g:foo ..= '…'<Bar>normal! <C-Right><CR>
+   let g:foo = ''
+   call feedkeys('0dix.', 'xt')
+   call assert_equal('……', g:foo)
+   call assert_equal('ccc ddd', getline(1))
+   unlet g:foo
+ 
+   " command line ending in "0" is handled without errors
+   onoremap ix <Cmd>eval 0<CR>
+   call feedkeys('dix.', 'xt')
+ 
+   ounmap ix
+   bwipe!
  endfunc
  
  func Test_map_script_cmd_restore()
*** ../vim-9.0.1515/src/version.c       2023-05-06 14:08:10.143045044 +0100
--- src/version.c       2023-05-06 16:16:10.290851058 +0100
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1516,
  /**/

-- 
A)bort, R)etry, D)o it right this time

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
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

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20230506152232.782AD1C1B21%40moolenaar.net.

Raspunde prin e-mail lui