Skip to content

Commit 921101e

Browse files
authored
Merge pull request neovim#20774 from zeertzjq/vim-8.2.4679
vim-patch:8.2.{1506,1600,1624,1626,1751,2606,4679}
2 parents 1bcddd5 + 3c0651f commit 921101e

12 files changed

+137
-37
lines changed

runtime/doc/builtin.txt

+33-5
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ exists({expr}) Number |TRUE| if {expr} exists
134134
exp({expr}) Float exponential of {expr}
135135
expand({expr} [, {nosuf} [, {list}]])
136136
any expand special keywords in {expr}
137-
expandcmd({expr}) String expand {expr} like with `:edit`
137+
expandcmd({string} [, {options}])
138+
String expand {string} like with `:edit`
138139
extend({expr1}, {expr2} [, {expr3}])
139140
List/Dict insert items of {expr2} into {expr1}
140141
feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer
@@ -466,10 +467,11 @@ str2list({expr} [, {utf8}]) List convert each character of {expr} to
466467
ASCII/UTF-8 value
467468
str2nr({expr} [, {base} [, {quoted}]])
468469
Number convert String to Number
470+
strcharlen({expr}) Number character length of the String {expr}
469471
strcharpart({str}, {start} [, {len}])
470472
String {len} characters of {str} at
471473
character {start}
472-
strchars({expr} [, {skipcc}]) Number character length of the String {expr}
474+
strchars({expr} [, {skipcc}]) Number character count of the String {expr}
473475
strdisplaywidth({expr} [, {col}]) Number display length of the String {expr}
474476
strftime({format} [, {time}]) String format time with a specified format
475477
strgetchar({str}, {index}) Number get char {index} from {str}
@@ -2043,18 +2045,27 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
20432045
Can also be used as a |method|: >
20442046
Getpattern()->expand()
20452047
2046-
expandcmd({string}) *expandcmd()*
2048+
expandcmd({string} [, {options}]) *expandcmd()*
20472049
Expand special items in String {string} like what is done for
20482050
an Ex command such as `:edit`. This expands special keywords,
20492051
like with |expand()|, and environment variables, anywhere in
20502052
{string}. "~user" and "~/path" are only expanded at the
20512053
start.
2054+
2055+
The following items are supported in the {options} Dict
2056+
argument:
2057+
errmsg If set to TRUE, error messages are displayed
2058+
if an error is encountered during expansion.
2059+
By default, error messages are not displayed.
2060+
20522061
Returns the expanded string. If an error is encountered
20532062
during expansion, the unmodified {string} is returned.
2063+
20542064
Example: >
20552065
:echo expandcmd('make %<.o')
2056-
< make /path/runtime/doc/builtin.o ~
2057-
2066+
make /path/runtime/doc/builtin.o
2067+
:echo expandcmd('make %<.o', {'errmsg': v:true})
2068+
<
20582069
Can also be used as a |method|: >
20592070
GetCommand()->expandcmd()
20602071
<
@@ -7836,6 +7847,21 @@ str2nr({string} [, {base}]) *str2nr()*
78367847
Can also be used as a |method|: >
78377848
GetText()->str2nr()
78387849
7850+
7851+
strcharlen({string}) *strcharlen()*
7852+
The result is a Number, which is the number of characters
7853+
in String {string}. Composing characters are ignored.
7854+
|strchars()| can count the number of characters, counting
7855+
composing characters separately.
7856+
7857+
Returns 0 if {string} is empty or on error.
7858+
7859+
Also see |strlen()|, |strdisplaywidth()| and |strwidth()|.
7860+
7861+
Can also be used as a |method|: >
7862+
GetText()->strcharlen()
7863+
7864+
78397865
strcharpart({src}, {start} [, {len}]) *strcharpart()*
78407866
Like |strpart()| but using character index and length instead
78417867
of byte index and length. Composing characters are counted
@@ -7850,12 +7876,14 @@ strcharpart({src}, {start} [, {len}]) *strcharpart()*
78507876
Can also be used as a |method|: >
78517877
GetText()->strcharpart(5)
78527878
7879+
78537880
strchars({string} [, {skipcc}]) *strchars()*
78547881
The result is a Number, which is the number of characters
78557882
in String {string}.
78567883
When {skipcc} is omitted or zero, composing characters are
78577884
counted separately.
78587885
When {skipcc} set to 1, Composing characters are ignored.
7886+
|strcharlen()| always does this.
78597887

78607888
Returns zero on error.
78617889

