Merge pull request #20774 from zeertzjq/vim-8.2.4679

vim-patch:8.2.{1506,1600,1624,1626,1751,2606,4679}
This commit is contained in:
zeertzjq
2022-11-05 18:51:03 +08:00
committed by GitHub
12 changed files with 137 additions and 37 deletions

View File

@@ -134,7 +134,8 @@ exists({expr}) Number |TRUE| if {expr} exists
exp({expr}) Float exponential of {expr}
expand({expr} [, {nosuf} [, {list}]])
any expand special keywords in {expr}
expandcmd({expr}) String expand {expr} like with `:edit`
expandcmd({string} [, {options}])
String expand {string} like with `:edit`
extend({expr1}, {expr2} [, {expr3}])
List/Dict insert items of {expr2} into {expr1}
feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer
@@ -466,10 +467,11 @@ str2list({expr} [, {utf8}]) List convert each character of {expr} to
ASCII/UTF-8 value
str2nr({expr} [, {base} [, {quoted}]])
Number convert String to Number
strcharlen({expr}) Number character length of the String {expr}
strcharpart({str}, {start} [, {len}])
String {len} characters of {str} at
character {start}
strchars({expr} [, {skipcc}]) Number character length of the String {expr}
strchars({expr} [, {skipcc}]) Number character count of the String {expr}
strdisplaywidth({expr} [, {col}]) Number display length of the String {expr}
strftime({format} [, {time}]) String format time with a specified format
strgetchar({str}, {index}) Number get char {index} from {str}
@@ -2043,18 +2045,27 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
Can also be used as a |method|: >
Getpattern()->expand()
expandcmd({string}) *expandcmd()*
expandcmd({string} [, {options}]) *expandcmd()*
Expand special items in String {string} like what is done for
an Ex command such as `:edit`. This expands special keywords,
like with |expand()|, and environment variables, anywhere in
{string}. "~user" and "~/path" are only expanded at the
start.
The following items are supported in the {options} Dict
argument:
errmsg If set to TRUE, error messages are displayed
if an error is encountered during expansion.
By default, error messages are not displayed.
Returns the expanded string. If an error is encountered
during expansion, the unmodified {string} is returned.
Example: >
:echo expandcmd('make %<.o')
< make /path/runtime/doc/builtin.o ~
make /path/runtime/doc/builtin.o
:echo expandcmd('make %<.o', {'errmsg': v:true})
<
Can also be used as a |method|: >
GetCommand()->expandcmd()
<
@@ -7836,6 +7847,21 @@ str2nr({string} [, {base}]) *str2nr()*
Can also be used as a |method|: >
GetText()->str2nr()
strcharlen({string}) *strcharlen()*
The result is a Number, which is the number of characters
in String {string}. Composing characters are ignored.
|strchars()| can count the number of characters, counting
composing characters separately.
Returns 0 if {string} is empty or on error.
Also see |strlen()|, |strdisplaywidth()| and |strwidth()|.
Can also be used as a |method|: >
GetText()->strcharlen()
strcharpart({src}, {start} [, {len}]) *strcharpart()*
Like |strpart()| but using character index and length instead
of byte index and length. Composing characters are counted
@@ -7850,12 +7876,14 @@ strcharpart({src}, {start} [, {len}]) *strcharpart()*
Can also be used as a |method|: >
GetText()->strcharpart(5)
strchars({string} [, {skipcc}]) *strchars()*
The result is a Number, which is the number of characters
in String {string}.
When {skipcc} is omitted or zero, composing characters are
counted separately.
When {skipcc} set to 1, Composing characters are ignored.
|strcharlen()| always does this.
Returns zero on error.

View File

@@ -619,7 +619,8 @@ String manipulation: *string-functions*
stridx() first index of a short string in a long string
strridx() last index of a short string in a long string
strlen() length of a string in bytes
strchars() length of a string in characters
strcharlen() length of a string in characters
strchars() number of characters in a string
strwidth() size of string when displayed
strdisplaywidth() size of string when displayed, deals with tabs
setcellwidths() set character cell width overrides

View File

