vim-patch:9.0.0285: it is not easy to change the command line from a plugin (#19979)

vim-patch:9.0.0285: it is not easy to change the command line from a plugin

Problem:    It is not easy to change the command line from a plugin.
Solution:   Add setcmdline(). (Shougo Matsushita, closes vim/vim#10869)
07ea5f1509
This commit is contained in:
Shougo
2022-08-29 14:11:52 +09:00
committed by GitHub
parent 1dcaa75a65
commit 253f0ffd8d
6 changed files with 123 additions and 9 deletions

View File

@@ -400,6 +400,7 @@ setbufvar({buf}, {varname}, {val}) set {varname} in buffer {buf} to {val}
setcellwidths({list}) none set character cell width overrides
setcharpos({expr}, {list}) Number set the {expr} position to {list}
setcharsearch({dict}) Dict set character search from {dict}
setcmdline({str} [, {pos}]) Number set command-line
setcmdpos({pos}) Number set cursor position in command-line
setcursorcharpos({list}) Number move cursor to position in {list}
setenv({name}, {val}) none set environment variable
@@ -2880,7 +2881,8 @@ getcmdcompltype() *getcmdcompltype()*
Only works when the command line is being edited, thus
requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
See |:command-completion| for the return string.
Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|.
Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
|setcmdline()|.
Returns an empty string when completion is not defined.
getcmdline() *getcmdline()*
@@ -2889,7 +2891,8 @@ getcmdline() *getcmdline()*
|c_CTRL-R_=|.
Example: >
:cmap <F7> <C-\>eescape(getcmdline(), ' \')<CR>
< Also see |getcmdtype()|, |getcmdpos()| and |setcmdpos()|.
< Also see |getcmdtype()|, |getcmdpos()|, |setcmdpos()| and
|setcmdline()|.
Returns an empty string when entering a password or using
|inputsecret()|.
@@ -2899,7 +2902,8 @@ getcmdpos() *getcmdpos()*
Only works when editing the command line, thus requires use of
|c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping.
Returns 0 otherwise.
Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|.
Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
|setcmdline()|.
getcmdscreenpos() *getcmdscreenpos()*
Return the screen position of the cursor in the command line
@@ -2908,7 +2912,8 @@ getcmdscreenpos() *getcmdscreenpos()*
Only works when editing the command line, thus requires use of
|c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping.
Returns 0 otherwise.
Also see |getcmdpos()|, |setcmdpos()|.
Also see |getcmdpos()|, |setcmdpos()|, |getcmdline()| and
|setcmdline()|.
getcmdtype() *getcmdtype()*
Return the current command-line type. Possible return values
@@ -6912,6 +6917,16 @@ setcharsearch({dict}) *setcharsearch()*
Can also be used as a |method|: >
SavedSearch()->setcharsearch()
setcmdline({str} [, {pos}]) *setcmdline()*
Set the command line to {str} and set the cursor position to
{pos}.
If {pos} is omitted, the cursor is positioned after the text.
Returns 0 when successful, 1 when not editing the command
line.
Can also be used as a |method|: >
GetText()->setcmdline()
setcmdpos({pos}) *setcmdpos()*
Set the cursor position in the command line to byte position
{pos}. The first position is 1.
@@ -6924,8 +6939,8 @@ setcmdpos({pos}) *setcmdpos()*
before inserting the resulting text.
When the number is too big the cursor is put at the end of the
line. A number smaller than one has undefined results.
Returns FALSE when successful, TRUE when not editing the
command line.
Returns 0 when successful, 1 when not editing the command
line.
Can also be used as a |method|: >
GetPos()->setcmdpos()

View File

@@ -872,6 +872,7 @@ Command line: *command-line-functions*
getcmdpos() get position of the cursor in the command line
getcmdscreenpos() get screen position of the cursor in the
command line
setcmdline() set the current command line
setcmdpos() set position of the cursor in the command line
getcmdtype() return the current command-line type
getcmdwintype() return the current command-line window type

View File

@@ -332,6 +332,7 @@ return {
setcharpos={args=2, base=2},
setcharsearch={args=1, base=1},
setcmdpos={args=1, base=1},
setcmdline={args={1, 2}, base=1},
setcursorcharpos={args={1, 3}, base=1},
setenv={args=2, base=2},
setfperm={args=2, base=1},

View File

@@ -7619,6 +7619,31 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt
}
}
/// "setcmdline()" function
static void f_setcmdline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_STRING || argvars[0].vval.v_string == NULL) {
emsg(_(e_stringreq));
return;
}
int pos = -1;
if (argvars[1].v_type != VAR_UNKNOWN) {
bool error = false;
pos = (int)tv_get_number_chk(&argvars[1], &error) - 1;
if (error) {
return;
}
if (pos < 0) {
emsg(_(e_positive));
return;
}
}
rettv->vval.v_number = set_cmdline_str(argvars[0].vval.v_string, pos);
}
/// "setcmdpos()" function
static void f_setcmdpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{

View File

@@ -2373,9 +2373,9 @@ end:
return cmdpreview_type != 0;
}
static int command_line_changed(CommandLineState *s)
/// Trigger CmdlineChanged autocommands.
static void do_autocmd_cmdlinechanged(int firstc)
{
// Trigger CmdlineChanged autocommands.
if (has_event(EVENT_CMDLINECHANGED)) {
TryState tstate;
Error err = ERROR_INIT;
@@ -2383,7 +2383,7 @@ static int command_line_changed(CommandLineState *s)
dict_T *dict = get_v_event(&save_v_event);
char firstcbuf[2];
firstcbuf[0] = (char)(s->firstc > 0 ? s->firstc : '-');
firstcbuf[0] = (char)firstc;
firstcbuf[1] = 0;
// set v:event to a dictionary with information about the commandline
@@ -2403,6 +2403,12 @@ static int command_line_changed(CommandLineState *s)
redrawcmd();
}
}
}
static int command_line_changed(CommandLineState *s)
{
// Trigger CmdlineChanged autocommands.
do_autocmd_cmdlinechanged(s->firstc > 0 ? s->firstc : '-');
if (s->firstc == ':'
&& current_sctx.sc_sid == 0 // only if interactive
@@ -3991,6 +3997,32 @@ int get_cmdline_screen_pos(void)
return p->cmdspos;
}
/// Set the command line str to "str".
/// @return 1 when failed, 0 when OK.
int set_cmdline_str(const char *str, int pos)
{
CmdlineInfo *p = get_ccline_ptr();
if (p == NULL) {
return 1;
}
int len = (int)STRLEN(str);
realloc_cmdbuff(len + 1);
p->cmdlen = len;
STRCPY(p->cmdbuff, str);
p->cmdpos = pos < 0 || pos > p->cmdlen ? p->cmdlen : pos;
new_cmdpos = p->cmdpos;
redrawcmd();
// Trigger CmdlineChanged autocommands.
do_autocmd_cmdlinechanged(ccline.cmdfirstc == NUL ? '-' : ccline.cmdfirstc);
return 0;
}
/*
* Set the command line byte position to "pos". Zero is the first position.
* Only works when the command line is being edited.

View File

@@ -2185,4 +2185,44 @@ func Test_wildmenu_pum_disable_while_shown()
set wildoptions& wildmenu&
endfunc
func Test_setcmdline()
func SetText(text, pos)
call assert_equal(0, setcmdline(a:text))
call assert_equal(a:text, getcmdline())
call assert_equal(len(a:text) + 1, getcmdpos())
call assert_equal(0, setcmdline(a:text, a:pos))
call assert_equal(a:text, getcmdline())
call assert_equal(a:pos, getcmdpos())
call assert_fails('call setcmdline("' .. a:text .. '", -1)', 'E487:')
call assert_fails('call setcmdline({}, 0)', 'E928:')
call assert_fails('call setcmdline("' .. a:text .. '", {})', 'E728:')
return ''
endfunc
call feedkeys(":\<C-R>=SetText('set rtp?', 2)\<CR>\<CR>", 'xt')
call assert_equal('set rtp?', @:)
" setcmdline() returns 1 when not editing the command line.
call assert_equal(1, 'foo'->setcmdline())
" Called in custom function
func CustomComplete(A, L, P)
call assert_equal(0, setcmdline("DoCmd "))
return "January\nFebruary\nMars\n"
endfunc
com! -nargs=* -complete=custom,CustomComplete DoCmd :
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"DoCmd January February Mars', @:)
" Called in <expr>
cnoremap <expr>a setcmdline('let foo=')
call feedkeys(":a\<CR>", 'tx')
call assert_equal('let foo=0', @:)
cunmap a
endfunc
" vim: shiftwidth=2 sts=2 expandtab