runtime/doc/usr_41.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,8 @@ String manipulation: *string-functions*
619619
stridx() first index of a short string in a long string
620620
strridx() last index of a short string in a long string
621621
strlen() length of a string in bytes
622-
strchars() length of a string in characters
622+
strcharlen() length of a string in characters
623+
strchars() number of characters in a string
623624
strwidth() size of string when displayed
624625
strdisplaywidth() size of string when displayed, deals with tabs
625626
setcellwidths() set character cell width overrides

src/nvim/eval.lua

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ return {
118118
exists={args=1, base=1},
119119
exp={args=1, base=1, float_func="exp"},
120120
expand={args={1, 3}, base=1},
121-
expandcmd={args=1, base=1},
121+
expandcmd={args={1, 2}, base=1},
122122
extend={args={2, 3}, base=1},
123123
feedkeys={args={1, 2}, base=1},
124124
file_readable={args=1, base=1, func='f_filereadable'}, -- obsolete
@@ -376,6 +376,7 @@ return {
376376
str2float={args=1, base=1},
377377
str2list={args={1, 2}, base=1},
378378
str2nr={args={1, 3}, base=1},
379+
strcharlen={args=1, base=1},
379380
strcharpart={args={2, 3}, base=1},
380381
strchars={args={1, 2}, base=1},
381382
strdisplaywidth={args={1, 2}, base=1},

src/nvim/eval/funcs.c

+47-19
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ PRAGMA_DIAG_POP
112112
static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob");
113113
static char *e_invalwindow = N_("E957: Invalid window number");
114114
static char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value");
115+
static char e_using_number_as_bool_nr[]
116+
= N_("E1023: Using a Number as a Bool: %d");
115117
static char e_cannot_resize_window_in_another_tab_page[]
116118
= N_("E1308: Cannot resize a window in another tab page");
117119

@@ -906,7 +908,7 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
906908
countcc = (int)tv_get_number(&argvars[2]);
907909
}
908910
if (countcc < 0 || countcc > 1) {
909-
emsg(_(e_invarg));
911+
semsg(_(e_using_number_as_bool_nr), countcc);
910912
return;
911913
}
912914

@@ -1358,10 +1360,10 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
13581360
int noref = 0;
13591361

13601362
if (argvars[1].v_type != VAR_UNKNOWN) {
1361-
noref = (int)tv_get_number_chk(&argvars[1], NULL);
1363+
noref = (int)tv_get_bool_chk(&argvars[1], NULL);
13621364
}
13631365
if (noref < 0 || noref > 1) {
1364-
emsg(_(e_invarg));
1366+
semsg(_(e_using_number_as_bool_nr), noref);
13651367
} else {
13661368
var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0
13671369
? get_copyID()
@@ -2056,6 +2058,12 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
20562058
static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
20572059
{
20582060
char *errormsg = NULL;
2061+
bool emsgoff = true;
2062+
2063+
if (argvars[1].v_type == VAR_DICT
2064+
&& tv_dict_get_bool(argvars[1].vval.v_dict, "errmsg", kBoolVarFalse)) {
2065+
emsgoff = false;
2066+
}
20592067

20602068
rettv->v_type = VAR_STRING;
20612069
char *cmdstr = xstrdup(tv_get_string(&argvars[0]));
@@ -2069,9 +2077,17 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
20692077
};
20702078
eap.argt |= EX_NOSPC;
20712079

2072-
emsg_off++;
2073-
expand_filename(&eap, &cmdstr, &errormsg);
2074-
emsg_off--;
2080+
if (emsgoff) {
2081+
emsg_off++;
2082+
}
2083+
if (expand_filename(&eap, &cmdstr, &errormsg) == FAIL) {
2084+
if (!emsgoff && errormsg != NULL && *errormsg != NUL) {
2085+
emsg(errormsg);
2086+
}
2087+
}
2088+
if (emsgoff) {
2089+
emsg_off--;
2090+
}
20752091

20762092
rettv->vval.v_string = cmdstr;
20772093
}
@@ -8160,7 +8176,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
81608176
typeerr = true;
81618177
}
81628178
if (argvars[2].v_type != VAR_UNKNOWN) {
8163-
keepempty = (bool)tv_get_number_chk(&argvars[2], &typeerr);
8179+
keepempty = (bool)tv_get_bool_chk(&argvars[2], &typeerr);
81648180
}
81658181
}
81668182
if (pat == NULL || *pat == NUL) {
@@ -8290,7 +8306,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
82908306
emsg(_(e_invarg));
82918307
return;
82928308
}
8293-
if (argvars[2].v_type != VAR_UNKNOWN && tv_get_number(&argvars[2])) {
8309+
if (argvars[2].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[2])) {
82948310
what |= STR2NR_QUOTE;
82958311
}
82968312
}
@@ -8445,26 +8461,38 @@ static void f_strlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
84458461
rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0]));
84468462
}
84478463

