Patch 8.2.2138

3 views
Skip to first unread message

Bram Moolenaar

unread,
Dec 13, 2020, 11:51:01 AM12/13/20
to vim...@googlegroups.com

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 -- Br...@Moolenaar.net -- 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 ///
Reply all
Reply to author
Forward
0 new messages