forked from aniani/vim
patch 9.1.1068: getchar() can't distinguish between C-I and Tab
Problem: getchar() can't distinguish between C-I and Tab. Solution: Add {opts} to pass extra flags to getchar() and getcharstr(), with "number" and "simplify" keys. related: #10603 closes: #16554 Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
cbc1f409c1
commit
e0a2ab397f
@@ -1,4 +1,4 @@
|
|||||||
*builtin.txt* For Vim version 9.1. Last change: 2025 Feb 01
|
*builtin.txt* For Vim version 9.1. Last change: 2025 Feb 02
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -228,12 +228,12 @@ getbufvar({buf}, {varname} [, {def}])
|
|||||||
getcellpixels() List get character cell pixel size
|
getcellpixels() List get character cell pixel size
|
||||||
getcellwidths() List get character cell width overrides
|
getcellwidths() List get character cell width overrides
|
||||||
getchangelist([{buf}]) List list of change list items
|
getchangelist([{buf}]) List list of change list items
|
||||||
getchar([{expr}]) Number or String
|
getchar([{expr} [, {opts}]]) Number or String
|
||||||
get one character from the user
|
get one character from the user
|
||||||
getcharmod() Number modifiers for the last typed character
|
getcharmod() Number modifiers for the last typed character
|
||||||
getcharpos({expr}) List position of cursor, mark, etc.
|
getcharpos({expr}) List position of cursor, mark, etc.
|
||||||
getcharsearch() Dict last character search
|
getcharsearch() Dict last character search
|
||||||
getcharstr([{expr}]) String get one character from the user
|
getcharstr([{expr} [, {opts}]]) String get one character from the user
|
||||||
getcmdcomplpat() String return the completion pattern of the
|
getcmdcomplpat() String return the completion pattern of the
|
||||||
current command-line completion
|
current command-line completion
|
||||||
getcmdcompltype() String return the type of the current
|
getcmdcompltype() String return the type of the current
|
||||||
@@ -3918,14 +3918,16 @@ getchangelist([{buf}]) *getchangelist()*
|
|||||||
Return type: list<any>
|
Return type: list<any>
|
||||||
|
|
||||||
|
|
||||||
getchar([{expr}]) *getchar()*
|
getchar([{expr} [, {opts}]]) *getchar()*
|
||||||
Get a single character from the user or input stream.
|
Get a single character from the user or input stream.
|
||||||
If {expr} is omitted, wait until a character is available.
|
If {expr} is omitted or is -1, wait until a character is
|
||||||
|
available.
|
||||||
If {expr} is 0, only get a character when one is available.
|
If {expr} is 0, only get a character when one is available.
|
||||||
Return zero otherwise.
|
Return zero otherwise.
|
||||||
If {expr} is 1, only check if a character is available, it is
|
If {expr} is 1, only check if a character is available, it is
|
||||||
not consumed. Return zero if no character available.
|
not consumed. Return zero if no character available.
|
||||||
If you prefer always getting a string use |getcharstr()|.
|
If you prefer always getting a string use |getcharstr()|, or
|
||||||
|
specify |FALSE| as "number" in {opts}.
|
||||||
|
|
||||||
Without {expr} and when {expr} is 0 a whole character or
|
Without {expr} and when {expr} is 0 a whole character or
|
||||||
special key is returned. If it is a single character, the
|
special key is returned. If it is a single character, the
|
||||||
@@ -3935,7 +3937,8 @@ getchar([{expr}]) *getchar()*
|
|||||||
starting with 0x80 (decimal: 128). This is the same value as
|
starting with 0x80 (decimal: 128). This is the same value as
|
||||||
the String "\<Key>", e.g., "\<Left>". The returned value is
|
the String "\<Key>", e.g., "\<Left>". The returned value is
|
||||||
also a String when a modifier (shift, control, alt) was used
|
also a String when a modifier (shift, control, alt) was used
|
||||||
that is not included in the character.
|
that is not included in the character. |keytrans()| can also
|
||||||
|
be used to convert a returned String into a readable form.
|
||||||
|
|
||||||
When {expr} is 0 and Esc is typed, there will be a short delay
|
When {expr} is 0 and Esc is typed, there will be a short delay
|
||||||
while Vim waits to see if this is the start of an escape
|
while Vim waits to see if this is the start of an escape
|
||||||
@@ -3947,6 +3950,24 @@ getchar([{expr}]) *getchar()*
|
|||||||
|
|
||||||
Use getcharmod() to obtain any additional modifiers.
|
Use getcharmod() to obtain any additional modifiers.
|
||||||
|
|
||||||
|
The optional argument {opts} is a Dict and supports the
|
||||||
|
following items:
|
||||||
|
|
||||||
|
number If |TRUE|, return a Number when getting
|
||||||
|
a single character.
|
||||||
|
If |FALSE|, the return value is always
|
||||||
|
converted to a String, and an empty
|
||||||
|
String (instead of 0) is returned when
|
||||||
|
no character is available.
|
||||||
|
(default: |TRUE|)
|
||||||
|
|
||||||
|
simplify If |TRUE|, include modifiers in the
|
||||||
|
character if possible. E.g., return
|
||||||
|
the same value for CTRL-I and <Tab>.
|
||||||
|
If |FALSE|, don't include modifiers in
|
||||||
|
the character.
|
||||||
|
(default: |TRUE|)
|
||||||
|
|
||||||
When the user clicks a mouse button, the mouse event will be
|
When the user clicks a mouse button, the mouse event will be
|
||||||
returned. The position can then be found in |v:mouse_col|,
|
returned. The position can then be found in |v:mouse_col|,
|
||||||
|v:mouse_lnum|, |v:mouse_winid| and |v:mouse_win|.
|
|v:mouse_lnum|, |v:mouse_winid| and |v:mouse_win|.
|
||||||
@@ -4062,17 +4083,9 @@ getcharsearch() *getcharsearch()*
|
|||||||
Return type: dict<any>
|
Return type: dict<any>
|
||||||
|
|
||||||
|
|
||||||
getcharstr([{expr}]) *getcharstr()*
|
getcharstr([{expr} [, {opts}]]) *getcharstr()*
|
||||||
Get a single character from the user or input stream as a
|
The same as |getchar()|, except that this always returns a
|
||||||
string.
|
String, and "number" isn't allowed in {opts}.
|
||||||
If {expr} is omitted, wait until a character is available.
|
|
||||||
If {expr} is 0 or false, only get a character when one is
|
|
||||||
available. Return an empty string otherwise.
|
|
||||||
If {expr} is 1 or true, only check if a character is
|
|
||||||
available, it is not consumed. Return an empty string
|
|
||||||
if no character is available.
|
|
||||||
Otherwise this works like |getchar()|, except that a number
|
|
||||||
result is converted to a string.
|
|
||||||
|
|
||||||
Return type: |String|
|
Return type: |String|
|
||||||
|
|
||||||
|
@@ -3172,7 +3172,8 @@ EXTERN char e_exists_compiled_can_only_be_used_in_def_function[]
|
|||||||
EXTERN char e_legacy_must_be_followed_by_command[]
|
EXTERN char e_legacy_must_be_followed_by_command[]
|
||||||
INIT(= N_("E1234: legacy must be followed by a command"));
|
INIT(= N_("E1234: legacy must be followed by a command"));
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
// E1235 unused
|
EXTERN char e_bool_or_number_required_for_argument_nr[]
|
||||||
|
INIT(= N_("E1235: Bool or Number required for argument %d"));
|
||||||
EXTERN char e_cannot_use_str_itself_it_is_imported[]
|
EXTERN char e_cannot_use_str_itself_it_is_imported[]
|
||||||
INIT(= N_("E1236: Cannot use %s itself, it is imported"));
|
INIT(= N_("E1236: Cannot use %s itself, it is imported"));
|
||||||
#endif
|
#endif
|
||||||
|
@@ -387,6 +387,20 @@ arg_bool(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
|
|||||||
return check_arg_type(&t_bool, type, context);
|
return check_arg_type(&t_bool, type, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check "type" is a bool or a number.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
arg_bool_or_nr(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
|
||||||
|
{
|
||||||
|
if (type->tt_type == VAR_BOOL
|
||||||
|
|| type->tt_type == VAR_NUMBER
|
||||||
|
|| type_any_or_unknown(type))
|
||||||
|
return OK;
|
||||||
|
arg_type_mismatch(&t_number, type, context->arg_idx + 1);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check "type" is a list of 'any' or a blob.
|
* Check "type" is a list of 'any' or a blob.
|
||||||
*/
|
*/
|
||||||
@@ -1195,6 +1209,7 @@ static argcheck_T arg24_count[] = {arg_string_or_list_or_dict, arg_any, arg_bool
|
|||||||
static argcheck_T arg13_cursor[] = {arg_cursor1, arg_number, arg_number};
|
static argcheck_T arg13_cursor[] = {arg_cursor1, arg_number, arg_number};
|
||||||
static argcheck_T arg12_deepcopy[] = {arg_any, arg_bool};
|
static argcheck_T arg12_deepcopy[] = {arg_any, arg_bool};
|
||||||
static argcheck_T arg12_execute[] = {arg_string_or_list_string, arg_string};
|
static argcheck_T arg12_execute[] = {arg_string_or_list_string, arg_string};
|
||||||
|
static argcheck_T arg12_getchar[] = {arg_bool_or_nr, arg_dict_any};
|
||||||
static argcheck_T arg23_extend[] = {arg_list_or_dict_mod, arg_same_as_prev, arg_extend3};
|
static argcheck_T arg23_extend[] = {arg_list_or_dict_mod, arg_same_as_prev, arg_extend3};
|
||||||
static argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3};
|
static argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3};
|
||||||
static argcheck_T arg23_get[] = {arg_get1, arg_string_or_nr, arg_any};
|
static argcheck_T arg23_get[] = {arg_get1, arg_string_or_nr, arg_any};
|
||||||
@@ -2095,7 +2110,7 @@ static funcentry_T global_functions[] =
|
|||||||
ret_list_any, f_getcellwidths},
|
ret_list_any, f_getcellwidths},
|
||||||
{"getchangelist", 0, 1, FEARG_1, arg1_buffer,
|
{"getchangelist", 0, 1, FEARG_1, arg1_buffer,
|
||||||
ret_list_any, f_getchangelist},
|
ret_list_any, f_getchangelist},
|
||||||
{"getchar", 0, 1, 0, arg1_bool,
|
{"getchar", 0, 2, 0, arg12_getchar,
|
||||||
ret_any, f_getchar},
|
ret_any, f_getchar},
|
||||||
{"getcharmod", 0, 0, 0, NULL,
|
{"getcharmod", 0, 0, 0, NULL,
|
||||||
ret_number, f_getcharmod},
|
ret_number, f_getcharmod},
|
||||||
@@ -2103,7 +2118,7 @@ static funcentry_T global_functions[] =
|
|||||||
ret_list_number, f_getcharpos},
|
ret_list_number, f_getcharpos},
|
||||||
{"getcharsearch", 0, 0, 0, NULL,
|
{"getcharsearch", 0, 0, 0, NULL,
|
||||||
ret_dict_any, f_getcharsearch},
|
ret_dict_any, f_getcharsearch},
|
||||||
{"getcharstr", 0, 1, 0, arg1_bool,
|
{"getcharstr", 0, 2, 0, arg12_getchar,
|
||||||
ret_string, f_getcharstr},
|
ret_string, f_getcharstr},
|
||||||
{"getcmdcomplpat", 0, 0, 0, NULL,
|
{"getcmdcomplpat", 0, 0, 0, NULL,
|
||||||
ret_string, f_getcmdcomplpat},
|
ret_string, f_getcmdcomplpat},
|
||||||
|
@@ -2384,14 +2384,33 @@ char_avail(void)
|
|||||||
* "getchar()" and "getcharstr()" functions
|
* "getchar()" and "getcharstr()" functions
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
getchar_common(typval_T *argvars, typval_T *rettv)
|
getchar_common(typval_T *argvars, typval_T *rettv, int allow_number)
|
||||||
{
|
{
|
||||||
varnumber_T n;
|
varnumber_T n;
|
||||||
int error = FALSE;
|
int error = FALSE;
|
||||||
|
int simplify = TRUE;
|
||||||
|
|
||||||
if (in_vim9script() && check_for_opt_bool_arg(argvars, 0) == FAIL)
|
if ((in_vim9script()
|
||||||
|
&& check_for_opt_bool_or_number_arg(argvars, 0) == FAIL)
|
||||||
|
|| (argvars[0].v_type != VAR_UNKNOWN
|
||||||
|
&& check_for_opt_dict_arg(argvars, 1) == FAIL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (argvars[0].v_type != VAR_UNKNOWN && argvars[1].v_type == VAR_DICT)
|
||||||
|
{
|
||||||
|
dict_T *d = argvars[1].vval.v_dict;
|
||||||
|
|
||||||
|
if (allow_number)
|
||||||
|
allow_number = dict_get_bool(d, "number", TRUE);
|
||||||
|
else if (dict_has_key(d, "number"))
|
||||||
|
{
|
||||||
|
semsg(_(e_invalid_argument_str), "number");
|
||||||
|
error = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
simplify = dict_get_bool(d, "simplify", TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MESSAGE_QUEUE
|
#ifdef MESSAGE_QUEUE
|
||||||
// vpeekc() used to check for messages, but that caused problems, invoking
|
// vpeekc() used to check for messages, but that caused problems, invoking
|
||||||
// a callback where it was not expected. Some plugins use getchar(1) in a
|
// a callback where it was not expected. Some plugins use getchar(1) in a
|
||||||
@@ -2404,9 +2423,13 @@ getchar_common(typval_T *argvars, typval_T *rettv)
|
|||||||
|
|
||||||
++no_mapping;
|
++no_mapping;
|
||||||
++allow_keys;
|
++allow_keys;
|
||||||
for (;;)
|
if (!simplify)
|
||||||
|
++no_reduce_keys;
|
||||||
|
while (!error)
|
||||||
{
|
{
|
||||||
if (argvars[0].v_type == VAR_UNKNOWN)
|
if (argvars[0].v_type == VAR_UNKNOWN
|
||||||
|
|| (argvars[0].v_type == VAR_NUMBER
|
||||||
|
&& argvars[0].vval.v_number == -1))
|
||||||
// getchar(): blocking wait.
|
// getchar(): blocking wait.
|
||||||
n = plain_vgetc_nopaste();
|
n = plain_vgetc_nopaste();
|
||||||
else if (tv_get_bool_chk(&argvars[0], &error))
|
else if (tv_get_bool_chk(&argvars[0], &error))
|
||||||
@@ -2427,14 +2450,15 @@ getchar_common(typval_T *argvars, typval_T *rettv)
|
|||||||
}
|
}
|
||||||
--no_mapping;
|
--no_mapping;
|
||||||
--allow_keys;
|
--allow_keys;
|
||||||
|
if (!simplify)
|
||||||
|
--no_reduce_keys;
|
||||||
|
|
||||||
set_vim_var_nr(VV_MOUSE_WIN, 0);
|
set_vim_var_nr(VV_MOUSE_WIN, 0);
|
||||||
set_vim_var_nr(VV_MOUSE_WINID, 0);
|
set_vim_var_nr(VV_MOUSE_WINID, 0);
|
||||||
set_vim_var_nr(VV_MOUSE_LNUM, 0);
|
set_vim_var_nr(VV_MOUSE_LNUM, 0);
|
||||||
set_vim_var_nr(VV_MOUSE_COL, 0);
|
set_vim_var_nr(VV_MOUSE_COL, 0);
|
||||||
|
|
||||||
rettv->vval.v_number = n;
|
if (n != 0 && (!allow_number || IS_SPECIAL(n) || mod_mask != 0))
|
||||||
if (n != 0 && (IS_SPECIAL(n) || mod_mask != 0))
|
|
||||||
{
|
{
|
||||||
char_u temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1
|
char_u temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -2492,6 +2516,10 @@ getchar_common(typval_T *argvars, typval_T *rettv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!allow_number)
|
||||||
|
rettv->v_type = VAR_STRING;
|
||||||
|
else
|
||||||
|
rettv->vval.v_number = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2500,7 +2528,7 @@ getchar_common(typval_T *argvars, typval_T *rettv)
|
|||||||
void
|
void
|
||||||
f_getchar(typval_T *argvars, typval_T *rettv)
|
f_getchar(typval_T *argvars, typval_T *rettv)
|
||||||
{
|
{
|
||||||
getchar_common(argvars, rettv);
|
getchar_common(argvars, rettv, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2509,25 +2537,7 @@ f_getchar(typval_T *argvars, typval_T *rettv)
|
|||||||
void
|
void
|
||||||
f_getcharstr(typval_T *argvars, typval_T *rettv)
|
f_getcharstr(typval_T *argvars, typval_T *rettv)
|
||||||
{
|
{
|
||||||
getchar_common(argvars, rettv);
|
getchar_common(argvars, rettv, FALSE);
|
||||||
|
|
||||||
if (rettv->v_type != VAR_NUMBER)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char_u temp[7]; // mbyte-char: 6, NUL: 1
|
|
||||||
varnumber_T n = rettv->vval.v_number;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (n != 0)
|
|
||||||
{
|
|
||||||
if (has_mbyte)
|
|
||||||
i += (*mb_char2bytes)(n, temp + i);
|
|
||||||
else
|
|
||||||
temp[i++] = n;
|
|
||||||
}
|
|
||||||
temp[i] = NUL;
|
|
||||||
rettv->v_type = VAR_STRING;
|
|
||||||
rettv->vval.v_string = vim_strnsave(temp, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -18,7 +18,9 @@ int check_for_number_arg(typval_T *args, int idx);
|
|||||||
int check_for_opt_number_arg(typval_T *args, int idx);
|
int check_for_opt_number_arg(typval_T *args, int idx);
|
||||||
int check_for_float_or_nr_arg(typval_T *args, int idx);
|
int check_for_float_or_nr_arg(typval_T *args, int idx);
|
||||||
int check_for_bool_arg(typval_T *args, int idx);
|
int check_for_bool_arg(typval_T *args, int idx);
|
||||||
|
int check_for_bool_or_number_arg(typval_T *args, int idx);
|
||||||
int check_for_opt_bool_arg(typval_T *args, int idx);
|
int check_for_opt_bool_arg(typval_T *args, int idx);
|
||||||
|
int check_for_opt_bool_or_number_arg(typval_T *args, int idx);
|
||||||
int check_for_blob_arg(typval_T *args, int idx);
|
int check_for_blob_arg(typval_T *args, int idx);
|
||||||
int check_for_list_arg(typval_T *args, int idx);
|
int check_for_list_arg(typval_T *args, int idx);
|
||||||
int check_for_nonnull_list_arg(typval_T *args, int idx);
|
int check_for_nonnull_list_arg(typval_T *args, int idx);
|
||||||
|
@@ -2562,6 +2562,75 @@ func Test_getchar()
|
|||||||
call assert_equal("\<M-F2>", getchar(0))
|
call assert_equal("\<M-F2>", getchar(0))
|
||||||
call assert_equal(0, getchar(0))
|
call assert_equal(0, getchar(0))
|
||||||
|
|
||||||
|
call feedkeys("\<Tab>", '')
|
||||||
|
call assert_equal(char2nr("\<Tab>"), getchar())
|
||||||
|
call feedkeys("\<Tab>", '')
|
||||||
|
call assert_equal(char2nr("\<Tab>"), getchar(-1))
|
||||||
|
call feedkeys("\<Tab>", '')
|
||||||
|
call assert_equal(char2nr("\<Tab>"), getchar(-1, {}))
|
||||||
|
call feedkeys("\<Tab>", '')
|
||||||
|
call assert_equal(char2nr("\<Tab>"), getchar(-1, #{number: v:true}))
|
||||||
|
call assert_equal(0, getchar(0))
|
||||||
|
call assert_equal(0, getchar(1))
|
||||||
|
call assert_equal(0, getchar(0, #{number: v:true}))
|
||||||
|
call assert_equal(0, getchar(1, #{number: v:true}))
|
||||||
|
|
||||||
|
call feedkeys("\<Tab>", '')
|
||||||
|
call assert_equal("\<Tab>", getcharstr())
|
||||||
|
call feedkeys("\<Tab>", '')
|
||||||
|
call assert_equal("\<Tab>", getcharstr(-1))
|
||||||
|
call feedkeys("\<Tab>", '')
|
||||||
|
call assert_equal("\<Tab>", getcharstr(-1, {}))
|
||||||
|
call feedkeys("\<Tab>", '')
|
||||||
|
call assert_equal("\<Tab>", getchar(-1, #{number: v:false}))
|
||||||
|
call assert_equal('', getcharstr(0))
|
||||||
|
call assert_equal('', getcharstr(1))
|
||||||
|
call assert_equal('', getchar(0, #{number: v:false}))
|
||||||
|
call assert_equal('', getchar(1, #{number: v:false}))
|
||||||
|
|
||||||
|
for key in ["C-I", "C-X", "M-x"]
|
||||||
|
let lines =<< eval trim END
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal(char2nr("\<{key}>"), getchar())
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal(char2nr("\<{key}>"), getchar(-1))
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal(char2nr("\<{key}>"), getchar(-1, {{}}))
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal(char2nr("\<{key}>"), getchar(-1, {{'number': 1}}))
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal(char2nr("\<{key}>"), getchar(-1, {{'simplify': 1}}))
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal("\<*{key}>", getchar(-1, {{'simplify': v:false}}))
|
||||||
|
call assert_equal(0, getchar(0))
|
||||||
|
call assert_equal(0, getchar(1))
|
||||||
|
END
|
||||||
|
call v9.CheckLegacyAndVim9Success(lines)
|
||||||
|
|
||||||
|
let lines =<< eval trim END
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal("\<{key}>", getcharstr())
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal("\<{key}>", getcharstr(-1))
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal("\<{key}>", getcharstr(-1, {{}}))
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal("\<{key}>", getchar(-1, {{'number': 0}}))
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal("\<{key}>", getcharstr(-1, {{'simplify': 1}}))
|
||||||
|
call feedkeys("\<*{key}>", '')
|
||||||
|
call assert_equal("\<*{key}>", getcharstr(-1, {{'simplify': v:false}}))
|
||||||
|
call assert_equal('', getcharstr(0))
|
||||||
|
call assert_equal('', getcharstr(1))
|
||||||
|
END
|
||||||
|
call v9.CheckLegacyAndVim9Success(lines)
|
||||||
|
endfor
|
||||||
|
|
||||||
|
call assert_fails('call getchar(1, 1)', 'E1206:')
|
||||||
|
call assert_fails('call getcharstr(1, 1)', 'E1206:')
|
||||||
|
call assert_fails('call getcharstr(1, #{number: v:true})', 'E475:')
|
||||||
|
call assert_fails('call getcharstr(1, #{number: v:false})', 'E475:')
|
||||||
|
|
||||||
call setline(1, 'xxxx')
|
call setline(1, 'xxxx')
|
||||||
call test_setmouse(1, 3)
|
call test_setmouse(1, 3)
|
||||||
let v:mouse_win = 9
|
let v:mouse_win = 9
|
||||||
|
@@ -1838,8 +1838,10 @@ def Test_getchar()
|
|||||||
endwhile
|
endwhile
|
||||||
getchar(true)->assert_equal(0)
|
getchar(true)->assert_equal(0)
|
||||||
getchar(1)->assert_equal(0)
|
getchar(1)->assert_equal(0)
|
||||||
v9.CheckSourceDefAndScriptFailure(['getchar(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1'])
|
v9.CheckSourceDefExecAndScriptFailure(['getchar(2)'], 'E1023: Using a Number as a Bool: 2')
|
||||||
v9.CheckSourceDefAndScriptFailure(['getchar("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1'])
|
v9.CheckSourceDefExecAndScriptFailure(['getchar(-2)'], 'E1023: Using a Number as a Bool: -2')
|
||||||
|
v9.CheckSourceDefAndScriptFailure(['getchar("1")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1235: Bool or Number required for argument 1'])
|
||||||
|
v9.CheckSourceDefAndScriptFailure(['getchar(1, 1)'], ['E1013: Argument 2: type mismatch, expected dict<any> but got number', 'E1206: Dictionary required for argument 2'])
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_getcharpos()
|
def Test_getcharpos()
|
||||||
@@ -1851,8 +1853,14 @@ def Test_getcharpos()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_getcharstr()
|
def Test_getcharstr()
|
||||||
v9.CheckSourceDefAndScriptFailure(['getcharstr(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1'])
|
while len(getcharstr(0)) > 0
|
||||||
v9.CheckSourceDefAndScriptFailure(['getcharstr("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1'])
|
endwhile
|
||||||
|
getcharstr(true)->assert_equal('')
|
||||||
|
getcharstr(1)->assert_equal('')
|
||||||
|
v9.CheckSourceDefExecAndScriptFailure(['getcharstr(2)'], 'E1023: Using a Number as a Bool: 2')
|
||||||
|
v9.CheckSourceDefExecAndScriptFailure(['getcharstr(-2)'], 'E1023: Using a Number as a Bool: -2')
|
||||||
|
v9.CheckSourceDefAndScriptFailure(['getcharstr("1")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1235: Bool or Number required for argument 1'])
|
||||||
|
v9.CheckSourceDefAndScriptFailure(['getcharstr(1, 1)'], ['E1013: Argument 2: type mismatch, expected dict<any> but got number', 'E1206: Dictionary required for argument 2'])
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_getcompletion()
|
def Test_getcompletion()
|
||||||
@@ -4989,7 +4997,7 @@ enddef
|
|||||||
|
|
||||||
def Test_win_findbuf()
|
def Test_win_findbuf()
|
||||||
v9.CheckSourceDefAndScriptFailure(['win_findbuf("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1'])
|
v9.CheckSourceDefAndScriptFailure(['win_findbuf("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1'])
|
||||||
assert_equal([], win_findbuf(1000))
|
assert_equal([], win_findbuf(9999))
|
||||||
assert_equal([win_getid()], win_findbuf(bufnr('')))
|
assert_equal([win_getid()], win_findbuf(bufnr('')))
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
26
src/typval.c
26
src/typval.c
@@ -526,6 +526,20 @@ check_for_bool_arg(typval_T *args, int idx)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Give an error and return FAIL unless "args[idx]" is a bool or a number.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
check_for_bool_or_number_arg(typval_T *args, int idx)
|
||||||
|
{
|
||||||
|
if (args[idx].v_type != VAR_BOOL && args[idx].v_type != VAR_NUMBER)
|
||||||
|
{
|
||||||
|
semsg(_(e_bool_or_number_required_for_argument_nr), idx + 1);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for an optional bool argument at 'idx'.
|
* Check for an optional bool argument at 'idx'.
|
||||||
* Return FAIL if the type is wrong.
|
* Return FAIL if the type is wrong.
|
||||||
@@ -538,6 +552,18 @@ check_for_opt_bool_arg(typval_T *args, int idx)
|
|||||||
return check_for_bool_arg(args, idx);
|
return check_for_bool_arg(args, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for an optional bool or number argument at 'idx'.
|
||||||
|
* Return FAIL if the type is wrong.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
check_for_opt_bool_or_number_arg(typval_T *args, int idx)
|
||||||
|
{
|
||||||
|
if (args[idx].v_type == VAR_UNKNOWN)
|
||||||
|
return OK;
|
||||||
|
return check_for_bool_or_number_arg(args, idx);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Give an error and return FAIL unless "args[idx]" is a blob.
|
* Give an error and return FAIL unless "args[idx]" is a blob.
|
||||||
*/
|
*/
|
||||||
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1068,
|
||||||
/**/
|
/**/
|
||||||
1067,
|
1067,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user