mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
Merge remote-tracking branch 'vim/master'
This commit is contained in:
+17
-9
@@ -2848,7 +2848,8 @@ str2list({expr} [, {utf8}]) List convert each character of {expr} to
|
||||
str2nr({expr} [, {base} [, {quoted}]])
|
||||
Number convert String to Number
|
||||
strcharpart({str}, {start} [, {len}])
|
||||
String {len} characters of {str} at {start}
|
||||
String {len} characters of {str} at
|
||||
character {start}
|
||||
strchars({expr} [, {skipcc}]) Number character length of the String {expr}
|
||||
strdisplaywidth({expr} [, {col}]) Number display length of the String {expr}
|
||||
strftime({format} [, {time}]) String format time with a specified format
|
||||
@@ -2857,8 +2858,9 @@ stridx({haystack}, {needle} [, {start}])
|
||||
Number index of {needle} in {haystack}
|
||||
string({expr}) String String representation of {expr} value
|
||||
strlen({expr}) Number length of the String {expr}
|
||||
strpart({str}, {start} [, {len}])
|
||||
String {len} bytes of {str} at byte {start}
|
||||
strpart({str}, {start} [, {len} [, {chars}]])
|
||||
String {len} bytes/chars of {str} at
|
||||
byte {start}
|
||||
strptime({format}, {timestring})
|
||||
Number Convert {timestring} to unix timestamp
|
||||
strridx({haystack}, {needle} [, {start}])
|
||||
@@ -3430,7 +3432,8 @@ byte2line({byte}) *byte2line()*
|
||||
|
||||
byteidx({expr}, {nr}) *byteidx()*
|
||||
Return byte index of the {nr}'th character in the string
|
||||
{expr}. Use zero for the first character, it returns zero.
|
||||
{expr}. Use zero for the first character, it then returns
|
||||
zero.
|
||||
This function is only useful when there are multibyte
|
||||
characters, otherwise the returned value is equal to {nr}.
|
||||
Composing characters are not counted separately, their byte
|
||||
@@ -9960,17 +9963,22 @@ strlen({expr}) The result is a Number, which is the length of the String
|
||||
{expr} in bytes.
|
||||
If the argument is a Number it is first converted to a String.
|
||||
For other types an error is given.
|
||||
If you want to count the number of multi-byte characters use
|
||||
If you want to count the number of multibyte characters use
|
||||
|strchars()|.
|
||||
Also see |len()|, |strdisplaywidth()| and |strwidth()|.
|
||||
|
||||
Can also be used as a |method|: >
|
||||
GetString()->strlen()
|
||||
|
||||
strpart({src}, {start} [, {len}]) *strpart()*
|
||||
strpart({src}, {start} [, {len} [, {chars}]]) *strpart()*
|
||||
The result is a String, which is part of {src}, starting from
|
||||
byte {start}, with the byte length {len}.
|
||||
To count characters instead of bytes use |strcharpart()|.
|
||||
When {chars} is present and TRUE then {len} is the number of
|
||||
characters positions (composing characters are not counted
|
||||
separately, thus "1" means one base character and any
|
||||
following composing characters).
|
||||
To count {start} as characters instead of bytes use
|
||||
|strcharpart()|.
|
||||
|
||||
When bytes are selected which do not exist, this doesn't
|
||||
result in an error, the bytes are simply omitted.
|
||||
@@ -9982,8 +9990,8 @@ strpart({src}, {start} [, {len}]) *strpart()*
|
||||
strpart("abcdefg", 3) == "defg"
|
||||
|
||||
< Note: To get the first character, {start} must be 0. For
|
||||
example, to get three bytes under and after the cursor: >
|
||||
strpart(getline("."), col(".") - 1, 3)
|
||||
example, to get the character under the cursor: >
|
||||
strpart(getline("."), col(".") - 1, 1, v:true)
|
||||
<
|
||||
Can also be used as a |method|: >
|
||||
GetText()->strpart(5)
|
||||
|
||||
+1
-1
@@ -923,7 +923,7 @@ channel_connect(
|
||||
*waittime -= elapsed_msec;
|
||||
if (waitnow > 0)
|
||||
{
|
||||
mch_delay((long)waitnow, TRUE);
|
||||
mch_delay((long)waitnow, MCH_DELAY_IGNOREINPUT);
|
||||
ui_breakcheck();
|
||||
*waittime -= waitnow;
|
||||
}
|
||||
|
||||
+6
-5
@@ -2675,6 +2675,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
int oplen;
|
||||
int concat;
|
||||
typval_T var2;
|
||||
int vim9script = in_vim9script();
|
||||
|
||||
// "." is only string concatenation when scriptversion is 1
|
||||
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
||||
@@ -2689,7 +2690,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
*arg = eval_next_line(evalarg);
|
||||
else
|
||||
{
|
||||
if (evaluate && in_vim9script() && !VIM_ISWHITE(**arg))
|
||||
if (evaluate && vim9script && !VIM_ISWHITE(**arg))
|
||||
{
|
||||
error_white_both(p, oplen);
|
||||
clear_tv(rettv);
|
||||
@@ -2721,14 +2722,14 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
/*
|
||||
* Get the second variable.
|
||||
*/
|
||||
if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[oplen]))
|
||||
if (evaluate && vim9script && !IS_WHITE_OR_NUL((*arg)[oplen]))
|
||||
{
|
||||
error_white_both(p, oplen);
|
||||
clear_tv(rettv);
|
||||
return FAIL;
|
||||
}
|
||||
*arg = skipwhite_and_linebreak(*arg + oplen, evalarg);
|
||||
if (eval6(arg, &var2, evalarg, !in_vim9script() && op == '.') == FAIL)
|
||||
if (eval6(arg, &var2, evalarg, !vim9script && op == '.') == FAIL)
|
||||
{
|
||||
clear_tv(rettv);
|
||||
return FAIL;
|
||||
@@ -2745,12 +2746,12 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
char_u *s1 = tv_get_string_buf(rettv, buf1);
|
||||
char_u *s2 = NULL;
|
||||
|
||||
if (in_vim9script() && (var2.v_type == VAR_VOID
|
||||
if (vim9script && (var2.v_type == VAR_VOID
|
||||
|| var2.v_type == VAR_CHANNEL
|
||||
|| var2.v_type == VAR_JOB))
|
||||
emsg(_(e_inval_string));
|
||||
#ifdef FEAT_FLOAT
|
||||
else if (var2.v_type == VAR_FLOAT)
|
||||
else if (vim9script && var2.v_type == VAR_FLOAT)
|
||||
{
|
||||
vim_snprintf((char *)buf2, NUMBUFLEN, "%g",
|
||||
var2.vval.v_float);
|
||||
|
||||
+13
-5
@@ -950,7 +950,7 @@ static funcentry_T global_functions[] =
|
||||
{"stridx", 2, 3, FEARG_1, ret_number, f_stridx},
|
||||
{"string", 1, 1, FEARG_1, ret_string, f_string},
|
||||
{"strlen", 1, 1, FEARG_1, ret_number, f_strlen},
|
||||
{"strpart", 2, 3, FEARG_1, ret_string, f_strpart},
|
||||
{"strpart", 2, 4, FEARG_1, ret_string, f_strpart},
|
||||
{"strptime", 2, 2, FEARG_1, ret_number,
|
||||
#ifdef HAVE_STRPTIME
|
||||
f_strptime
|
||||
@@ -8305,10 +8305,8 @@ f_strpart(typval_T *argvars, typval_T *rettv)
|
||||
else
|
||||
len = slen - n; // default len: all bytes that are available.
|
||||
|
||||
/*
|
||||
* Only return the overlap between the specified part and the actual
|
||||
* string.
|
||||
*/
|
||||
// Only return the overlap between the specified part and the actual
|
||||
// string.
|
||||
if (n < 0)
|
||||
{
|
||||
len += n;
|
||||
@@ -8321,6 +8319,16 @@ f_strpart(typval_T *argvars, typval_T *rettv)
|
||||
else if (n + len > slen)
|
||||
len = slen - n;
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN && argvars[3].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
int off;
|
||||
|
||||
// length in characters
|
||||
for (off = n; off < slen && len > 0; --len)
|
||||
off += mb_ptr2len(p + off);
|
||||
len = off - n;
|
||||
}
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = vim_strnsave(p + n, len);
|
||||
}
|
||||
|
||||
@@ -2463,6 +2463,20 @@ eval_variable(
|
||||
tv = sv->sv_tv;
|
||||
}
|
||||
}
|
||||
else if (in_vim9script())
|
||||
{
|
||||
ufunc_T *ufunc = find_func(name, FALSE, NULL);
|
||||
|
||||
if (ufunc != NULL)
|
||||
{
|
||||
foundFunc = TRUE;
|
||||
if (rettv != NULL)
|
||||
{
|
||||
rettv->v_type = VAR_FUNC;
|
||||
rettv->vval.v_string = vim_strsave(ufunc->uf_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundFunc)
|
||||
|
||||
+146
-101
@@ -66,7 +66,9 @@ static int getargopt(exarg_T *eap);
|
||||
# define ex_cexpr ex_ni
|
||||
#endif
|
||||
|
||||
static linenr_T default_address(exarg_T *eap);
|
||||
static linenr_T get_address(exarg_T *, char_u **, cmd_addr_T addr_type, int skip, int silent, int to_other_file, int address_count);
|
||||
static void address_default_all(exarg_T *eap);
|
||||
static void get_flags(exarg_T *eap);
|
||||
#if !defined(FEAT_PERL) \
|
||||
|| !defined(FEAT_PYTHON) || !defined(FEAT_PYTHON3) \
|
||||
@@ -1886,7 +1888,9 @@ do_one_cmd(
|
||||
|
||||
ea.cmd = cmd;
|
||||
#ifdef FEAT_EVAL
|
||||
if (may_have_range)
|
||||
if (!may_have_range)
|
||||
ea.line1 = ea.line2 = default_address(&ea);
|
||||
else
|
||||
#endif
|
||||
if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL)
|
||||
goto doend;
|
||||
@@ -2288,59 +2292,7 @@ do_one_cmd(
|
||||
}
|
||||
|
||||
if ((ea.argt & EX_DFLALL) && ea.addr_count == 0)
|
||||
{
|
||||
buf_T *buf;
|
||||
|
||||
ea.line1 = 1;
|
||||
switch (ea.addr_type)
|
||||
{
|
||||
case ADDR_LINES:
|
||||
case ADDR_OTHER:
|
||||
ea.line2 = curbuf->b_ml.ml_line_count;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
buf = firstbuf;
|
||||
while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL)
|
||||
buf = buf->b_next;
|
||||
ea.line1 = buf->b_fnum;
|
||||
buf = lastbuf;
|
||||
while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL)
|
||||
buf = buf->b_prev;
|
||||
ea.line2 = buf->b_fnum;
|
||||
break;
|
||||
case ADDR_BUFFERS:
|
||||
ea.line1 = firstbuf->b_fnum;
|
||||
ea.line2 = lastbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
ea.line2 = LAST_WIN_NR;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
ea.line2 = LAST_TAB_NR;
|
||||
break;
|
||||
case ADDR_TABS_RELATIVE:
|
||||
ea.line2 = 1;
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
if (ARGCOUNT == 0)
|
||||
ea.line1 = ea.line2 = 0;
|
||||
else
|
||||
ea.line2 = ARGCOUNT;
|
||||
break;
|
||||
case ADDR_QUICKFIX_VALID:
|
||||
#ifdef FEAT_QUICKFIX
|
||||
ea.line2 = qf_get_valid_size(&ea);
|
||||
if (ea.line2 == 0)
|
||||
ea.line2 = 1;
|
||||
#endif
|
||||
break;
|
||||
case ADDR_NONE:
|
||||
case ADDR_UNSIGNED:
|
||||
case ADDR_QUICKFIX:
|
||||
iemsg(_("INTERNAL: Cannot use EX_DFLALL with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
address_default_all(&ea);
|
||||
|
||||
// accept numbered register only when no count allowed (:put)
|
||||
if ( (ea.argt & EX_REGSTR)
|
||||
@@ -3017,50 +2969,7 @@ parse_cmd_address(exarg_T *eap, char **errormsg, int silent)
|
||||
for (;;)
|
||||
{
|
||||
eap->line1 = eap->line2;
|
||||
switch (eap->addr_type)
|
||||
{
|
||||
case ADDR_LINES:
|
||||
case ADDR_OTHER:
|
||||
// Default is the cursor line number. Avoid using an invalid
|
||||
// line number though.
|
||||
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
|
||||
eap->line2 = curbuf->b_ml.ml_line_count;
|
||||
else
|
||||
eap->line2 = curwin->w_cursor.lnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
eap->line2 = CURRENT_WIN_NR;
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
eap->line2 = curwin->w_arg_idx + 1;
|
||||
if (eap->line2 > ARGCOUNT)
|
||||
eap->line2 = ARGCOUNT;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
case ADDR_BUFFERS:
|
||||
eap->line2 = curbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
eap->line2 = CURRENT_TAB_NR;
|
||||
break;
|
||||
case ADDR_TABS_RELATIVE:
|
||||
case ADDR_UNSIGNED:
|
||||
eap->line2 = 1;
|
||||
break;
|
||||
case ADDR_QUICKFIX:
|
||||
#ifdef FEAT_QUICKFIX
|
||||
eap->line2 = qf_get_cur_idx(eap);
|
||||
#endif
|
||||
break;
|
||||
case ADDR_QUICKFIX_VALID:
|
||||
#ifdef FEAT_QUICKFIX
|
||||
eap->line2 = qf_get_cur_valid_idx(eap);
|
||||
#endif
|
||||
break;
|
||||
case ADDR_NONE:
|
||||
// Will give an error later if a range is found.
|
||||
break;
|
||||
}
|
||||
eap->line2 = default_address(eap);
|
||||
eap->cmd = skipwhite(eap->cmd);
|
||||
lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, silent,
|
||||
eap->addr_count == 0, address_count++);
|
||||
@@ -3248,6 +3157,27 @@ append_command(char_u *cmd)
|
||||
*d = NUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If "start" points "&opt", "&l:opt", "&g:opt" or "$ENV" return a pointer to
|
||||
* the name. Otherwise just return "start".
|
||||
*/
|
||||
char_u *
|
||||
skip_option_env_lead(char_u *start)
|
||||
{
|
||||
char_u *name = start;
|
||||
|
||||
if (*start == '&')
|
||||
{
|
||||
if ((start[1] == 'l' || start[1] == 'g') && start[2] == ':')
|
||||
name += 3;
|
||||
else
|
||||
name += 1;
|
||||
}
|
||||
else if (*start == '$')
|
||||
name += 1;
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an Ex command by its name, either built-in or user.
|
||||
* Start of the name can be found at eap->cmd.
|
||||
@@ -3279,9 +3209,7 @@ find_ex_command(
|
||||
p = eap->cmd;
|
||||
if (lookup != NULL)
|
||||
{
|
||||
// Skip over first char for "&opt = val", "$ENV = val" and "@r = val".
|
||||
char_u *pskip = (*eap->cmd == '&' || *eap->cmd == '$')
|
||||
? eap->cmd + 1 : eap->cmd;
|
||||
char_u *pskip = skip_option_env_lead(eap->cmd);
|
||||
|
||||
if (vim_strchr((char_u *)"{('[\"@", *p) != NULL
|
||||
|| ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL))
|
||||
@@ -3659,6 +3587,61 @@ addr_error(cmd_addr_T addr_type)
|
||||
emsg(_(e_invrange));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the default address for an address type.
|
||||
*/
|
||||
static linenr_T
|
||||
default_address(exarg_T *eap)
|
||||
{
|
||||
linenr_T lnum = 0;
|
||||
|
||||
switch (eap->addr_type)
|
||||
{
|
||||
case ADDR_LINES:
|
||||
case ADDR_OTHER:
|
||||
// Default is the cursor line number. Avoid using an invalid
|
||||
// line number though.
|
||||
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
|
||||
lnum = curbuf->b_ml.ml_line_count;
|
||||
else
|
||||
lnum = curwin->w_cursor.lnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
lnum = CURRENT_WIN_NR;
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
lnum = curwin->w_arg_idx + 1;
|
||||
if (lnum > ARGCOUNT)
|
||||
lnum = ARGCOUNT;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
case ADDR_BUFFERS:
|
||||
lnum = curbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
lnum = CURRENT_TAB_NR;
|
||||
break;
|
||||
case ADDR_TABS_RELATIVE:
|
||||
case ADDR_UNSIGNED:
|
||||
lnum = 1;
|
||||
break;
|
||||
case ADDR_QUICKFIX:
|
||||
#ifdef FEAT_QUICKFIX
|
||||
lnum = qf_get_cur_idx(eap);
|
||||
#endif
|
||||
break;
|
||||
case ADDR_QUICKFIX_VALID:
|
||||
#ifdef FEAT_QUICKFIX
|
||||
lnum = qf_get_cur_valid_idx(eap);
|
||||
#endif
|
||||
break;
|
||||
case ADDR_NONE:
|
||||
// Will give an error later if a range is found.
|
||||
break;
|
||||
}
|
||||
return lnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a single EX address.
|
||||
*
|
||||
@@ -4020,6 +4003,68 @@ error:
|
||||
return lnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set eap->line1 and eap->line2 to the whole range.
|
||||
* Used for commands with the EX_DFLALL flag and no range given.
|
||||
*/
|
||||
static void
|
||||
address_default_all(exarg_T *eap)
|
||||
{
|
||||
eap->line1 = 1;
|
||||
switch (eap->addr_type)
|
||||
{
|
||||
case ADDR_LINES:
|
||||
case ADDR_OTHER:
|
||||
eap->line2 = curbuf->b_ml.ml_line_count;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
{
|
||||
buf_T *buf = firstbuf;
|
||||
|
||||
while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL)
|
||||
buf = buf->b_next;
|
||||
eap->line1 = buf->b_fnum;
|
||||
buf = lastbuf;
|
||||
while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL)
|
||||
buf = buf->b_prev;
|
||||
eap->line2 = buf->b_fnum;
|
||||
}
|
||||
break;
|
||||
case ADDR_BUFFERS:
|
||||
eap->line1 = firstbuf->b_fnum;
|
||||
eap->line2 = lastbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
eap->line2 = LAST_WIN_NR;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
eap->line2 = LAST_TAB_NR;
|
||||
break;
|
||||
case ADDR_TABS_RELATIVE:
|
||||
eap->line2 = 1;
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
if (ARGCOUNT == 0)
|
||||
eap->line1 = eap->line2 = 0;
|
||||
else
|
||||
eap->line2 = ARGCOUNT;
|
||||
break;
|
||||
case ADDR_QUICKFIX_VALID:
|
||||
#ifdef FEAT_QUICKFIX
|
||||
eap->line2 = qf_get_valid_size(eap);
|
||||
if (eap->line2 == 0)
|
||||
eap->line2 = 1;
|
||||
#endif
|
||||
break;
|
||||
case ADDR_NONE:
|
||||
case ADDR_UNSIGNED:
|
||||
case ADDR_QUICKFIX:
|
||||
iemsg(_("INTERNAL: Cannot use EX_DFLALL with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get flags from an Ex command argument.
|
||||
*/
|
||||
|
||||
+2
-2
@@ -2243,7 +2243,7 @@ cs_release_csp(int i, int freefnpp)
|
||||
waitpid_errno = errno;
|
||||
if (pid != 0)
|
||||
break; // break unless the process is still running
|
||||
mch_delay(50L, FALSE); // sleep 50 ms
|
||||
mch_delay(50L, 0); // sleep 50 ms
|
||||
}
|
||||
# endif
|
||||
/*
|
||||
@@ -2278,7 +2278,7 @@ cs_release_csp(int i, int freefnpp)
|
||||
alive = FALSE; // cscope process no longer exists
|
||||
break;
|
||||
}
|
||||
mch_delay(50L, FALSE); // sleep 50ms
|
||||
mch_delay(50L, 0); // sleep 50 ms
|
||||
}
|
||||
}
|
||||
if (alive)
|
||||
|
||||
+3
-1
@@ -3656,8 +3656,10 @@ nv_ident(cmdarg_T *cap)
|
||||
{
|
||||
if (g_cmd)
|
||||
STRCPY(buf, "tj ");
|
||||
else if (cap->count0 == 0)
|
||||
STRCPY(buf, "ta ");
|
||||
else
|
||||
sprintf((char *)buf, "%ldta ", cap->count0);
|
||||
sprintf((char *)buf, ":%ldta ", cap->count0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -222,10 +222,10 @@ mch_avail_mem(int special)
|
||||
|
||||
/*
|
||||
* Waits a specified amount of time, or until input arrives if
|
||||
* ignoreinput is FALSE.
|
||||
* flags does not have MCH_DELAY_IGNOREINPUT.
|
||||
*/
|
||||
void
|
||||
mch_delay(long msec, int ignoreinput)
|
||||
mch_delay(long msec, int flags)
|
||||
{
|
||||
#ifndef LATTICE // SAS declares void Delay(ULONG)
|
||||
void Delay(long);
|
||||
@@ -233,7 +233,7 @@ mch_delay(long msec, int ignoreinput)
|
||||
|
||||
if (msec > 0)
|
||||
{
|
||||
if (ignoreinput)
|
||||
if (flags & MCH_DELAY_IGNOREINPUT)
|
||||
Delay(msec / 20L); // Delay works with 20 msec intervals
|
||||
else
|
||||
WaitForChar(raw_in, msec * 1000L);
|
||||
|
||||
+22
-13
@@ -577,15 +577,19 @@ mch_total_mem(int special UNUSED)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "flags": MCH_DELAY_IGNOREINPUT - don't read input
|
||||
* MCH_DELAY_SETTMODE - use settmode() even for short delays
|
||||
*/
|
||||
void
|
||||
mch_delay(long msec, int ignoreinput)
|
||||
mch_delay(long msec, int flags)
|
||||
{
|
||||
tmode_T old_tmode;
|
||||
#ifdef FEAT_MZSCHEME
|
||||
long total = msec; // remember original value
|
||||
#endif
|
||||
|
||||
if (ignoreinput)
|
||||
if (flags & MCH_DELAY_IGNOREINPUT)
|
||||
{
|
||||
// Go to cooked mode without echo, to allow SIGINT interrupting us
|
||||
// here. But we don't want QUIT to kill us (CTRL-\ used in a
|
||||
@@ -593,7 +597,8 @@ mch_delay(long msec, int ignoreinput)
|
||||
// Only do this if sleeping for more than half a second.
|
||||
in_mch_delay = TRUE;
|
||||
old_tmode = mch_cur_tmode;
|
||||
if (mch_cur_tmode == TMODE_RAW && msec > 500)
|
||||
if (mch_cur_tmode == TMODE_RAW
|
||||
&& (msec > 500 || (flags & MCH_DELAY_SETTMODE)))
|
||||
settmode(TMODE_SLEEP);
|
||||
|
||||
/*
|
||||
@@ -636,10 +641,8 @@ mch_delay(long msec, int ignoreinput)
|
||||
|
||||
tv.tv_sec = msec / 1000;
|
||||
tv.tv_usec = (msec % 1000) * 1000;
|
||||
/*
|
||||
* NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
|
||||
* a patch from Sun to fix this. Reported by Gunnar Pedersen.
|
||||
*/
|
||||
// NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
|
||||
// a patch from Sun to fix this. Reported by Gunnar Pedersen.
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
}
|
||||
# endif // HAVE_SELECT
|
||||
@@ -650,7 +653,7 @@ mch_delay(long msec, int ignoreinput)
|
||||
while (total > 0);
|
||||
#endif
|
||||
|
||||
if (msec > 500)
|
||||
if (msec > 500 || (flags & MCH_DELAY_SETTMODE))
|
||||
settmode(old_tmode);
|
||||
in_mch_delay = FALSE;
|
||||
}
|
||||
@@ -1284,7 +1287,7 @@ mch_suspend(void)
|
||||
long wait_time;
|
||||
|
||||
for (wait_time = 0; !sigcont_received && wait_time <= 3L; wait_time++)
|
||||
mch_delay(wait_time, FALSE);
|
||||
mch_delay(wait_time, 0);
|
||||
}
|
||||
# endif
|
||||
in_mch_suspend = FALSE;
|
||||
@@ -4176,7 +4179,7 @@ wait4pid(pid_t child, waitstatus *status)
|
||||
if (wait_pid == 0)
|
||||
{
|
||||
// Wait for 1 to 10 msec before trying again.
|
||||
mch_delay(delay_msec, TRUE);
|
||||
mch_delay(delay_msec, MCH_DELAY_IGNOREINPUT | MCH_DELAY_SETTMODE);
|
||||
if (++delay_msec > 10)
|
||||
delay_msec = 10;
|
||||
continue;
|
||||
@@ -5284,6 +5287,9 @@ finished:
|
||||
{
|
||||
long delay_msec = 1;
|
||||
|
||||
out_str(T_CTE); // possibly disables modifyOtherKeys, so that
|
||||
// the system can recognize CTRL-C
|
||||
|
||||
/*
|
||||
* Similar to the loop above, but only handle X events, no
|
||||
* I/O.
|
||||
@@ -5317,11 +5323,14 @@ finished:
|
||||
clip_update();
|
||||
|
||||
// Wait for 1 to 10 msec. 1 is faster but gives the child
|
||||
// less time.
|
||||
mch_delay(delay_msec, TRUE);
|
||||
// less time, gradually wait longer.
|
||||
mch_delay(delay_msec,
|
||||
MCH_DELAY_IGNOREINPUT | MCH_DELAY_SETTMODE);
|
||||
if (++delay_msec > 10)
|
||||
delay_msec = 10;
|
||||
}
|
||||
|
||||
out_str(T_CTI); // possibly enables modifyOtherKeys again
|
||||
}
|
||||
# endif
|
||||
|
||||
@@ -6732,7 +6741,7 @@ mch_expand_wildcards(
|
||||
// When running in the background, give it some time to create the temp
|
||||
// file, but don't wait for it to finish.
|
||||
if (ampersand)
|
||||
mch_delay(10L, TRUE);
|
||||
mch_delay(10L, MCH_DELAY_IGNOREINPUT);
|
||||
|
||||
extra_shell_arg = NULL; // cleanup
|
||||
show_shell_mess = TRUE;
|
||||
|
||||
+2
-2
@@ -6739,7 +6739,7 @@ notsgr:
|
||||
void
|
||||
mch_delay(
|
||||
long msec,
|
||||
int ignoreinput UNUSED)
|
||||
int flags UNUSED)
|
||||
{
|
||||
#if defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)
|
||||
Sleep((int)msec); // never wait for input
|
||||
@@ -6751,7 +6751,7 @@ mch_delay(
|
||||
return;
|
||||
}
|
||||
# endif
|
||||
if (ignoreinput)
|
||||
if (flags & MCH_DELAY_IGNOREINPUT)
|
||||
# ifdef FEAT_MZSCHEME
|
||||
if (mzthreads_allowed() && p_mzq > 0 && msec > p_mzq)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only);
|
||||
void undo_cmdmod(exarg_T *eap, int save_msg_scroll);
|
||||
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
|
||||
int checkforcmd(char_u **pp, char *cmd, int len);
|
||||
char_u *skip_option_env_lead(char_u *start);
|
||||
char_u *find_ex_command(exarg_T *eap, int *full, void *(*lookup)(char_u *, size_t, cctx_T *), cctx_T *cctx);
|
||||
int modifier_len(char_u *cmd);
|
||||
int cmd_exists(char_u *name);
|
||||
|
||||
@@ -5,7 +5,7 @@ void mch_write(char_u *p, int len);
|
||||
int mch_inchar(char_u *buf, int maxlen, long time, int tb_change_cnt);
|
||||
int mch_char_avail(void);
|
||||
long_u mch_avail_mem(int special);
|
||||
void mch_delay(long msec, int ignoreinput);
|
||||
void mch_delay(long msec, int flags);
|
||||
void mch_suspend(void);
|
||||
void mch_init(void);
|
||||
int mch_check_win(int argc, char **argv);
|
||||
|
||||
@@ -5,7 +5,7 @@ int mch_inchar(char_u *buf, int maxlen, long wtime, int tb_change_cnt);
|
||||
int mch_char_avail(void);
|
||||
int mch_check_messages(void);
|
||||
long_u mch_total_mem(int special);
|
||||
void mch_delay(long msec, int ignoreinput);
|
||||
void mch_delay(long msec, int flags);
|
||||
int mch_stackcheck(char *p);
|
||||
void mch_suspend(void);
|
||||
void mch_init(void);
|
||||
|
||||
@@ -53,7 +53,7 @@ int mch_signal_job(job_T *job, char_u *how);
|
||||
void mch_clear_job(job_T *job);
|
||||
void mch_set_normal_colors(void);
|
||||
void mch_write(char_u *s, int len);
|
||||
void mch_delay(long msec, int ignoreinput);
|
||||
void mch_delay(long msec, int flags);
|
||||
int mch_remove(char_u *name);
|
||||
void mch_breakcheck(int force);
|
||||
long_u mch_total_mem(int special);
|
||||
|
||||
+2
-1
@@ -465,7 +465,8 @@ screen_line(
|
||||
// double-wide character. Clear the left half to avoid it getting the popup
|
||||
// window background color.
|
||||
if (coloff > 0 && ScreenLines[off_to] == 0
|
||||
&& ScreenLinesUC[off_to - 1] != 0)
|
||||
&& ScreenLinesUC[off_to - 1] != 0
|
||||
&& (*mb_char2cells)(ScreenLinesUC[off_to - 1]) > 1)
|
||||
{
|
||||
ScreenLines[off_to - 1] = ' ';
|
||||
ScreenLinesUC[off_to - 1] = 0;
|
||||
|
||||
@@ -66,6 +66,7 @@ struct slang_S
|
||||
int sl_add; // TRUE if it's a .add file.
|
||||
|
||||
char_u *sl_fbyts; // case-folded word bytes
|
||||
long sl_fbyts_len; // length of sl_fbyts
|
||||
idx_T *sl_fidxs; // case-folded word indexes
|
||||
char_u *sl_kbyts; // keep-case word bytes
|
||||
idx_T *sl_kidxs; // keep-case word indexes
|
||||
|
||||
+11
-7
@@ -315,7 +315,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len);
|
||||
static int set_sofo(slang_T *lp, char_u *from, char_u *to);
|
||||
static void set_sal_first(slang_T *lp);
|
||||
static int *mb_str2wide(char_u *s);
|
||||
static int spell_read_tree(FILE *fd, char_u **bytsp, idx_T **idxsp, int prefixtree, int prefixcnt);
|
||||
static int spell_read_tree(FILE *fd, char_u **bytsp, long *bytsp_len, idx_T **idxsp, int prefixtree, int prefixcnt);
|
||||
static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx_T startidx, int prefixtree, int maxprefcondnr);
|
||||
static void set_spell_charflags(char_u *flags, int cnt, char_u *upp);
|
||||
static int set_spell_chartab(char_u *fol, char_u *low, char_u *upp);
|
||||
@@ -553,17 +553,18 @@ truncerr:
|
||||
}
|
||||
|
||||
// <LWORDTREE>
|
||||
res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fidxs, FALSE, 0);
|
||||
res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fbyts_len,
|
||||
&lp->sl_fidxs, FALSE, 0);
|
||||
if (res != 0)
|
||||
goto someerror;
|
||||
|
||||
// <KWORDTREE>
|
||||
res = spell_read_tree(fd, &lp->sl_kbyts, &lp->sl_kidxs, FALSE, 0);
|
||||
res = spell_read_tree(fd, &lp->sl_kbyts, NULL, &lp->sl_kidxs, FALSE, 0);
|
||||
if (res != 0)
|
||||
goto someerror;
|
||||
|
||||
// <PREFIXTREE>
|
||||
res = spell_read_tree(fd, &lp->sl_pbyts, &lp->sl_pidxs, TRUE,
|
||||
res = spell_read_tree(fd, &lp->sl_pbyts, NULL, &lp->sl_pidxs, TRUE,
|
||||
lp->sl_prefixcnt);
|
||||
if (res != 0)
|
||||
goto someerror;
|
||||
@@ -737,7 +738,7 @@ suggest_load_files(void)
|
||||
* <SUGWORDTREE>: <wordtree>
|
||||
* Read the trie with the soundfolded words.
|
||||
*/
|
||||
if (spell_read_tree(fd, &slang->sl_sbyts, &slang->sl_sidxs,
|
||||
if (spell_read_tree(fd, &slang->sl_sbyts, NULL, &slang->sl_sidxs,
|
||||
FALSE, 0) != 0)
|
||||
{
|
||||
someerror:
|
||||
@@ -1572,6 +1573,7 @@ mb_str2wide(char_u *s)
|
||||
spell_read_tree(
|
||||
FILE *fd,
|
||||
char_u **bytsp,
|
||||
long *bytsp_len,
|
||||
idx_T **idxsp,
|
||||
int prefixtree, // TRUE for the prefix tree
|
||||
int prefixcnt) // when "prefixtree" is TRUE: prefix count
|
||||
@@ -1596,6 +1598,8 @@ spell_read_tree(
|
||||
if (bp == NULL)
|
||||
return SP_OTHERERROR;
|
||||
*bytsp = bp;
|
||||
if (bytsp_len != NULL)
|
||||
*bytsp_len = len;
|
||||
|
||||
// Allocate the index array.
|
||||
ip = lalloc_clear(len * sizeof(int), TRUE);
|
||||
@@ -5609,8 +5613,8 @@ sug_filltree(spellinfo_T *spin, slang_T *slang)
|
||||
spin->si_blocks_cnt = 0;
|
||||
|
||||
// Skip over any other NUL bytes (same word with different
|
||||
// flags).
|
||||
while (byts[n + 1] == 0)
|
||||
// flags). But don't go over the end.
|
||||
while (n + 1 < slang->sl_fbyts_len && byts[n + 1] == 0)
|
||||
{
|
||||
++n;
|
||||
++curi[depth];
|
||||
|
||||
+1
-1
@@ -3604,7 +3604,7 @@ stoptermcap(void)
|
||||
{
|
||||
# ifdef UNIX
|
||||
// Give the terminal a chance to respond.
|
||||
mch_delay(100L, FALSE);
|
||||
mch_delay(100L, 0);
|
||||
# endif
|
||||
# ifdef TCIFLUSH
|
||||
// Discard data received but not read.
|
||||
|
||||
@@ -117,7 +117,7 @@ $(TEST_OUTFILES): $(DOSTMP)\$(*B).in
|
||||
# Limitation: Only works with the +eval feature.
|
||||
|
||||
newtests: newtestssilent
|
||||
@if exist messages (findstr "SKIPPED FAILED" messages > nul) && type messages
|
||||
@if exist messages type messages
|
||||
|
||||
newtestssilent: $(NEW_TESTS_RES)
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ $(DOSTMP)/%.in : %.in
|
||||
# Limitation: Only works with the +eval feature.
|
||||
|
||||
newtests: newtestssilent
|
||||
@if exist messages (findstr "SKIPPED FAILED" messages > nul) && type messages
|
||||
@if exist messages type messages
|
||||
|
||||
newtestssilent: $(NEW_TESTS_RES)
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ tinytests: $(SCRIPTS_TINY_OUT)
|
||||
RUN_VIMTEST = VIMRUNTIME=$(SCRIPTSOURCE) $(VALGRIND) $(VIMPROG) -f $(GUI_FLAG) -u unix.vim
|
||||
|
||||
newtests: newtestssilent
|
||||
@/bin/sh -c "if test -f messages && grep -q 'SKIPPED\|FAILED' messages; then cat messages; fi"
|
||||
@/bin/sh -c "if test -f messages; then cat messages; fi"
|
||||
|
||||
newtestssilent: $(NEW_TESTS_RES)
|
||||
|
||||
|
||||
@@ -135,6 +135,12 @@ func Test_string_concatenation()
|
||||
let a = 'a'
|
||||
let a..=b
|
||||
call assert_equal('ab', a)
|
||||
|
||||
if has('float')
|
||||
let a = 'A'
|
||||
let b = 1.234
|
||||
call assert_fails('echo a .. b', 'E806:')
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Test fix for issue #4507
|
||||
|
||||
@@ -513,6 +513,10 @@ func Test_strpart()
|
||||
|
||||
call assert_equal('lép', strpart('éléphant', 2, 4))
|
||||
call assert_equal('léphant', strpart('éléphant', 2))
|
||||
|
||||
call assert_equal('é', strpart('éléphant', 0, 1, 1))
|
||||
call assert_equal('ép', strpart('éléphant', 3, 2, v:true))
|
||||
call assert_equal('ó', strpart('cómposed', 1, 1, 1))
|
||||
endfunc
|
||||
|
||||
func Test_tolower()
|
||||
|
||||
@@ -410,6 +410,24 @@ func Test_sugfile_format_error()
|
||||
call assert_fails("let s = spellsuggest('abc')", 'E782:')
|
||||
set nospell spelllang&
|
||||
|
||||
" invalid suggest word count in SUGTABLE
|
||||
set encoding=utf-8
|
||||
call writefile(0z56494D7375670100000000000000440000000022, sugfile)
|
||||
set runtimepath=./Xtest
|
||||
set spelllang=Xtest
|
||||
set spell
|
||||
call assert_fails("let s = spellsuggest('abc')", 'E782:')
|
||||
set nospell spelllang&
|
||||
|
||||
" missing sugline in SUGTABLE
|
||||
set encoding=utf-8
|
||||
call writefile(0z56494D7375670100000000000000440000000000000005, sugfile)
|
||||
set runtimepath=./Xtest
|
||||
set spelllang=Xtest
|
||||
set spell
|
||||
call assert_fails("let s = spellsuggest('abc')", 'E782:')
|
||||
set nospell spelllang&
|
||||
|
||||
let &rtp = save_rtp
|
||||
call delete('Xtest', 'rf')
|
||||
endfunc
|
||||
@@ -510,6 +528,197 @@ func Test_mkspell()
|
||||
call assert_fails('mkspell en en_US abc_xyz', 'E755:')
|
||||
endfunc
|
||||
|
||||
" Tests for :mkspell with a .dic and .aff file
|
||||
func Test_aff_file_format_error()
|
||||
" FIXME: For some reason, the :mkspell command below doesn't fail on the
|
||||
" MS-Windows CI build. Disable this test on MS-Windows for now.
|
||||
CheckNotMSWindows
|
||||
|
||||
" No word count in .dic file
|
||||
call writefile([], 'Xtest.dic')
|
||||
call writefile([], 'Xtest.aff')
|
||||
call assert_fails('mkspell! Xtest.spl Xtest', 'E760:')
|
||||
|
||||
" create a .dic file for the tests below
|
||||
call writefile(['1', 'work'], 'Xtest.dic')
|
||||
|
||||
" Invalid encoding in .aff file
|
||||
call writefile(['# comment', 'SET Xinvalidencoding'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Conversion in Xtest.aff not supported: from xinvalidencoding', output)
|
||||
|
||||
" Invalid flag in .aff file
|
||||
call writefile(['FLAG xxx'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Invalid value for FLAG in Xtest.aff line 1: xxx', output)
|
||||
|
||||
" set FLAGS after using flag for an affix
|
||||
call writefile(['SFX L Y 1', 'SFX L 0 re [^x]', 'FLAG long'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('FLAG after using flags in Xtest.aff line 3: long', output)
|
||||
|
||||
" INFO in affix file
|
||||
let save_encoding = &encoding
|
||||
call mkdir('Xrtp/spell', 'p')
|
||||
call writefile(['1', 'work'], 'Xrtp/spell/Xtest.dic')
|
||||
call writefile(['NAME klingon', 'VERSION 1.4', 'AUTHOR Spock'],
|
||||
\ 'Xrtp/spell/Xtest.aff')
|
||||
silent mkspell! Xrtp/spell/Xtest.utf-8.spl Xrtp/spell/Xtest
|
||||
let save_rtp = &rtp
|
||||
set runtimepath=./Xrtp
|
||||
set spelllang=Xtest
|
||||
set spell
|
||||
let output = split(execute('spellinfo'), "\n")
|
||||
call assert_equal("NAME klingon", output[1])
|
||||
call assert_equal("VERSION 1.4", output[2])
|
||||
call assert_equal("AUTHOR Spock", output[3])
|
||||
let &rtp = save_rtp
|
||||
call delete('Xrtp', 'rf')
|
||||
set spell& spelllang& spellfile&
|
||||
%bw!
|
||||
" 'encoding' must be set again to clear the spell file in memory
|
||||
let &encoding = save_encoding
|
||||
|
||||
" COMPOUNDFORBIDFLAG flag after PFX in an affix file
|
||||
call writefile(['PFX L Y 1', 'PFX L 0 re x', 'COMPOUNDFLAG c', 'COMPOUNDFORBIDFLAG x'],
|
||||
\ 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in Xtest.aff line 4', output)
|
||||
|
||||
" COMPOUNDPERMITFLAG flag after PFX in an affix file
|
||||
call writefile(['PFX L Y 1', 'PFX L 0 re x', 'COMPOUNDPERMITFLAG c'],
|
||||
\ 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in Xtest.aff line 3', output)
|
||||
|
||||
" Wrong COMPOUNDRULES flag value in an affix file
|
||||
call writefile(['COMPOUNDRULES a'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Wrong COMPOUNDRULES value in Xtest.aff line 1: a', output)
|
||||
|
||||
" Wrong COMPOUNDWORDMAX flag value in an affix file
|
||||
call writefile(['COMPOUNDWORDMAX 0'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Wrong COMPOUNDWORDMAX value in Xtest.aff line 1: 0', output)
|
||||
|
||||
" Wrong COMPOUNDMIN flag value in an affix file
|
||||
call writefile(['COMPOUNDMIN 0'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Wrong COMPOUNDMIN value in Xtest.aff line 1: 0', output)
|
||||
|
||||
" Wrong COMPOUNDSYLMAX flag value in an affix file
|
||||
call writefile(['COMPOUNDSYLMAX 0'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Wrong COMPOUNDSYLMAX value in Xtest.aff line 1: 0', output)
|
||||
|
||||
" Wrong CHECKCOMPOUNDPATTERN flag value in an affix file
|
||||
call writefile(['CHECKCOMPOUNDPATTERN 0'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Wrong CHECKCOMPOUNDPATTERN value in Xtest.aff line 1: 0', output)
|
||||
|
||||
" Duplicate affix entry in an affix file
|
||||
call writefile(['PFX L Y 1', 'PFX L 0 re x', 'PFX L Y 1', 'PFX L 0 re x'],
|
||||
\ 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Duplicate affix in Xtest.aff line 3: L', output)
|
||||
|
||||
" Duplicate affix entry in an affix file
|
||||
call writefile(['PFX L Y 1', 'PFX L Y 1'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Unrecognized or duplicate item in Xtest.aff line 2: PFX', output)
|
||||
|
||||
" Different combining flags in an affix file
|
||||
call writefile(['PFX L Y 1', 'PFX L 0 re x', 'PFX L N 1'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Different combining flag in continued affix block in Xtest.aff line 3', output)
|
||||
|
||||
" Try to reuse a affix used for BAD flag
|
||||
call writefile(['BAD x', 'PFX x Y 1', 'PFX x 0 re x'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in Xtest.aff line 2: x', output)
|
||||
|
||||
" Trailing characters in an affix entry
|
||||
call writefile(['PFX L Y 1 Test', 'PFX L 0 re x'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Trailing text in Xtest.aff line 1: Test', output)
|
||||
|
||||
" Trailing characters in an affix entry
|
||||
call writefile(['PFX L Y 1', 'PFX L 0 re x Test'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Trailing text in Xtest.aff line 2: Test', output)
|
||||
|
||||
" Incorrect combine flag in an affix entry
|
||||
call writefile(['PFX L X 1', 'PFX L 0 re x'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Expected Y or N in Xtest.aff line 1: X', output)
|
||||
|
||||
" Invalid count for REP item
|
||||
call writefile(['REP a'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Expected REP(SAL) count in Xtest.aff line 1', output)
|
||||
|
||||
" Trailing characters in REP item
|
||||
call writefile(['REP 1', 'REP f ph test'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Trailing text in Xtest.aff line 2: test', output)
|
||||
|
||||
" Invalid count for MAP item
|
||||
call writefile(['MAP a'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Expected MAP count in Xtest.aff line 1', output)
|
||||
|
||||
" Duplicate character in a MAP item
|
||||
call writefile(['MAP 2', 'MAP xx', 'MAP yy'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Duplicate character in MAP in Xtest.aff line 2', output)
|
||||
|
||||
" Use COMPOUNDSYLMAX without SYLLABLE
|
||||
call writefile(['COMPOUNDSYLMAX 2'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('COMPOUNDSYLMAX used without SYLLABLE', output)
|
||||
|
||||
" Missing SOFOTO
|
||||
call writefile(['SOFOFROM abcdef'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Missing SOFOTO line in Xtest.aff', output)
|
||||
|
||||
" Length of SOFOFROM and SOFOTO differ
|
||||
call writefile(['SOFOFROM abcde', 'SOFOTO ABCD'], 'Xtest.aff')
|
||||
call assert_fails('mkspell! Xtest.spl Xtest', 'E759:')
|
||||
|
||||
" Both SAL and SOFOFROM/SOFOTO items
|
||||
call writefile(['SOFOFROM abcd', 'SOFOTO ABCD', 'SAL CIA X'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Both SAL and SOFO lines in Xtest.aff', output)
|
||||
|
||||
" use an alphabet flag when FLAG is num
|
||||
call writefile(['FLAG num', 'SFX L Y 1', 'SFX L 0 re [^x]'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Flag is not a number in Xtest.aff line 2: L', output)
|
||||
|
||||
" use number and alphabet flag when FLAG is num
|
||||
call writefile(['FLAG num', 'SFX 4f Y 1', 'SFX 4f 0 re [^x]'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Affix name too long in Xtest.aff line 2: 4f', output)
|
||||
|
||||
" use a single character flag when FLAG is long
|
||||
call writefile(['FLAG long', 'SFX L Y 1', 'SFX L 0 re [^x]'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('Illegal flag in Xtest.aff line 2: L', output)
|
||||
|
||||
" duplicate word in the .dic file
|
||||
call writefile(['2', 'good', 'good', 'good'], 'Xtest.dic')
|
||||
call writefile(['NAME vim'], 'Xtest.aff')
|
||||
let output = execute('mkspell! Xtest.spl Xtest')
|
||||
call assert_match('First duplicate word in Xtest.dic line 3: good', output)
|
||||
call assert_match('2 duplicate word(s) in Xtest.dic', output)
|
||||
|
||||
call delete('Xtest.dic')
|
||||
call delete('Xtest.aff')
|
||||
call delete('Xtest.spl')
|
||||
call delete('Xtest.sug')
|
||||
endfunc
|
||||
|
||||
func Test_spell_add_word()
|
||||
set spellfile=
|
||||
call assert_fails('spellgood abc', 'E764:')
|
||||
@@ -524,4 +733,36 @@ func Test_spell_add_word()
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" When 'spellfile' is not set, adding a new good word will automatically set
|
||||
" the 'spellfile'
|
||||
func Test_init_spellfile()
|
||||
let save_rtp = &rtp
|
||||
let save_encoding = &encoding
|
||||
call mkdir('Xrtp/spell', 'p')
|
||||
call writefile(['vim'], 'Xrtp/spell/Xtest.dic')
|
||||
silent mkspell Xrtp/spell/Xtest.utf-8.spl Xrtp/spell/Xtest.dic
|
||||
set runtimepath=./Xrtp
|
||||
set spelllang=Xtest
|
||||
set spell
|
||||
silent spellgood abc
|
||||
call assert_equal('./Xrtp/spell/Xtest.utf-8.add', &spellfile)
|
||||
call assert_equal(['abc'], readfile('Xrtp/spell/Xtest.utf-8.add'))
|
||||
call assert_true(filereadable('Xrtp/spell/Xtest.utf-8.spl'))
|
||||
set spell& spelllang& spellfile&
|
||||
call delete('Xrtp', 'rf')
|
||||
let &encoding = save_encoding
|
||||
let &rtp = save_rtp
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" Test for the 'mkspellmem' option
|
||||
func Test_mkspellmem_opt()
|
||||
call assert_fails('set mkspellmem=1000', 'E474:')
|
||||
call assert_fails('set mkspellmem=1000,', 'E474:')
|
||||
call assert_fails('set mkspellmem=1000,50', 'E474:')
|
||||
call assert_fails('set mkspellmem=1000,50,', 'E474:')
|
||||
call assert_fails('set mkspellmem=1000,50,10,', 'E474:')
|
||||
call assert_fails('set mkspellmem=1000,50,0', 'E474:')
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -295,5 +295,25 @@ def Test_map_command()
|
||||
CheckScriptSuccess(['vim9script'] + lines)
|
||||
enddef
|
||||
|
||||
def Test_normal_command()
|
||||
new
|
||||
setline(1, 'doesnotexist')
|
||||
let caught = 0
|
||||
try
|
||||
exe "norm! \<C-]>"
|
||||
catch /E433/
|
||||
caught = 2
|
||||
endtry
|
||||
assert_equal(2, caught)
|
||||
|
||||
try
|
||||
exe "norm! 3\<C-]>"
|
||||
catch /E433/
|
||||
caught = 3
|
||||
endtry
|
||||
assert_equal(3, caught)
|
||||
bwipe!
|
||||
enddef
|
||||
|
||||
|
||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||
|
||||
@@ -43,6 +43,9 @@ def Test_expr1()
|
||||
var = 0
|
||||
assert_equal('two', var ? 'one' : 'two')
|
||||
|
||||
# with constant condition expression is not evaluated
|
||||
assert_equal('one', 1 ? 'one' : xxx)
|
||||
|
||||
let Some: func = function('len')
|
||||
let Other: func = function('winnr')
|
||||
let Res: func = g:atrue ? Some : Other
|
||||
@@ -139,7 +142,6 @@ enddef
|
||||
|
||||
func Test_expr1_fails()
|
||||
call CheckDefFailure(["let x = 1 ? 'one'"], "Missing ':' after '?'", 1)
|
||||
call CheckDefFailure(["let x = 1 ? 'one' : xxx"], "E1001:", 1)
|
||||
|
||||
let msg = "white space required before and after '?'"
|
||||
call CheckDefFailure(["let x = 1? 'one' : 'two'"], msg, 1)
|
||||
@@ -1668,6 +1670,17 @@ def Test_expr7_lambda_vim9script()
|
||||
CheckScriptSuccess(lines)
|
||||
enddef
|
||||
|
||||
def Test_epxr7_funcref()
|
||||
let lines =<< trim END
|
||||
def RetNumber(): number
|
||||
return 123
|
||||
enddef
|
||||
let FuncRef = RetNumber
|
||||
assert_equal(123, FuncRef())
|
||||
END
|
||||
CheckDefAndScriptSuccess(lines)
|
||||
enddef
|
||||
|
||||
def Test_expr7_dict()
|
||||
# dictionary
|
||||
assert_equal(g:dict_empty, {})
|
||||
|
||||
@@ -15,6 +15,18 @@ def Test_range_only()
|
||||
setline(1, ['blah', 'Blah'])
|
||||
:/Blah/
|
||||
assert_equal(2, getcurpos()[1])
|
||||
bwipe!
|
||||
|
||||
# without range commands use current line
|
||||
new
|
||||
setline(1, ['one', 'two', 'three'])
|
||||
:2
|
||||
print
|
||||
assert_equal('two', Screenline(&lines))
|
||||
:3
|
||||
list
|
||||
assert_equal('three$', Screenline(&lines))
|
||||
bwipe!
|
||||
enddef
|
||||
|
||||
let s:appendToMe = 'xxx'
|
||||
@@ -110,12 +122,21 @@ def Test_assignment()
|
||||
endif
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
&ts = 6
|
||||
&ts += 3
|
||||
assert_equal(9, &ts)
|
||||
|
||||
&l:ts = 6
|
||||
assert_equal(6, &ts)
|
||||
&l:ts += 2
|
||||
assert_equal(8, &ts)
|
||||
|
||||
&g:ts = 6
|
||||
assert_equal(6, &g:ts)
|
||||
&g:ts += 2
|
||||
assert_equal(8, &g:ts)
|
||||
END
|
||||
CheckScriptSuccess(lines)
|
||||
CheckDefAndScriptSuccess(lines)
|
||||
|
||||
CheckDefFailure(['¬ex += 3'], 'E113:')
|
||||
CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
|
||||
@@ -163,19 +184,15 @@ def Test_assignment()
|
||||
call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
|
||||
call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
|
||||
|
||||
@a = 'areg'
|
||||
@a ..= 'add'
|
||||
assert_equal('aregadd', @a)
|
||||
call CheckDefFailure(['@a += "more"'], 'E1051:')
|
||||
call CheckDefFailure(['@a += 123'], 'E1012:')
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
@c = 'areg'
|
||||
@c ..= 'add'
|
||||
assert_equal('aregadd', @c)
|
||||
END
|
||||
call CheckScriptSuccess(lines)
|
||||
CheckDefAndScriptSuccess(lines)
|
||||
|
||||
call CheckDefFailure(['@a += "more"'], 'E1051:')
|
||||
call CheckDefFailure(['@a += 123'], 'E1012:')
|
||||
|
||||
v:errmsg = 'none'
|
||||
v:errmsg ..= 'again'
|
||||
@@ -608,6 +625,13 @@ def Test_unlet()
|
||||
assert_false(exists('g:somevar'))
|
||||
unlet! g:somevar
|
||||
|
||||
# also works for script-local variable in legacy Vim script
|
||||
s:somevar = 'legacy'
|
||||
assert_true(exists('s:somevar'))
|
||||
unlet s:somevar
|
||||
assert_false(exists('s:somevar'))
|
||||
unlet! s:somevar
|
||||
|
||||
call CheckScriptFailure([
|
||||
'vim9script',
|
||||
'let svar = 123',
|
||||
@@ -1660,8 +1684,9 @@ def Test_vim9script_funcref()
|
||||
delete('Xscript.vim')
|
||||
enddef
|
||||
|
||||
" Check that when searcing for "FilterFunc" it doesn't find the import in the
|
||||
" script where FastFilter() is called from.
|
||||
" Check that when searching for "FilterFunc" it finds the import in the
|
||||
" script where FastFilter() is called from, both as a string and as a direct
|
||||
" function reference.
|
||||
def Test_vim9script_funcref_other_script()
|
||||
let filterLines =<< trim END
|
||||
vim9script
|
||||
@@ -1671,22 +1696,26 @@ def Test_vim9script_funcref_other_script()
|
||||
export def FastFilter(): list<number>
|
||||
return range(10)->filter('FilterFunc')
|
||||
enddef
|
||||
export def FastFilterDirect(): list<number>
|
||||
return range(10)->filter(FilterFunc)
|
||||
enddef
|
||||
END
|
||||
writefile(filterLines, 'Xfilter.vim')
|
||||
|
||||
let lines =<< trim END
|
||||
vim9script
|
||||
import {FilterFunc, FastFilter} from './Xfilter.vim'
|
||||
import {FilterFunc, FastFilter, FastFilterDirect} from './Xfilter.vim'
|
||||
def Test()
|
||||
let x: list<number> = FastFilter()
|
||||
enddef
|
||||
Test()
|
||||
def TestDirect()
|
||||
let x: list<number> = FastFilterDirect()
|
||||
enddef
|
||||
TestDirect()
|
||||
END
|
||||
writefile(lines, 'Ximport.vim')
|
||||
assert_fails('source Ximport.vim', 'E121:')
|
||||
|
||||
CheckScriptSuccess(lines)
|
||||
delete('Xfilter.vim')
|
||||
delete('Ximport.vim')
|
||||
enddef
|
||||
|
||||
def Test_vim9script_reload_delfunc()
|
||||
@@ -2093,6 +2122,14 @@ def Test_if_const_expr()
|
||||
res = true
|
||||
endif
|
||||
assert_equal(false, res)
|
||||
|
||||
# with constant "false" expression may be invalid so long as the syntax is OK
|
||||
if false | eval 0 | endif
|
||||
if false | eval burp + 234 | endif
|
||||
if false | echo burp 234 'asd' | endif
|
||||
if false
|
||||
burp
|
||||
endif
|
||||
enddef
|
||||
|
||||
def Test_if_const_expr_fails()
|
||||
@@ -2152,8 +2189,9 @@ def Test_execute_cmd()
|
||||
echomsg [1, 2, 3] #{a: 1, b: 2}
|
||||
assert_match('^\[1, 2, 3\] {''a'': 1, ''b'': 2}$', Screenline(&lines))
|
||||
|
||||
call CheckDefFailure(['execute xxx'], 'E1001:')
|
||||
call CheckDefFailure(['execute "cmd"# comment'], 'E488:')
|
||||
call CheckDefFailure(['execute xxx'], 'E1001:', 1)
|
||||
call CheckDefExecFailure(['execute "tabnext " .. 8'], 'E475:', 1)
|
||||
call CheckDefFailure(['execute "cmd"# comment'], 'E488:', 1)
|
||||
enddef
|
||||
|
||||
def Test_execute_cmd_vimscript()
|
||||
|
||||
@@ -41,6 +41,11 @@ def CheckScriptSuccess(lines: list<string>)
|
||||
delete('Xdef')
|
||||
enddef
|
||||
|
||||
def CheckDefAndScriptSuccess(lines: list<string>)
|
||||
CheckDefSuccess(lines)
|
||||
CheckScriptSuccess(['vim9script'] + lines)
|
||||
enddef
|
||||
|
||||
" Check that a command fails both when used in a :def function and when used
|
||||
" in Vim9 script.
|
||||
def CheckScriptAndDefFailure(lines: list<string>, error: string, lnum = -3)
|
||||
|
||||
@@ -548,7 +548,7 @@ ui_delay(long msec_arg, int ignoreinput)
|
||||
if (gui.in_use)
|
||||
gui_macvim_force_flush();
|
||||
#endif
|
||||
mch_delay(msec, ignoreinput);
|
||||
mch_delay(msec, ignoreinput ? MCH_DELAY_IGNOREINPUT : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -769,6 +769,44 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1531,
|
||||
/**/
|
||||
1530,
|
||||
/**/
|
||||
1529,
|
||||
/**/
|
||||
1528,
|
||||
/**/
|
||||
1527,
|
||||
/**/
|
||||
1526,
|
||||
/**/
|
||||
1525,
|
||||
/**/
|
||||
1524,
|
||||
/**/
|
||||
1523,
|
||||
/**/
|
||||
1522,
|
||||
/**/
|
||||
1521,
|
||||
/**/
|
||||
1520,
|
||||
/**/
|
||||
1519,
|
||||
/**/
|
||||
1518,
|
||||
/**/
|
||||
1517,
|
||||
/**/
|
||||
1516,
|
||||
/**/
|
||||
1515,
|
||||
/**/
|
||||
1514,
|
||||
/**/
|
||||
1513,
|
||||
/**/
|
||||
1512,
|
||||
/**/
|
||||
|
||||
@@ -2679,4 +2679,8 @@ long elapsed(DWORD start_tick);
|
||||
#define READDIR_SORT_IC 2 // sort ignoring case (strcasecmp)
|
||||
#define READDIR_SORT_COLLATE 3 // sort according to collation (strcoll)
|
||||
|
||||
// Flags for mch_delay.
|
||||
#define MCH_DELAY_IGNOREINPUT 1
|
||||
#define MCH_DELAY_SETTMODE 2
|
||||
|
||||
#endif // VIM__H
|
||||
|
||||
+55
-30
@@ -258,6 +258,15 @@ lookup_arg(
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returnd TRUE if the script context is Vim9 script.
|
||||
*/
|
||||
static int
|
||||
script_is_vim9()
|
||||
{
|
||||
return SCRIPT_ITEM(current_sctx.sc_sid)->sn_version == SCRIPT_VERSION_VIM9;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a variable in the current script.
|
||||
* If "vim9script" is TRUE the script must be Vim9 script. Used for "var"
|
||||
@@ -271,8 +280,7 @@ lookup_script(char_u *name, size_t len, int vim9script)
|
||||
hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
|
||||
dictitem_T *di;
|
||||
|
||||
if (vim9script && SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
|
||||
!= SCRIPT_VERSION_VIM9)
|
||||
if (vim9script && !script_is_vim9())
|
||||
return FAIL;
|
||||
cc = name[len];
|
||||
name[len] = NUL;
|
||||
@@ -4006,6 +4014,13 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
int ppconst_used = ppconst->pp_used;
|
||||
char_u *next;
|
||||
|
||||
// Ignore all kinds of errors when not producing code.
|
||||
if (cctx->ctx_skip == SKIP_YES)
|
||||
{
|
||||
skip_expr(arg);
|
||||
return OK;
|
||||
}
|
||||
|
||||
// Evaluate the first expression.
|
||||
if (compile_expr2(arg, cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
@@ -4256,7 +4271,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
||||
ufunc = def_function(eap, lambda_name);
|
||||
|
||||
if (ufunc == NULL)
|
||||
return NULL;
|
||||
return eap->skip ? (char_u *)"" : NULL;
|
||||
if (ufunc->uf_def_status == UF_TO_BE_COMPILED
|
||||
&& compile_def_function(ufunc, TRUE, cctx) == FAIL)
|
||||
return NULL;
|
||||
@@ -4542,8 +4557,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
p = var_start + 2;
|
||||
else
|
||||
{
|
||||
p = (*var_start == '&' || *var_start == '$')
|
||||
? var_start + 1 : var_start;
|
||||
// skip over the leading "&", "&l:", "&g:" and "$"
|
||||
p = skip_option_env_lead(var_start);
|
||||
p = to_name_end(p, TRUE);
|
||||
}
|
||||
|
||||
@@ -4587,8 +4602,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
}
|
||||
cc = *p;
|
||||
*p = NUL;
|
||||
opt_type = get_option_value(var_start + 1, &numval,
|
||||
NULL, opt_flags);
|
||||
opt_type = get_option_value(skip_option_env_lead(var_start),
|
||||
&numval, NULL, opt_flags);
|
||||
*p = cc;
|
||||
if (opt_type == -3)
|
||||
{
|
||||
@@ -5123,7 +5138,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
switch (dest)
|
||||
{
|
||||
case dest_option:
|
||||
generate_STOREOPT(cctx, name + 1, opt_flags);
|
||||
generate_STOREOPT(cctx, skip_option_env_lead(name),
|
||||
opt_flags);
|
||||
break;
|
||||
case dest_global:
|
||||
// include g: with the name, easier to execute that way
|
||||
@@ -5234,6 +5250,9 @@ check_vim9_unlet(char_u *name)
|
||||
{
|
||||
if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
|
||||
{
|
||||
// "unlet s:var" is allowed in legacy script.
|
||||
if (*name == 's' && !script_is_vim9())
|
||||
return OK;
|
||||
semsg(_(e_cannot_unlet_str), name);
|
||||
return FAIL;
|
||||
}
|
||||
@@ -5500,6 +5519,7 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
||||
isn_T *isn;
|
||||
scope_T *scope = cctx->ctx_scope;
|
||||
ppconst_T ppconst;
|
||||
skip_T save_skip = cctx->ctx_skip;
|
||||
|
||||
if (scope == NULL || scope->se_type != IF_SCOPE)
|
||||
{
|
||||
@@ -5522,11 +5542,14 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
||||
|
||||
// compile "expr"; if we know it evaluates to FALSE skip the block
|
||||
CLEAR_FIELD(ppconst);
|
||||
if (cctx->ctx_skip == SKIP_YES)
|
||||
cctx->ctx_skip = SKIP_UNKNOWN;
|
||||
if (compile_expr1(&p, cctx, &ppconst) == FAIL)
|
||||
{
|
||||
clear_ppconst(&ppconst);
|
||||
return NULL;
|
||||
}
|
||||
cctx->ctx_skip = save_skip;
|
||||
if (scope->se_skip_save == SKIP_YES)
|
||||
clear_ppconst(&ppconst);
|
||||
else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
|
||||
@@ -6712,17 +6735,8 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
|
||||
p = skipwhite(p);
|
||||
|
||||
if (cctx.ctx_skip == SKIP_YES
|
||||
&& ea.cmdidx != CMD_if
|
||||
if (cctx.ctx_had_return
|
||||
&& ea.cmdidx != CMD_elseif
|
||||
&& ea.cmdidx != CMD_else
|
||||
&& ea.cmdidx != CMD_endif)
|
||||
{
|
||||
line = (char_u *)"";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ea.cmdidx != CMD_elseif
|
||||
&& ea.cmdidx != CMD_else
|
||||
&& ea.cmdidx != CMD_endif
|
||||
&& ea.cmdidx != CMD_endfor
|
||||
@@ -6731,11 +6745,8 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
&& ea.cmdidx != CMD_finally
|
||||
&& ea.cmdidx != CMD_endtry)
|
||||
{
|
||||
if (cctx.ctx_had_return)
|
||||
{
|
||||
emsg(_(e_unreachable_code_after_return));
|
||||
goto erret;
|
||||
}
|
||||
emsg(_(e_unreachable_code_after_return));
|
||||
goto erret;
|
||||
}
|
||||
|
||||
switch (ea.cmdidx)
|
||||
@@ -6833,7 +6844,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
if (compile_expr0(&p, &cctx) == FAIL)
|
||||
goto erret;
|
||||
|
||||
// drop the return value
|
||||
// drop the result
|
||||
generate_instr_drop(&cctx, ISN_DROP, 1);
|
||||
|
||||
line = skipwhite(p);
|
||||
@@ -6847,7 +6858,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
line = compile_mult_expr(p, ea.cmdidx, &cctx);
|
||||
break;
|
||||
|
||||
// TODO: other commands with an expression argument
|
||||
// TODO: any other commands with an expression argument?
|
||||
|
||||
case CMD_append:
|
||||
case CMD_change:
|
||||
@@ -6858,13 +6869,27 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
||||
goto erret;
|
||||
|
||||
case CMD_SIZE:
|
||||
semsg(_(e_invalid_command_str), ea.cmd);
|
||||
goto erret;
|
||||
if (cctx.ctx_skip != SKIP_YES)
|
||||
{
|
||||
semsg(_(e_invalid_command_str), ea.cmd);
|
||||
goto erret;
|
||||
}
|
||||
// We don't check for a next command here.
|
||||
line = (char_u *)"";
|
||||
break;
|
||||
|
||||
default:
|
||||
// Not recognized, execute with do_cmdline_cmd().
|
||||
ea.arg = p;
|
||||
line = compile_exec(line, &ea, &cctx);
|
||||
if (cctx.ctx_skip == SKIP_YES)
|
||||
{
|
||||
// We don't check for a next command here.
|
||||
line = (char_u *)"";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not recognized, execute with do_cmdline_cmd().
|
||||
ea.arg = p;
|
||||
line = compile_exec(line, &ea, &cctx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
nextline:
|
||||
|
||||
@@ -1062,7 +1062,10 @@ call_def_function(
|
||||
if (ga.ga_data != NULL)
|
||||
{
|
||||
if (iptr->isn_type == ISN_EXECUTE)
|
||||
{
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
do_cmdline_cmd((char_u *)ga.ga_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_sb_eol();
|
||||
|
||||
Reference in New Issue
Block a user