@@ -118,7 +118,7 @@ return {
exists={args=1, base=1},
exp={args=1, base=1, float_func="exp"},
expand={args={1, 3}, base=1},
expandcmd={args=1, base=1},
expandcmd={args={1, 2}, base=1},
extend={args={2, 3}, base=1},
feedkeys={args={1, 2}, base=1},
file_readable={args=1, base=1, func='f_filereadable'}, -- obsolete
@@ -376,6 +376,7 @@ return {
str2float={args=1, base=1},
str2list={args={1, 2}, base=1},
str2nr={args={1, 3}, base=1},
strcharlen={args=1, base=1},
strcharpart={args={2, 3}, base=1},
strchars={args={1, 2}, base=1},
strdisplaywidth={args={1, 2}, base=1},

View File

@@ -112,6 +112,8 @@ PRAGMA_DIAG_POP
static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob");
static char *e_invalwindow = N_("E957: Invalid window number");
static char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value");
static char e_using_number_as_bool_nr[]
= N_("E1023: Using a Number as a Bool: %d");
static char e_cannot_resize_window_in_another_tab_page[]
= N_("E1308: Cannot resize a window in another tab page");
@@ -906,7 +908,7 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
countcc = (int)tv_get_number(&argvars[2]);
}
if (countcc < 0 || countcc > 1) {
emsg(_(e_invarg));
semsg(_(e_using_number_as_bool_nr), countcc);
return;
}
@@ -1358,10 +1360,10 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
int noref = 0;
if (argvars[1].v_type != VAR_UNKNOWN) {
noref = (int)tv_get_number_chk(&argvars[1], NULL);
noref = (int)tv_get_bool_chk(&argvars[1], NULL);
}
if (noref < 0 || noref > 1) {
emsg(_(e_invarg));
semsg(_(e_using_number_as_bool_nr), noref);
} else {
var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0
? get_copyID()
@@ -2056,6 +2058,12 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char *errormsg = NULL;
bool emsgoff = true;
if (argvars[1].v_type == VAR_DICT
&& tv_dict_get_bool(argvars[1].vval.v_dict, "errmsg", kBoolVarFalse)) {
emsgoff = false;
}
rettv->v_type = VAR_STRING;
char *cmdstr = xstrdup(tv_get_string(&argvars[0]));
@@ -2069,9 +2077,17 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
};
eap.argt |= EX_NOSPC;
emsg_off++;
expand_filename(&eap, &cmdstr, &errormsg);
emsg_off--;
if (emsgoff) {
emsg_off++;
}
if (expand_filename(&eap, &cmdstr, &errormsg) == FAIL) {
if (!emsgoff && errormsg != NULL && *errormsg != NUL) {
emsg(errormsg);
}
}
if (emsgoff) {
emsg_off--;
}
rettv->vval.v_string = cmdstr;
}
@@ -8160,7 +8176,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
typeerr = true;
}
if (argvars[2].v_type != VAR_UNKNOWN) {
keepempty = (bool)tv_get_number_chk(&argvars[2], &typeerr);
keepempty = (bool)tv_get_bool_chk(&argvars[2], &typeerr);
}
}
if (pat == NULL || *pat == NUL) {
@@ -8290,7 +8306,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
emsg(_(e_invarg));
return;
}
if (argvars[2].v_type != VAR_UNKNOWN && tv_get_number(&argvars[2])) {
if (argvars[2].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[2])) {
what |= STR2NR_QUOTE;
}
}
@@ -8445,26 +8461,38 @@ static void f_strlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0]));
}
/// "strchars()" function
static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
static void strchar_common(typval_T *argvars, typval_T *rettv, bool skipcc)
{
const char *s = tv_get_string(&argvars[0]);
int skipcc = 0;
varnumber_T len = 0;
int (*func_mb_ptr2char_adv)(const char_u **pp);
func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
while (*s != NUL) {
func_mb_ptr2char_adv((const char_u **)&s);
len++;
}
rettv->vval.v_number = len;
}
/// "strcharlen()" function
static void f_strcharlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
strchar_common(argvars, rettv, true);
}
/// "strchars()" function
static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int skipcc = false;
if (argvars[1].v_type != VAR_UNKNOWN) {
skipcc = (int)tv_get_number_chk(&argvars[1], NULL);
skipcc = (int)tv_get_bool(&argvars[1]);
}
if (skipcc < 0 || skipcc > 1) {
emsg(_(e_invarg));
semsg(_(e_using_number_as_bool_nr), skipcc);
} else {
func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
while (*s != NUL) {
func_mb_ptr2char_adv((const char_u **)&s);
len++;
}
rettv->vval.v_number = len;
strchar_common(argvars, rettv, skipcc);
}
}

View File

@@ -2060,10 +2060,25 @@ int tv_dict_get_tv(dict_T *d, const char *const key, typval_T *rettv)
/// @return Dictionary item.
varnumber_T tv_dict_get_number(const dict_T *const d, const char *const key)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return tv_dict_get_number_def(d, key, 0);
}
/// Get a number item from a dictionary.
///
/// Returns "def" if the entry doesn't exist.
///
/// @param[in] d Dictionary to get item from.
/// @param[in] key Key to find in dictionary.
/// @param[in] def Default value.
///
/// @return Dictionary item.
varnumber_T tv_dict_get_number_def(const dict_T *const d, const char *const key, const int def)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
dictitem_T *const di = tv_dict_find(d, key, -1);
if (di == NULL) {
return 0;
return def;
}
return tv_get_number(&di->di_tv);
}