8448-
/// "strchars()" function
8449-
static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
8464+
static void strchar_common(typval_T *argvars, typval_T *rettv, bool skipcc)
84508465
{
84518466
const char *s = tv_get_string(&argvars[0]);
8452-
int skipcc = 0;
84538467
varnumber_T len = 0;
84548468
int (*func_mb_ptr2char_adv)(const char_u **pp);
84558469

8470+
func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
8471+
while (*s != NUL) {
8472+
func_mb_ptr2char_adv((const char_u **)&s);
8473+
len++;
8474+
}
8475+
rettv->vval.v_number = len;
8476+
}
8477+
8478+
/// "strcharlen()" function
8479+
static void f_strcharlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
8480+
{
8481+
strchar_common(argvars, rettv, true);
8482+
}
8483+
8484+
/// "strchars()" function
8485+
static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
8486+
{
8487+
int skipcc = false;
8488+
84568489
if (argvars[1].v_type != VAR_UNKNOWN) {
8457-
skipcc = (int)tv_get_number_chk(&argvars[1], NULL);
8490+
skipcc = (int)tv_get_bool(&argvars[1]);
84588491
}
84598492
if (skipcc < 0 || skipcc > 1) {
8460-
emsg(_(e_invarg));
8493+
semsg(_(e_using_number_as_bool_nr), skipcc);
84618494
} else {
8462-
func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
8463-
while (*s != NUL) {
8464-
func_mb_ptr2char_adv((const char_u **)&s);
8465-
len++;
8466-
}
8467-
rettv->vval.v_number = len;
8495+
strchar_common(argvars, rettv, skipcc);
84688496
}
84698497
}
84708498

src/nvim/eval/typval.c

+16-1
Original file line numberDiff line numberDiff line change
@@ -2060,10 +2060,25 @@ int tv_dict_get_tv(dict_T *d, const char *const key, typval_T *rettv)
20602060
/// @return Dictionary item.
20612061
varnumber_T tv_dict_get_number(const dict_T *const d, const char *const key)
20622062
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
2063+
{
2064+
return tv_dict_get_number_def(d, key, 0);
2065+
}
2066+
2067+
/// Get a number item from a dictionary.
2068+
///
2069+
/// Returns "def" if the entry doesn't exist.
2070+
///
2071+
/// @param[in] d Dictionary to get item from.
2072+
/// @param[in] key Key to find in dictionary.
2073+
/// @param[in] def Default value.
2074+
///
2075+
/// @return Dictionary item.
2076+
varnumber_T tv_dict_get_number_def(const dict_T *const d, const char *const key, const int def)
2077+
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
20632078
{
20642079
dictitem_T *const di = tv_dict_find(d, key, -1);
20652080
if (di == NULL) {
2066-
return 0;
2081+
return def;
20672082
}
20682083
return tv_get_number(&di->di_tv);
20692084
}

src/nvim/eval/typval.h

+5
Original file line numberDiff line numberDiff line change
@@ -559,4 +559,9 @@ EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE);
559559
#ifdef INCLUDE_GENERATED_DECLARATIONS
560560
# include "eval/typval.h.generated.h"
561561
#endif
562+
563+
#define tv_get_bool tv_get_number
564+
#define tv_get_bool_chk tv_get_number_chk
565+
#define tv_dict_get_bool tv_dict_get_number_def
566+
562567
#endif // NVIM_EVAL_TYPVAL_H

