forked from aniani/vim
patch 8.2.1308: Vim9: accidentally using "x" causes Vim to exit
Problem: Vim9: accidentally using "x" causes Vim to exit. Solution: Disallow using ":x" or "xit" in Vim9 script. (closes #6399)
This commit is contained in:
parent
0aac67a431
commit
ae616494d7
@ -71,16 +71,17 @@ comments start with #. >
|
||||
|
||||
The reason is that a double quote can also be the start of a string. In many
|
||||
places, especially halfway an expression with a line break, it's hard to tell
|
||||
what the meaning is. To avoid confusion only # comments are recognized.
|
||||
This is the same as in shell scripts and Python programs.
|
||||
what the meaning is, since both a string and a comment can be followed by
|
||||
arbitrary text. To avoid confusion only # comments are recognized. This is
|
||||
the same as in shell scripts and Python programs.
|
||||
|
||||
In Vi # is a command to list text with numbers. In Vim9 script you can use
|
||||
`:number` for that. >
|
||||
101number
|
||||
101 number
|
||||
|
||||
To improve readability there must be a space between a command and the #
|
||||
that starts a comment. Note that #{ is the start of a dictionary, therefore
|
||||
it cannot start a comment.
|
||||
it does not start a comment.
|
||||
|
||||
|
||||
Vim9 functions ~
|
||||
@ -93,7 +94,7 @@ The syntax is strict, to enforce code that is easy to read and understand.
|
||||
|
||||
Compilation is done when the function is first called, or when the
|
||||
`:defcompile` command is encountered in the script where the function was
|
||||
defined.
|
||||
defined. `:disassemble` also compiles the function.
|
||||
|
||||
`:def` has no options like `:function` does: "range", "abort", "dict" or
|
||||
"closure". A `:def` function always aborts on an error, does not get a range
|
||||
@ -104,7 +105,7 @@ be used, type checking will then be done at runtime, like with legacy
|
||||
functions.
|
||||
|
||||
Arguments are accessed by name, without "a:". There is no "a:" dictionary or
|
||||
"a:000" list.
|
||||
"a:000" list. Just like any other language.
|
||||
|
||||
Variable arguments are defined as the last argument, with a name and have a
|
||||
list type, similar to Typescript. For example, a list of numbers: >
|
||||
@ -216,29 +217,29 @@ Functions can be called without `:call`: >
|
||||
Using `:call` is still possible, but this is discouraged.
|
||||
|
||||
A method call without `eval` is possible, so long as the start is an
|
||||
identifier or can't be an Ex command. It does NOT work for string constants: >
|
||||
myList->add(123) # works
|
||||
g:myList->add(123) # works
|
||||
[1, 2, 3]->Process() # works
|
||||
#{a: 1, b: 2}->Process() # works
|
||||
{'a': 1, 'b': 2}->Process() # works
|
||||
"foobar"->Process() # does NOT work
|
||||
("foobar")->Process() # works
|
||||
'foobar'->Process() # does NOT work
|
||||
('foobar')->Process() # works
|
||||
identifier or can't be an Ex command. Examples: >
|
||||
myList->add(123)
|
||||
g:myList->add(123)
|
||||
[1, 2, 3]->Process()
|
||||
#{a: 1, b: 2}->Process()
|
||||
{'a': 1, 'b': 2}->Process()
|
||||
"foobar"->Process()
|
||||
("foobar")->Process()
|
||||
'foobar'->Process()
|
||||
('foobar')->Process()
|
||||
|
||||
In case there is ambiguity between a function name and an Ex command, use ":"
|
||||
to make clear you want to use the Ex command. For example, there is both the
|
||||
`:substitute` command and the `substitute()` function. When the line starts
|
||||
with `substitute(` this will use the function, prepend a colon to use the
|
||||
command instead: >
|
||||
In rare case there is ambiguity between a function name and an Ex command, use
|
||||
":" to make clear you want to use the Ex command. For example, there is both
|
||||
the `:substitute` command and the `substitute()` function. When the line
|
||||
starts with `substitute(` this will use the function. Prepend a colon to use
|
||||
the command instead: >
|
||||
:substitute(pattern (replacement (
|
||||
|
||||
Note that while variables need to be defined before they can be used,
|
||||
functions can be called before being defined. This is required to be able
|
||||
have cyclic dependencies between functions. It is slightly less efficient,
|
||||
since the function has to be looked up by name. And a typo in the function
|
||||
name will only be found when the call is executed.
|
||||
name will only be found when the function is called.
|
||||
|
||||
|
||||
Omitting function() ~
|
||||
@ -347,9 +348,10 @@ No curly braces expansion ~
|
||||
|curly-braces-names| cannot be used.
|
||||
|
||||
|
||||
No :append, :change or :insert ~
|
||||
No :xit, :append, :change or :insert ~
|
||||
|
||||
These commands are too quickly confused with local variable names.
|
||||
These commands are too easily confused with local variable names. Instead of
|
||||
`:x` or `:xit` you can use `:exit`.
|
||||
|
||||
|
||||
Comparators ~
|
||||
|
@ -3176,6 +3176,9 @@ ex_append(exarg_T *eap)
|
||||
int vcol;
|
||||
int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
|
||||
|
||||
if (not_in_vim9(eap) == FAIL)
|
||||
return;
|
||||
|
||||
// the ! flag toggles autoindent
|
||||
if (eap->forceit)
|
||||
curbuf->b_p_ai = !curbuf->b_p_ai;
|
||||
@ -3317,6 +3320,9 @@ ex_change(exarg_T *eap)
|
||||
{
|
||||
linenr_T lnum;
|
||||
|
||||
if (not_in_vim9(eap) == FAIL)
|
||||
return;
|
||||
|
||||
if (eap->line2 >= eap->line1
|
||||
&& u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
|
||||
return;
|
||||
|
@ -5686,6 +5686,8 @@ ex_stop(exarg_T *eap)
|
||||
static void
|
||||
ex_exit(exarg_T *eap)
|
||||
{
|
||||
if (not_in_vim9(eap) == FAIL)
|
||||
return;
|
||||
#ifdef FEAT_CMDWIN
|
||||
if (cmdwin_type != 0)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* vim9script.c */
|
||||
int in_vim9script(void);
|
||||
void ex_vim9script(exarg_T *eap);
|
||||
int not_in_vim9(exarg_T *eap);
|
||||
void ex_export(exarg_T *eap);
|
||||
void free_imports(int sid);
|
||||
void ex_import(exarg_T *eap);
|
||||
|
@ -1515,6 +1515,21 @@ def Test_fixed_size_list()
|
||||
assert_equal([2, 99, 3, 4, 5], l)
|
||||
enddef
|
||||
|
||||
def Test_no_insert_xit()
|
||||
call CheckDefExecFailure(['x = 1'], 'E1100:')
|
||||
call CheckDefExecFailure(['a = 1'], 'E1100:')
|
||||
call CheckDefExecFailure(['i = 1'], 'E1100:')
|
||||
call CheckDefExecFailure(['c = 1'], 'E1100:')
|
||||
|
||||
CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:')
|
||||
CheckScriptFailure(['vim9script', 'a = 1'], 'E488:')
|
||||
CheckScriptFailure(['vim9script', 'a'], 'E1100:')
|
||||
CheckScriptFailure(['vim9script', 'i = 1'], 'E488:')
|
||||
CheckScriptFailure(['vim9script', 'i'], 'E1100:')
|
||||
CheckScriptFailure(['vim9script', 'c = 1'], 'E488:')
|
||||
CheckScriptFailure(['vim9script', 'c'], 'E1100:')
|
||||
enddef
|
||||
|
||||
def IfElse(what: number): string
|
||||
let res = ''
|
||||
if what == 1
|
||||
|
@ -754,6 +754,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1308,
|
||||
/**/
|
||||
1307,
|
||||
/**/
|
||||
|
@ -7409,6 +7409,13 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
|
||||
// TODO: other commands with an expression argument
|
||||
|
||||
case CMD_append:
|
||||
case CMD_change:
|
||||
case CMD_insert:
|
||||
case CMD_xit:
|
||||
not_in_vim9(&ea);
|
||||
goto erret;
|
||||
|
||||
case CMD_SIZE:
|
||||
semsg(_("E476: Invalid command: %s"), ea.cmd);
|
||||
goto erret;
|
||||
|
@ -58,13 +58,30 @@ ex_vim9script(exarg_T *eap)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When in Vim9 script give an error and return FAIL.
|
||||
*/
|
||||
int
|
||||
not_in_vim9(exarg_T *eap)
|
||||
{
|
||||
switch (eap->cmdidx)
|
||||
{
|
||||
case CMD_insert:
|
||||
case CMD_append:
|
||||
case CMD_change:
|
||||
case CMD_xit:
|
||||
semsg(_("E1100: Missing :let: %s"), eap->cmd);
|
||||
return FAIL;
|
||||
default: break;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ":export let Name: type"
|
||||
* ":export const Name: type"
|
||||
* ":export def Name(..."
|
||||
* ":export class Name ..."
|
||||
*
|
||||
* ":export {Name, ...}"
|
||||
*/
|
||||
void
|
||||
ex_export(exarg_T *eap)
|
||||
|
Loading…
x
Reference in New Issue
Block a user