View File

@@ -559,4 +559,9 @@ EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE);
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/typval.h.generated.h"
#endif
#define tv_get_bool tv_get_number
#define tv_get_bool_chk tv_get_number_chk
#define tv_dict_get_bool tv_dict_get_number_def
#endif // NVIM_EVAL_TYPVAL_H

View File

@@ -1244,7 +1244,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
add_pat = expand_backtick(&ga, (char *)p, flags);
if (add_pat == -1) {
recursive = false;
FreeWild(ga.ga_len, ga.ga_data);
ga_clear_strings(&ga);
*num_file = 0;
*file = NULL;
return FAIL;

View File

@@ -90,14 +90,26 @@ func Test_expandcmd()
" Test for expression expansion `=
let $FOO= "blue"
call assert_equal("blue sky", expandcmd("`=$FOO .. ' sky'`"))
let x = expandcmd("`=axbycz`")
call assert_equal('`=axbycz`', x)
call assert_fails('let x = expandcmd("`=axbycz`", #{errmsg: 1})', 'E121:')
let x = expandcmd("`=axbycz`", #{abc: []})
call assert_equal('`=axbycz`', x)
" Test for env variable with spaces
let $FOO= "foo bar baz"
call assert_equal("e foo bar baz", expandcmd("e $FOO"))
if has('unix')
" test for using the shell to expand a command argument
call assert_equal('{1..4}', expandcmd('{1..4}'))
if has('unix') && executable('bash')
" test for using the shell to expand a command argument.
" only bash supports the {..} syntax
set shell=bash
let x = expandcmd('{1..4}')
call assert_equal('{1..4}', x)
call assert_fails("let x = expandcmd('{1..4}', #{errmsg: v:true})", 'E77:')
let x = expandcmd('{1..4}', #{error: v:true})
call assert_equal('{1..4}', x)
set shell&
endif
unlet $FOO

View File

@@ -1101,8 +1101,8 @@ func Test_charidx()
call assert_fails('let x = charidx([], 1)', 'E474:')
call assert_fails('let x = charidx("abc", [])', 'E474:')
call assert_fails('let x = charidx("abc", 1, [])', 'E474:')
call assert_fails('let x = charidx("abc", 1, -1)', 'E474:')
call assert_fails('let x = charidx("abc", 1, 2)', 'E474:')
call assert_fails('let x = charidx("abc", 1, -1)', 'E1023:')
call assert_fails('let x = charidx("abc", 1, 2)', 'E1023:')
endfunc
func Test_count()

View File

@@ -336,12 +336,12 @@ func Test_dict_deepcopy()
let l = [4, d, 6]
let d[3] = l
let dc = deepcopy(d)
call assert_fails('call deepcopy(d, 1)', 'E698')
call assert_fails('call deepcopy(d, 1)', 'E698:')
let l2 = [0, l, l, 3]
let l[1] = l2
let l3 = deepcopy(l2)
call assert_true(l3[1] is l3[2])
call assert_fails("call deepcopy([1, 2], 2)", 'E474:')
call assert_fails("call deepcopy([1, 2], 2)", 'E1023:')
endfunc
" Locked variables

View File

@@ -294,6 +294,9 @@ func Test_searchpair()
new
call setline(1, ['other code', 'here [', ' [', ' " cursor here', ' ]]'])
" should not give an error for using "42"
call assert_equal(0, searchpair('a', 'b', 'c', '', 42))
4
call assert_equal(3, searchpair('\[', '', ']', 'bW'))
call assert_equal([0, 3, 2, 0], getpos('.'))

View File

@@ -12,7 +12,7 @@ func Test_visual_block_insert()
bwipeout!
endfunc
" Test for built-in function strchars()
" Test for built-in functions strchars() and strcharlen()
func Test_strchars()
let inp = ["a", "あいa", "A\u20dd", "A\u20dd\u20dd", "\u20dd"]
let exp = [[1, 1, 1], [3, 3, 3], [2, 2, 1], [3, 3, 1], [1, 1, 1]]
@@ -21,8 +21,15 @@ func Test_strchars()
call assert_equal(exp[i][1], inp[i]->strchars(0))
call assert_equal(exp[i][2], strchars(inp[i], 1))
endfor
let exp = [1, 3, 1, 1, 1]
for i in range(len(inp))
call assert_equal(exp[i], inp[i]->strcharlen())
call assert_equal(exp[i], strcharlen(inp[i]))
endfor
call assert_fails("let v=strchars('abc', [])", 'E745:')
call assert_fails("let v=strchars('abc', 2)", 'E474:')
call assert_fails("let v=strchars('abc', 2)", 'E1023:')
endfunc
" Test for customlist completion