src/nvim/path.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
12441244
add_pat = expand_backtick(&ga, (char *)p, flags);
12451245
if (add_pat == -1) {
12461246
recursive = false;
1247-
FreeWild(ga.ga_len, ga.ga_data);
1247+
ga_clear_strings(&ga);
12481248
*num_file = 0;
12491249
*file = NULL;
12501250
return FAIL;

src/nvim/testdir/test_expand.vim

+15-3
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,26 @@ func Test_expandcmd()
9090
" Test for expression expansion `=
9191
let $FOO= "blue"
9292
call assert_equal("blue sky", expandcmd("`=$FOO .. ' sky'`"))
93+
let x = expandcmd("`=axbycz`")
94+
call assert_equal('`=axbycz`', x)
95+
call assert_fails('let x = expandcmd("`=axbycz`", #{errmsg: 1})', 'E121:')
96+
let x = expandcmd("`=axbycz`", #{abc: []})
97+
call assert_equal('`=axbycz`', x)
9398

9499
" Test for env variable with spaces
95100
let $FOO= "foo bar baz"
96101
call assert_equal("e foo bar baz", expandcmd("e $FOO"))
97102

98-
if has('unix')
99-
" test for using the shell to expand a command argument
100-
call assert_equal('{1..4}', expandcmd('{1..4}'))
103+
if has('unix') && executable('bash')
104+
" test for using the shell to expand a command argument.
105+
" only bash supports the {..} syntax
106+
set shell=bash
107+
let x = expandcmd('{1..4}')
108+
call assert_equal('{1..4}', x)
109+
call assert_fails("let x = expandcmd('{1..4}', #{errmsg: v:true})", 'E77:')
110+
let x = expandcmd('{1..4}', #{error: v:true})
111+
call assert_equal('{1..4}', x)
112+
set shell&
101113
endif
102114

103115
unlet $FOO

src/nvim/testdir/test_functions.vim

+2-2
Original file line numberDiff line numberDiff line change
@@ -1101,8 +1101,8 @@ func Test_charidx()
11011101
call assert_fails('let x = charidx([], 1)', 'E474:')
11021102
call assert_fails('let x = charidx("abc", [])', 'E474:')
11031103
call assert_fails('let x = charidx("abc", 1, [])', 'E474:')
1104-
call assert_fails('let x = charidx("abc", 1, -1)', 'E474:')
1105-
call assert_fails('let x = charidx("abc", 1, 2)', 'E474:')
1104+
call assert_fails('let x = charidx("abc", 1, -1)', 'E1023:')
1105+
call assert_fails('let x = charidx("abc", 1, 2)', 'E1023:')
11061106
endfunc
11071107

11081108
func Test_count()

src/nvim/testdir/test_listdict.vim

+2-2
Original file line numberDiff line numberDiff line change
@@ -336,12 +336,12 @@ func Test_dict_deepcopy()
336336
let l = [4, d, 6]
337337
let d[3] = l
338338
let dc = deepcopy(d)
339-
call assert_fails('call deepcopy(d, 1)', 'E698')
339+
call assert_fails('call deepcopy(d, 1)', 'E698:')
340340
let l2 = [0, l, l, 3]
341341
let l[1] = l2
342342
let l3 = deepcopy(l2)
343343
call assert_true(l3[1] is l3[2])
344-
call assert_fails("call deepcopy([1, 2], 2)", 'E474:')
344+
call assert_fails("call deepcopy([1, 2], 2)", 'E1023:')
345345
endfunc
346346

347347
" Locked variables

src/nvim/testdir/test_search.vim

+3
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ func Test_searchpair()
294294
new
295295
call setline(1, ['other code', 'here [', ' [', ' " cursor here', ' ]]'])
296296

297+
" should not give an error for using "42"
298+
call assert_equal(0, searchpair('a', 'b', 'c', '', 42))
299+
297300
4
298301
call assert_equal(3, searchpair('\[', '', ']', 'bW'))
299302
call assert_equal([0, 3, 2, 0], getpos('.'))

src/nvim/testdir/test_utf8.vim

+9-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ func Test_visual_block_insert()
1212
bwipeout!
1313
endfunc
1414

15-
" Test for built-in function strchars()
15+
" Test for built-in functions strchars() and strcharlen()
1616
func Test_strchars()
1717
let inp = ["a", "あいa", "A\u20dd", "A\u20dd\u20dd", "\u20dd"]
1818
let exp = [[1, 1, 1], [3, 3, 3], [2, 2, 1], [3, 3, 1], [1, 1, 1]]
@@ -21,8 +21,15 @@ func Test_strchars()
2121
call assert_equal(exp[i][1], inp[i]->strchars(0))
2222
call assert_equal(exp[i][2], strchars(inp[i], 1))
2323
endfor
24+
25+
let exp = [1, 3, 1, 1, 1]
26+
for i in range(len(inp))
27+
call assert_equal(exp[i], inp[i]->strcharlen())
28+
call assert_equal(exp[i], strcharlen(inp[i]))
29+
endfor
30+
2431
call assert_fails("let v=strchars('abc', [])", 'E745:')
25-
call assert_fails("let v=strchars('abc', 2)", 'E474:')
32+
call assert_fails("let v=strchars('abc', 2)", 'E1023:')
2633
endfunc
2734

2835
" Test for customlist completion

0 commit comments

Comments
 (0)