mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 18:55:14 -07:00
Merge #6480 from ZyX-I/colored-cmdline'/input-dict
This commit is contained in:
commit
17531ed082
@ -4665,10 +4665,23 @@ index({list}, {expr} [, {start} [, {ic}]]) *index()*
|
||||
|
||||
|
||||
input({prompt} [, {text} [, {completion}]]) *input()*
|
||||
input({opts})
|
||||
The result is a String, which is whatever the user typed on
|
||||
the command-line. The {prompt} argument is either a prompt
|
||||
string, or a blank string (for no prompt). A '\n' can be used
|
||||
in the prompt to start a new line.
|
||||
|
||||
In the second form it accepts a single dictionary with the
|
||||
following keys, any of which may be omitted:
|
||||
|
||||
Key Default Description ~
|
||||
prompt "" Same as {prompt} in the first form.
|
||||
default "" Same as {text} in the first form.
|
||||
completion nothing Same as {completion} in the first form.
|
||||
cancelreturn "" Same as {cancelreturn} from
|
||||
|inputdialog()|. Also works with
|
||||
input().
|
||||
|
||||
The highlighting set with |:echohl| is used for the prompt.
|
||||
The input is entered just like a command-line, with the same
|
||||
editing commands and mappings. There is a separate history
|
||||
@ -4710,6 +4723,7 @@ input({prompt} [, {text} [, {completion}]]) *input()*
|
||||
:endfunction
|
||||
|
||||
inputdialog({prompt} [, {text} [, {cancelreturn}]]) *inputdialog()*
|
||||
inputdialog({opts})
|
||||
Like |input()|, but when the GUI is running and text dialogs
|
||||
are supported, a dialog window pops up to input the text.
|
||||
Example: >
|
||||
@ -4721,7 +4735,6 @@ inputdialog({prompt} [, {text} [, {cancelreturn}]]) *inputdialog()*
|
||||
omitted an empty string is returned.
|
||||
Hitting <Enter> works like pressing the OK button. Hitting
|
||||
<Esc> works like pressing the Cancel button.
|
||||
NOTE: Command-line completion is not supported.
|
||||
|
||||
inputlist({textlist}) *inputlist()*
|
||||
{textlist} must be a |List| of strings. This |List| is
|
||||
|
@ -244,6 +244,10 @@ Lua interface (|if_lua.txt|):
|
||||
- Lua has direct access to Nvim |API| via `vim.api`.
|
||||
- Currently, most legacy Vim features are missing.
|
||||
|
||||
|input()| and |inputdialog()| gained support for each other’s features (return
|
||||
on cancel and completion respectively) via dictionary argument (replaces all
|
||||
other arguments if used).
|
||||
|
||||
==============================================================================
|
||||
5. Missing legacy features *nvim-features-missing*
|
||||
|
||||
|
169
src/nvim/eval.c
169
src/nvim/eval.c
@ -10980,81 +10980,122 @@ void get_user_input(const typval_T *const argvars,
|
||||
typval_T *const rettv, const bool inputdialog)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const char *prompt = tv_get_string_chk(&argvars[0]);
|
||||
int cmd_silent_save = cmd_silent;
|
||||
int xp_type = EXPAND_NOTHING;
|
||||
char_u *xp_arg = NULL;
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = NULL;
|
||||
|
||||
cmd_silent = FALSE; /* Want to see the prompt. */
|
||||
if (prompt != NULL) {
|
||||
// Only the part of the message after the last NL is considered as
|
||||
// prompt for the command line.
|
||||
const char *p = strrchr(prompt, '\n');
|
||||
if (p == NULL) {
|
||||
p = prompt;
|
||||
} else {
|
||||
p++;
|
||||
msg_start();
|
||||
msg_clr_eos();
|
||||
msg_puts_attr_len(prompt, p - prompt, echo_attr);
|
||||
msg_didout = false;
|
||||
msg_starthere();
|
||||
}
|
||||
cmdline_row = msg_row;
|
||||
|
||||
const char *defstr = "";
|
||||
char buf[NUMBUFLEN];
|
||||
const char *prompt = "";
|
||||
const char *defstr = "";
|
||||
const char *cancelreturn = NULL;
|
||||
const char *xp_name = NULL;
|
||||
char prompt_buf[NUMBUFLEN];
|
||||
char defstr_buf[NUMBUFLEN];
|
||||
char cancelreturn_buf[NUMBUFLEN];
|
||||
char xp_name_buf[NUMBUFLEN];
|
||||
if (argvars[0].v_type == VAR_DICT) {
|
||||
if (argvars[1].v_type != VAR_UNKNOWN) {
|
||||
defstr = tv_get_string_buf_chk(&argvars[1], buf);
|
||||
if (defstr != NULL) {
|
||||
stuffReadbuffSpec(defstr);
|
||||
emsgf(_("E5050: {opts} must be the only argument"));
|
||||
return;
|
||||
}
|
||||
const dict_T *const dict = argvars[0].vval.v_dict;
|
||||
prompt = tv_dict_get_string_buf_chk(dict, S_LEN("prompt"), prompt_buf, "");
|
||||
if (prompt == NULL) {
|
||||
return;
|
||||
}
|
||||
defstr = tv_dict_get_string_buf_chk(dict, S_LEN("default"), defstr_buf, "");
|
||||
if (defstr == NULL) {
|
||||
return;
|
||||
}
|
||||
char def[1] = { 0 };
|
||||
cancelreturn = tv_dict_get_string_buf_chk(dict, S_LEN("cancelreturn"),
|
||||
cancelreturn_buf, def);
|
||||
if (cancelreturn == NULL) { // error
|
||||
return;
|
||||
}
|
||||
if (*cancelreturn == NUL) {
|
||||
cancelreturn = NULL;
|
||||
}
|
||||
xp_name = tv_dict_get_string_buf_chk(dict, S_LEN("completion"),
|
||||
xp_name_buf, def);
|
||||
if (xp_name == NULL) { // error
|
||||
return;
|
||||
}
|
||||
if (xp_name == def) { // default to NULL
|
||||
xp_name = NULL;
|
||||
}
|
||||
} else {
|
||||
prompt = tv_get_string_buf_chk(&argvars[0], prompt_buf);
|
||||
if (prompt == NULL) {
|
||||
return;
|
||||
}
|
||||
if (argvars[1].v_type != VAR_UNKNOWN) {
|
||||
defstr = tv_get_string_buf_chk(&argvars[1], defstr_buf);
|
||||
if (defstr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN) {
|
||||
char buf2[NUMBUFLEN];
|
||||
// input() with a third argument: completion
|
||||
rettv->vval.v_string = NULL;
|
||||
|
||||
const char *const xp_name = tv_get_string_buf_chk(&argvars[2], buf2);
|
||||
if (xp_name == NULL) {
|
||||
if (argvars[2].v_type != VAR_UNKNOWN) {
|
||||
const char *const arg2 = tv_get_string_buf_chk(&argvars[2],
|
||||
cancelreturn_buf);
|
||||
if (arg2 == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int xp_namelen = (int)strlen(xp_name);
|
||||
|
||||
uint32_t argt;
|
||||
if (parse_compl_arg((char_u *)xp_name, xp_namelen, &xp_type, &argt,
|
||||
&xp_arg) == FAIL) {
|
||||
return;
|
||||
if (inputdialog) {
|
||||
cancelreturn = arg2;
|
||||
} else {
|
||||
xp_name = arg2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defstr != NULL) {
|
||||
int save_ex_normal_busy = ex_normal_busy;
|
||||
ex_normal_busy = 0;
|
||||
rettv->vval.v_string =
|
||||
getcmdline_prompt(inputsecret_flag ? NUL : '@', (char_u *)p, echo_attr,
|
||||
xp_type, xp_arg);
|
||||
ex_normal_busy = save_ex_normal_busy;
|
||||
}
|
||||
if (inputdialog && rettv->vval.v_string == NULL
|
||||
&& argvars[1].v_type != VAR_UNKNOWN
|
||||
&& argvars[2].v_type != VAR_UNKNOWN) {
|
||||
char buf[NUMBUFLEN];
|
||||
rettv->vval.v_string = (char_u *)xstrdup(tv_get_string_buf(
|
||||
&argvars[2], buf));
|
||||
}
|
||||
|
||||
xfree(xp_arg);
|
||||
|
||||
/* since the user typed this, no need to wait for return */
|
||||
need_wait_return = FALSE;
|
||||
msg_didout = FALSE;
|
||||
}
|
||||
|
||||
int xp_type = EXPAND_NOTHING;
|
||||
char *xp_arg = NULL;
|
||||
if (xp_name != NULL) {
|
||||
// input() with a third argument: completion
|
||||
const int xp_namelen = (int)strlen(xp_name);
|
||||
|
||||
uint32_t argt;
|
||||
if (parse_compl_arg((char_u *)xp_name, xp_namelen, &xp_type,
|
||||
&argt, (char_u **)&xp_arg) == FAIL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int cmd_silent_save = cmd_silent;
|
||||
|
||||
cmd_silent = false; // Want to see the prompt.
|
||||
// Only the part of the message after the last NL is considered as
|
||||
// prompt for the command line.
|
||||
const char *p = strrchr(prompt, '\n');
|
||||
if (p == NULL) {
|
||||
p = prompt;
|
||||
} else {
|
||||
p++;
|
||||
msg_start();
|
||||
msg_clr_eos();
|
||||
msg_puts_attr_len(prompt, p - prompt, echo_attr);
|
||||
msg_didout = false;
|
||||
msg_starthere();
|
||||
}
|
||||
cmdline_row = msg_row;
|
||||
|
||||
stuffReadbuffSpec(defstr);
|
||||
|
||||
int save_ex_normal_busy = ex_normal_busy;
|
||||
ex_normal_busy = 0;
|
||||
rettv->vval.v_string =
|
||||
getcmdline_prompt(inputsecret_flag ? NUL : '@', (char_u *)p, echo_attr,
|
||||
xp_type, (char_u *)xp_arg);
|
||||
ex_normal_busy = save_ex_normal_busy;
|
||||
|
||||
if (rettv->vval.v_string == NULL && cancelreturn != NULL) {
|
||||
rettv->vval.v_string = (char_u *)xstrdup(cancelreturn);
|
||||
}
|
||||
|
||||
xfree(xp_arg);
|
||||
|
||||
// Since the user typed this, no need to wait for return.
|
||||
need_wait_return = false;
|
||||
msg_didout = false;
|
||||
cmd_silent = cmd_silent_save;
|
||||
}
|
||||
|
||||
|
@ -1210,7 +1210,8 @@ char *tv_dict_get_string(const dict_T *const d, const char *const key,
|
||||
///
|
||||
/// @param[in] d Dictionary to get item from.
|
||||
/// @param[in] key Dictionary key.
|
||||
/// @param[in] numbuf Numbuf for.
|
||||
/// @param[in] numbuf Buffer for non-string items converted to strings, at
|
||||
/// least of #NUMBUFLEN length.
|
||||
///
|
||||
/// @return NULL if key does not exist, empty string in case of type error,
|
||||
/// string item value otherwise.
|
||||
@ -1225,6 +1226,32 @@ const char *tv_dict_get_string_buf(const dict_T *const d, const char *const key,
|
||||
return tv_get_string_buf(&di->di_tv, numbuf);
|
||||
}
|
||||
|
||||
/// Get a string item from a dictionary
|
||||
///
|
||||
/// @param[in] d Dictionary to get item from.
|
||||
/// @param[in] key Dictionary key.
|
||||
/// @param[in] key_len Key length.
|
||||
/// @param[in] numbuf Buffer for non-string items converted to strings, at
|
||||
/// least of #NUMBUFLEN length.
|
||||
/// @param[in] def Default return when key does not exist.
|
||||
///
|
||||
/// @return `def` when key does not exist,
|
||||
/// NULL in case of type error,
|
||||
/// string item value in case of success.
|
||||
const char *tv_dict_get_string_buf_chk(const dict_T *const d,
|
||||
const char *const key,
|
||||
const ptrdiff_t key_len,
|
||||
char *const numbuf,
|
||||
const char *const def)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
const dictitem_T *const di = tv_dict_find(d, key, key_len);
|
||||
if (di == NULL) {
|
||||
return def;
|
||||
}
|
||||
return tv_get_string_buf_chk(&di->di_tv, numbuf);
|
||||
}
|
||||
|
||||
/// Get a function from a dictionary
|
||||
///
|
||||
/// @param[in] d Dictionary to get callback from.
|
||||
|
@ -1,9 +1,13 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
|
||||
local eq = helpers.eq
|
||||
local feed = helpers.feed
|
||||
local meths = helpers.meths
|
||||
local clear = helpers.clear
|
||||
local source = helpers.source
|
||||
local command = helpers.command
|
||||
local exc_exec = helpers.exc_exec
|
||||
|
||||
local screen
|
||||
|
||||
@ -11,28 +15,352 @@ before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(25, 5)
|
||||
screen:attach()
|
||||
source([[
|
||||
hi Test ctermfg=Red guifg=Red term=bold
|
||||
function CustomCompl(...)
|
||||
return 'TEST'
|
||||
endfunction
|
||||
function CustomListCompl(...)
|
||||
return ['FOO']
|
||||
endfunction
|
||||
]])
|
||||
screen:set_default_attr_ids({
|
||||
EOB={bold = true, foreground = Screen.colors.Blue1},
|
||||
T={foreground=Screen.colors.Red},
|
||||
})
|
||||
end)
|
||||
|
||||
describe('input()', function()
|
||||
it('works correctly with multiline prompts', function()
|
||||
it('works with multiline prompts', function()
|
||||
feed([[:call input("Test\nFoo")<CR>]])
|
||||
screen:expect([[
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
Test |
|
||||
Foo^ |
|
||||
]], {{bold=true, foreground=Screen.colors.Blue}})
|
||||
]])
|
||||
end)
|
||||
it('works correctly with multiline prompts and :echohl', function()
|
||||
command('hi Test ctermfg=Red guifg=Red term=bold')
|
||||
it('works with multiline prompts and :echohl', function()
|
||||
feed([[:echohl Test | call input("Test\nFoo")<CR>]])
|
||||
screen:expect([[
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{2:Test} |
|
||||
{2:Foo}^ |
|
||||
]], {{bold=true, foreground=Screen.colors.Blue}, {foreground=Screen.colors.Red}})
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Test} |
|
||||
{T:Foo}^ |
|
||||
]])
|
||||
command('redraw!')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo}^ |
|
||||
]])
|
||||
end)
|
||||
it('allows unequal numeric arguments when using multiple args', function()
|
||||
command('echohl Test')
|
||||
feed([[:call input(1, 2)<CR>]])
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:1}2^ |
|
||||
]])
|
||||
feed('<BS>')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:1}^ |
|
||||
]])
|
||||
end)
|
||||
it('allows unequal numeric values when using {opts} dictionary', function()
|
||||
command('echohl Test')
|
||||
meths.set_var('opts', {prompt=1, default=2, cancelreturn=3})
|
||||
feed([[:echo input(opts)<CR>]])
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:1}2^ |
|
||||
]])
|
||||
feed('<BS>')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:1}^ |
|
||||
]])
|
||||
feed('<Esc>')
|
||||
screen:expect([[
|
||||
^ |
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:3} |
|
||||
]])
|
||||
end)
|
||||
it('works with redraw', function()
|
||||
command('echohl Test')
|
||||
meths.set_var('opts', {prompt='Foo>', default='Bar'})
|
||||
feed([[:echo inputdialog(opts)<CR>]])
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo>}Bar^ |
|
||||
]])
|
||||
command('redraw!')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo>}Bar^ |
|
||||
]])
|
||||
feed('<BS>')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo>}Ba^ |
|
||||
]])
|
||||
command('redraw!')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo>}Ba^ |
|
||||
]])
|
||||
end)
|
||||
it('allows omitting everything with dictionary argument', function()
|
||||
command('echohl Test')
|
||||
feed([[:call input({})<CR>]])
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
^ |
|
||||
]])
|
||||
end)
|
||||
it('supports completion', function()
|
||||
feed(':let var = input("", "", "custom,CustomCompl")<CR>')
|
||||
feed('<Tab><CR>')
|
||||
eq('TEST', meths.get_var('var'))
|
||||
|
||||
feed(':let var = input({"completion": "customlist,CustomListCompl"})<CR>')
|
||||
feed('<Tab><CR>')
|
||||
eq('FOO', meths.get_var('var'))
|
||||
end)
|
||||
it('supports cancelreturn', function()
|
||||
feed(':let var = input({"cancelreturn": "BAR"})<CR>')
|
||||
feed('<Esc>')
|
||||
eq('BAR', meths.get_var('var'))
|
||||
end)
|
||||
it('supports default string', function()
|
||||
feed(':let var = input("", "DEF1")<CR>')
|
||||
feed('<CR>')
|
||||
eq('DEF1', meths.get_var('var'))
|
||||
|
||||
feed(':let var = input({"default": "DEF2"})<CR>')
|
||||
feed('<CR>')
|
||||
eq('DEF2', meths.get_var('var'))
|
||||
end)
|
||||
it('errors out on invalid inputs', function()
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call input([])'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call input("", [])'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call input("", "", [])'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call input({"prompt": []})'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call input({"cancelreturn": []})'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call input({"default": []})'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call input({"completion": []})'))
|
||||
eq('Vim(call):E5050: {opts} must be the only argument',
|
||||
exc_exec('call input({}, "default")'))
|
||||
eq('Vim(call):E118: Too many arguments for function: input',
|
||||
exc_exec('call input("prompt> ", "default", "file", "extra")'))
|
||||
end)
|
||||
end)
|
||||
describe('inputdialog()', function()
|
||||
it('works with multiline prompts', function()
|
||||
feed([[:call inputdialog("Test\nFoo")<CR>]])
|
||||
screen:expect([[
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
Test |
|
||||
Foo^ |
|
||||
]])
|
||||
end)
|
||||
it('works with multiline prompts and :echohl', function()
|
||||
feed([[:echohl Test | call inputdialog("Test\nFoo")<CR>]])
|
||||
screen:expect([[
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Test} |
|
||||
{T:Foo}^ |
|
||||
]])
|
||||
command('redraw!')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo}^ |
|
||||
]])
|
||||
end)
|
||||
it('allows unequal numeric arguments when using multiple args', function()
|
||||
command('echohl Test')
|
||||
feed([[:call inputdialog(1, 2)<CR>]])
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:1}2^ |
|
||||
]])
|
||||
feed('<BS>')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:1}^ |
|
||||
]])
|
||||
end)
|
||||
it('allows unequal numeric values when using {opts} dictionary', function()
|
||||
command('echohl Test')
|
||||
meths.set_var('opts', {prompt=1, default=2, cancelreturn=3})
|
||||
feed([[:echo input(opts)<CR>]])
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:1}2^ |
|
||||
]])
|
||||
feed('<BS>')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:1}^ |
|
||||
]])
|
||||
feed('<Esc>')
|
||||
screen:expect([[
|
||||
^ |
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:3} |
|
||||
]])
|
||||
end)
|
||||
it('works with redraw', function()
|
||||
command('echohl Test')
|
||||
meths.set_var('opts', {prompt='Foo>', default='Bar'})
|
||||
feed([[:echo input(opts)<CR>]])
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo>}Bar^ |
|
||||
]])
|
||||
command('redraw!')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo>}Bar^ |
|
||||
]])
|
||||
feed('<BS>')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo>}Ba^ |
|
||||
]])
|
||||
command('redraw!')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{T:Foo>}Ba^ |
|
||||
]])
|
||||
end)
|
||||
it('allows omitting everything with dictionary argument', function()
|
||||
command('echohl Test')
|
||||
feed(':echo inputdialog({})<CR>')
|
||||
screen:expect([[
|
||||
|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
{EOB:~ }|
|
||||
^ |
|
||||
]])
|
||||
end)
|
||||
it('supports completion', function()
|
||||
feed(':let var = inputdialog({"completion": "customlist,CustomListCompl"})<CR>')
|
||||
feed('<Tab><CR>')
|
||||
eq('FOO', meths.get_var('var'))
|
||||
end)
|
||||
it('supports cancelreturn', function()
|
||||
feed(':let var = inputdialog("", "", "CR1")<CR>')
|
||||
feed('<Esc>')
|
||||
eq('CR1', meths.get_var('var'))
|
||||
|
||||
feed(':let var = inputdialog({"cancelreturn": "BAR"})<CR>')
|
||||
feed('<Esc>')
|
||||
eq('BAR', meths.get_var('var'))
|
||||
end)
|
||||
it('supports default string', function()
|
||||
feed(':let var = inputdialog("", "DEF1")<CR>')
|
||||
feed('<CR>')
|
||||
eq('DEF1', meths.get_var('var'))
|
||||
|
||||
feed(':let var = inputdialog({"default": "DEF2"})<CR>')
|
||||
feed('<CR>')
|
||||
eq('DEF2', meths.get_var('var'))
|
||||
end)
|
||||
it('errors out on invalid inputs', function()
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call inputdialog([])'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call inputdialog("", [])'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call inputdialog("", "", [])'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call inputdialog({"prompt": []})'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call inputdialog({"cancelreturn": []})'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call inputdialog({"default": []})'))
|
||||
eq('Vim(call):E730: using List as a String',
|
||||
exc_exec('call inputdialog({"completion": []})'))
|
||||
eq('Vim(call):E5050: {opts} must be the only argument',
|
||||
exc_exec('call inputdialog({}, "default")'))
|
||||
eq('Vim(call):E118: Too many arguments for function: inputdialog',
|
||||
exc_exec('call inputdialog("prompt> ", "default", "file", "extra")'))
|
||||
end)
|
||||
end)
|
||||
|
@ -1751,6 +1751,55 @@ describe('typval.c', function()
|
||||
eq('2', s)
|
||||
end)
|
||||
end)
|
||||
describe('get_string_buf_chk()', function()
|
||||
local function tv_dict_get_string_buf_chk(d, key, len, buf, def, emsg)
|
||||
buf = buf or ffi.gc(lib.xmalloc(lib.NUMBUFLEN), lib.xfree)
|
||||
def = def or ffi.gc(lib.xstrdup('DEFAULT'), lib.xfree)
|
||||
len = len or #key
|
||||
alloc_log:clear()
|
||||
local ret = check_emsg(function() return lib.tv_dict_get_string_buf_chk(d, key, len, buf, def) end,
|
||||
emsg)
|
||||
local s_ret = (ret ~= nil) and ffi.string(ret) or nil
|
||||
if not emsg then
|
||||
alloc_log:check({})
|
||||
end
|
||||
return s_ret, ret, buf, def
|
||||
end
|
||||
itp('works with NULL dict', function()
|
||||
eq('DEFAULT', tv_dict_get_string_buf_chk(nil, 'test'))
|
||||
end)
|
||||
itp('works', function()
|
||||
local lua_d = {
|
||||
['']={},
|
||||
t=1,
|
||||
te=int(2),
|
||||
tes=empty_list,
|
||||
test='tset',
|
||||
testt=5,
|
||||
}
|
||||
local d = dict(lua_d)
|
||||
alloc_log:clear()
|
||||
eq(lua_d, dct2tbl(d))
|
||||
alloc_log:check({})
|
||||
local s, r, b, def
|
||||
s, r, b, def = tv_dict_get_string_buf_chk(d, 'test')
|
||||
neq(r, b)
|
||||
neq(r, def)
|
||||
eq('tset', s)
|
||||
s, r, b, def = tv_dict_get_string_buf_chk(d, 'test', 1, nil, nil, 'E806: using Float as a String')
|
||||
neq(r, b)
|
||||
neq(r, def)
|
||||
eq(nil, s)
|
||||
s, r, b, def = tv_dict_get_string_buf_chk(d, 'te')
|
||||
eq(r, b)
|
||||
neq(r, def)
|
||||
eq('2', s)
|
||||
s, r, b, def = tv_dict_get_string_buf_chk(d, 'TEST')
|
||||
eq(r, def)
|
||||
neq(r, b)
|
||||
eq('DEFAULT', s)
|
||||
end)
|
||||
end)
|
||||
describe('get_callback()', function()
|
||||
local function tv_dict_get_callback(d, key, key_len, emsg)
|
||||
key_len = key_len or #key
|
||||
|
Loading…
Reference in New Issue
Block a user