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.