Patch 8.2.2138
Problem:    Vim9: "exit_cb" causes Vim to exit.
Solution:   Require white space after a command in Vim9 script. (closes #7467)
            Also fix that Vim9 style heredoc was not always recognized.
Files:      src/ex_cmds.h, src/ex_docmd.c, src/errors.h, src/userfunc.c,
            src/testdir/test_vim9_assign.vim,
            src/testdir/test_vim9_script.vim, src/testdir/test_let.vim


*** ../vim-8.2.2137/src/ex_cmds.h       2020-11-14 17:25:44.868329693 +0100
--- src/ex_cmds.h       2020-12-13 15:05:18.625003271 +0100
***************
*** 55,60 ****
--- 55,61 ----
  #define EX_LOCK_OK  0x1000000 // command can be executed when textlock is
                                // set; when missing disallows editing another
                                // buffer when curbuf_lock is set
+ #define EX_NONWHITE_OK 0x2000000  // command can be followed by non-white
  
  #define EX_FILES (EX_XFILE | EX_EXTRA)        // multiple extra files allowed
  #define EX_FILE1 (EX_FILES | EX_NOSPC)        // 1 file, defaults to current 
file
***************
*** 632,638 ****
        EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_global,     "global",       ex_global,
!       
EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_EXTRA|EX_DFLALL|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
        ADDR_LINES),
  EXCMD(CMD_goto,               "goto",         ex_goto,
        EX_RANGE|EX_COUNT|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
--- 633,639 ----
        EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_global,     "global",       ex_global,
!       
EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_EXTRA|EX_DFLALL|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
        ADDR_LINES),
  EXCMD(CMD_goto,               "goto",         ex_goto,
        EX_RANGE|EX_COUNT|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
***************
*** 1277,1283 ****
        EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_substitute, "substitute",   ex_substitute,
!       EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK,
        ADDR_LINES),
  EXCMD(CMD_sNext,      "sNext",        ex_previous,
        EX_EXTRA|EX_RANGE|EX_COUNT|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR,
--- 1278,1284 ----
        EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_substitute, "substitute",   ex_substitute,
!       EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
        ADDR_LINES),
  EXCMD(CMD_sNext,      "sNext",        ex_previous,
        EX_EXTRA|EX_RANGE|EX_COUNT|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR,
***************
*** 1652,1658 ****
        EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR,
        ADDR_LINES),
  EXCMD(CMD_vglobal,    "vglobal",      ex_global,
!       EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_DFLALL|EX_CMDWIN|EX_LOCK_OK,
        ADDR_LINES),
  EXCMD(CMD_var,                "var",          ex_var,
        EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
--- 1653,1659 ----
        EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR,
        ADDR_LINES),
  EXCMD(CMD_vglobal,    "vglobal",      ex_global,
!       
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_DFLALL|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
        ADDR_LINES),
  EXCMD(CMD_var,                "var",          ex_var,
        EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
***************
*** 1792,1807 ****
  
  // commands that don't start with a letter
  EXCMD(CMD_bang,               "!",            ex_bang,
!       EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILES|EX_CMDWIN|EX_LOCK_OK,
        ADDR_LINES),
  EXCMD(CMD_pound,      "#",            ex_print,
        EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_LINES),
  EXCMD(CMD_and,                "&",            ex_substitute,
!       EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY,
        ADDR_LINES),
  EXCMD(CMD_star,               "*",            ex_at,
!       EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_LINES),
  EXCMD(CMD_lshift,     "<",            ex_operators,
        
EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY,
--- 1793,1808 ----
  
  // commands that don't start with a letter
  EXCMD(CMD_bang,               "!",            ex_bang,
!       
EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILES|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
        ADDR_LINES),
  EXCMD(CMD_pound,      "#",            ex_print,
        EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_LINES),
  EXCMD(CMD_and,                "&",            ex_substitute,
!       
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY|EX_NONWHITE_OK,
        ADDR_LINES),
  EXCMD(CMD_star,               "*",            ex_at,
!       
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
        ADDR_LINES),
  EXCMD(CMD_lshift,     "<",            ex_operators,
        
EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY,
***************
*** 1813,1819 ****
        
EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY,
        ADDR_LINES),
  EXCMD(CMD_at,         "@",            ex_at,
!       EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_LINES),
  EXCMD(CMD_block,      "{{{{{{{{",     ex_block,  // not found normally
        0,
--- 1814,1820 ----
        
EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY,
        ADDR_LINES),
  EXCMD(CMD_at,         "@",            ex_at,
!       
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_NONWHITE_OK,
        ADDR_LINES),
  EXCMD(CMD_block,      "{{{{{{{{",     ex_block,  // not found normally
        0,
***************
*** 1822,1828 ****
        EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_tilde,      "~",            ex_substitute,
!       EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY,
        ADDR_LINES),
  
  // commands that start with an uppercase letter
--- 1823,1829 ----
        EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
        ADDR_NONE),
  EXCMD(CMD_tilde,      "~",            ex_substitute,
!       
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY|EX_NONWHITE_OK,
        ADDR_LINES),
  
  // commands that start with an uppercase letter
*** ../vim-8.2.2137/src/ex_docmd.c      2020-12-12 21:25:52.837244962 +0100
--- src/ex_docmd.c      2020-12-13 15:00:13.226108961 +0100
***************
*** 3528,3533 ****
--- 3528,3541 ----
      if (eap->cmdidx == CMD_final && p - eap->cmd == 4)
        eap->cmdidx = CMD_finally;
  
+     if (eap->cmdidx != CMD_SIZE && in_vim9script()
+           && !IS_WHITE_OR_NUL(*p) && !ends_excmd(*p) && *p != '!'
+           && (cmdnames[eap->cmdidx].cmd_argt & EX_NONWHITE_OK) == 0)
+     {
+       semsg(_(e_command_not_followed_by_white_space_str), eap->cmd);
+       eap->cmdidx = CMD_SIZE;
+     }
+ 
      return p;
  }
  
