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

View File

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

View File

@@ -332,6 +332,7 @@ return {
setcharpos={args=2, base=2}, setcharpos={args=2, base=2},
setcharsearch={args=1, base=1}, setcharsearch={args=1, base=1},
setcmdpos={args=1, base=1}, setcmdpos={args=1, base=1},
setcmdline={args={1, 2}, base=1},
setcursorcharpos={args={1, 3}, base=1}, setcursorcharpos={args={1, 3}, base=1},
setenv={args=2, base=2}, setenv={args=2, base=2},
setfperm={args=2, base=1}, 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 /// "setcmdpos()" function
static void f_setcmdpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_setcmdpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{ {

View File

@@ -2373,9 +2373,9 @@ end:
return cmdpreview_type != 0; 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)) { if (has_event(EVENT_CMDLINECHANGED)) {
TryState tstate; TryState tstate;
Error err = ERROR_INIT; Error err = ERROR_INIT;
@@ -2383,7 +2383,7 @@ static int command_line_changed(CommandLineState *s)
dict_T *dict = get_v_event(&save_v_event); dict_T *dict = get_v_event(&save_v_event);
char firstcbuf[2]; char firstcbuf[2];
firstcbuf[0] = (char)(s->firstc > 0 ? s->firstc : '-'); firstcbuf[0] = (char)firstc;
firstcbuf[1] = 0; firstcbuf[1] = 0;
// set v:event to a dictionary with information about the commandline // set v:event to a dictionary with information about the commandline
@@ -2403,6 +2403,12 @@ static int command_line_changed(CommandLineState *s)
redrawcmd(); redrawcmd();
} }
} }
}
static int command_line_changed(CommandLineState *s)
{
// Trigger CmdlineChanged autocommands.
do_autocmd_cmdlinechanged(s->firstc > 0 ? s->firstc : '-');
if (s->firstc == ':' if (s->firstc == ':'
&& current_sctx.sc_sid == 0 // only if interactive && current_sctx.sc_sid == 0 // only if interactive
@@ -3991,6 +3997,32 @@ int get_cmdline_screen_pos(void)
return p->cmdspos; 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. * Set the command line byte position to "pos". Zero is the first position.
* Only works when the command line is being edited. * 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& set wildoptions& wildmenu&
endfunc 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 " vim: shiftwidth=2 sts=2 expandtab