mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
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:
@@ -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.
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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},
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -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
|
||||
|
@@ -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('.'))
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user