***************
*** 5114,5120 ****
  
  /*
   * Check if "c" ends an Ex command.
!  * In Vim9 script does not check for white space before # or #{.
   */
      int
  ends_excmd(int c)
--- 5122,5128 ----
  
  /*
   * Check if "c" ends an Ex command.
!  * In Vim9 script does not check for white space before #.
   */
      int
  ends_excmd(int c)
*** ../vim-8.2.2137/src/errors.h        2020-12-13 14:19:22.131979168 +0100
--- src/errors.h        2020-12-13 15:38:24.821893627 +0100
***************
*** 316,319 ****
  EXTERN char e_non_empty_string_required[]
        INIT(= N_("E1142: Non-empty string required"));
  EXTERN char e_empty_expression_str[]
!       INIT(= N_("E1143: empty expression: \"%s\""));
--- 316,323 ----
  EXTERN char e_non_empty_string_required[]
        INIT(= N_("E1142: Non-empty string required"));
  EXTERN char e_empty_expression_str[]
!       INIT(= N_("E1143: Empty expression: \"%s\""));
! EXTERN char e_command_not_followed_by_white_space_str[]
!       INIT(= N_("E1144: Command is not followed by white space: %s"));
! EXTERN char e_missing_heredoc_end_marker_str[]
!       INIT(= N_("E1145: Missing heredoc end marker: %s"));
*** ../vim-8.2.2137/src/userfunc.c      2020-11-22 18:15:40.171258382 +0100
--- src/userfunc.c      2020-12-13 15:38:37.353848980 +0100
***************
*** 3185,3191 ****
            lines_left = Rows - 1;
        if (theline == NULL)
        {
!           if (eap->cmdidx == CMD_def)
                emsg(_(e_missing_enddef));
            else
                emsg(_("E126: Missing :endfunction"));
--- 3185,3193 ----
            lines_left = Rows - 1;
        if (theline == NULL)
        {
!           if (skip_until != NULL)
!               semsg(_(e_missing_heredoc_end_marker_str), skip_until);
!           else if (eap->cmdidx == CMD_def)
                emsg(_(e_missing_enddef));
            else
                emsg(_("E126: Missing :endfunction"));
***************
*** 3352,3369 ****
  
            // Check for ":cmd v =<< [trim] EOF"
            //       and ":cmd [a, b] =<< [trim] EOF"
            // Where "cmd" can be "let", "var", "final" or "const".
            arg = skipwhite(skiptowhite(p));
            if (*arg == '[')
                arg = vim_strchr(arg, ']');
            if (arg != NULL)
            {
!               arg = skipwhite(skiptowhite(arg));
!               if (arg[0] == '=' && arg[1] == '<' && arg[2] =='<'
                        && (checkforcmd(&p, "let", 2)
                            || checkforcmd(&p, "var", 3)
                            || checkforcmd(&p, "final", 5)
!                           || checkforcmd(&p, "const", 5)))
                {
                    p = skipwhite(arg + 3);
                    if (STRNCMP(p, "trim", 4) == 0)
--- 3354,3377 ----
  
            // Check for ":cmd v =<< [trim] EOF"
            //       and ":cmd [a, b] =<< [trim] EOF"
+           //       and "lines =<< [trim] EOF" for Vim9
            // Where "cmd" can be "let", "var", "final" or "const".
            arg = skipwhite(skiptowhite(p));
            if (*arg == '[')
                arg = vim_strchr(arg, ']');
            if (arg != NULL)
            {
!               int found = (eap->cmdidx == CMD_def && arg[0] == '='
!                                            && arg[1] == '<' && arg[2] =='<');
! 
!               if (!found)
!                   // skip over the argument after "cmd"
!                   arg = skipwhite(skiptowhite(arg));
!               if (found || (arg[0] == '=' && arg[1] == '<' && arg[2] =='<'
                        && (checkforcmd(&p, "let", 2)
                            || checkforcmd(&p, "var", 3)
                            || checkforcmd(&p, "final", 5)
!                           || checkforcmd(&p, "const", 5))))
                {
                    p = skipwhite(arg + 3);
                    if (STRNCMP(p, "trim", 4) == 0)
*** ../vim-8.2.2137/src/testdir/test_vim9_assign.vim    2020-12-08 
22:08:47.672125693 +0100
--- src/testdir/test_vim9_assign.vim    2020-12-13 17:32:23.346376617 +0100
***************
*** 982,987 ****
--- 982,998 ----
          var&lines =<< trim END
          x
          x
+       enddef
+       defcompile
+   [END]
+   CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
+   delfunc! g:Func
+ 
+   lines =<< trim [END]
+       def Func()
+         var lines =<< trim END
+         x
+         x
          x
          x
          x
***************
*** 991,997 ****
        enddef
        call Func()
    [END]
!   CheckScriptFailure(lines, 'E990:')
    delfunc! g:Func
  enddef
  
--- 1002,1008 ----
        enddef
        call Func()
    [END]
!   CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
    delfunc! g:Func
  enddef
  
*** ../vim-8.2.2137/src/testdir/test_vim9_script.vim    2020-12-13 
14:19:22.131979168 +0100
--- src/testdir/test_vim9_script.vim    2020-12-13 15:01:09.653903594 +0100
***************
*** 3058,3064 ****
    new
    var lines =<< trim END
      vim9script
!     pu=split('abc', '\zs')
              ->join()
    END
    CheckScriptSuccess(lines)
--- 3058,3064 ----
    new
    var lines =<< trim END
      vim9script
!     pu =split('abc', '\zs')
              ->join()
    END
    CheckScriptSuccess(lines)
***************
*** 3079,3084 ****
--- 3079,3091 ----
    xunmap <F3>
  enddef
  
+ def Test_white_space_after_command()
+   var lines =<< trim END
+     exit_cb: Func})
+   END
+   CheckDefAndScriptFailure(lines, 'E1144:', 1)
+ enddef
+ 
  " Keep this last, it messes up highlighting.
  def Test_substitute_cmd()
    new
*** ../vim-8.2.2137/src/testdir/test_let.vim    2020-09-04 21:18:40.484161926 
+0200
--- src/testdir/test_let.vim    2020-12-13 17:48:23.775328713 +0100
***************
*** 338,344 ****
    endfunc
    END
    call writefile(text, 'XheredocFail')
!   call assert_fails('source XheredocFail', 'E126:')
    call delete('XheredocFail')
  
    let text =<< trim CodeEnd
--- 338,344 ----
    endfunc
    END
    call writefile(text, 'XheredocFail')
!   call assert_fails('source XheredocFail', 'E1145:')
    call delete('XheredocFail')
  
    let text =<< trim CodeEnd
***************
*** 347,353 ****
    endfunc
    CodeEnd
    call writefile(text, 'XheredocWrong')
!   call assert_fails('source XheredocWrong', 'E126:')
    call delete('XheredocWrong')
  
    let text =<< trim TEXTend
--- 347,353 ----
    endfunc
    CodeEnd
    call writefile(text, 'XheredocWrong')
!   call assert_fails('source XheredocWrong', 'E1145:')
    call delete('XheredocWrong')
  
    let text =<< trim TEXTend
*** ../vim-8.2.2137/src/version.c       2020-12-13 14:19:22.131979168 +0100
--- src/version.c       2020-12-13 14:50:00.388395996 +0100
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2138,
  /**/

-- 
FATAL ERROR! SYSTEM HALTED! - Press any key to continue doing nothing.

 /// Bram Moolenaar -- [email protected] -- 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    ///

-- 
-- 
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/202012131650.0BDGooRV3116662%40masaka.moolenaar.net.

Raspunde prin e-mail lui