Skip to content

Commit 07ea5f1

Browse files
Shougobrammool
authored andcommitted
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 #10869)
1 parent 5ff595d commit 07ea5f1

File tree

8 files changed

+134
-11
lines changed

8 files changed

+134
-11
lines changed

runtime/doc/builtin.txt

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ setbufvar({buf}, {varname}, {val})
505505
setcellwidths({list}) none set character cell width overrides
506506
setcharpos({expr}, {list}) Number set the {expr} position to {list}
507507
setcharsearch({dict}) Dict set character search from {dict}
508+
setcmdline({str} [, {pos}]) Number set command-line
508509
setcmdpos({pos}) Number set cursor position in command-line
509510
setcursorcharpos({list}) Number move cursor to position in {list}
510511
setenv({name}, {val}) none set environment variable
@@ -3425,7 +3426,8 @@ getcmdcompltype() *getcmdcompltype()*
34253426
Only works when the command line is being edited, thus
34263427
requires use of |c_CTRL-\_e| or |c_CTRL-R_=|.
34273428
See |:command-completion| for the return string.
3428-
Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|.
3429+
Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
3430+
|setcmdline()|.
34293431
Returns an empty string when completion is not defined.
34303432

34313433
getcmdline() *getcmdline()*
@@ -3434,7 +3436,8 @@ getcmdline() *getcmdline()*
34343436
|c_CTRL-R_=|.
34353437
Example: >
34363438
:cmap <F7> <C-\>eescape(getcmdline(), ' \')<CR>
3437-
< Also see |getcmdtype()|, |getcmdpos()| and |setcmdpos()|.
3439+
< Also see |getcmdtype()|, |getcmdpos()|, |setcmdpos()| and
3440+
|setcmdline()|.
34383441
Returns an empty string when entering a password or using
34393442
|inputsecret()|.
34403443

@@ -3444,7 +3447,8 @@ getcmdpos() *getcmdpos()*
34443447
Only works when editing the command line, thus requires use of
34453448
|c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping.
34463449
Returns 0 otherwise.
3447-
Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|.
3450+
Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
3451+
|setcmdline()|.
34483452

34493453
getcmdscreenpos() *getcmdscreenpos()*
34503454
Return the screen position of the cursor in the command line
@@ -3453,7 +3457,8 @@ getcmdscreenpos() *getcmdscreenpos()*
34533457
Only works when editing the command line, thus requires use of
34543458
|c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping.
34553459
Returns 0 otherwise.
3456-
Also see |getcmdpos()|, |setcmdpos()|.
3460+
Also see |getcmdpos()|, |setcmdpos()|, |getcmdline()| and
3461+
|setcmdline()|.
34573462

34583463
getcmdtype() *getcmdtype()*
34593464
Return the current command-line type. Possible return values
@@ -7925,6 +7930,16 @@ setcharsearch({dict}) *setcharsearch()*
79257930
Can also be used as a |method|: >
79267931
SavedSearch()->setcharsearch()
79277932
7933+
setcmdline({str} [, {pos}]) *setcmdline()*
7934+
Set the command line to {str} and set the cursor position to
7935+
{pos}.
7936+
If {pos} is omitted, the cursor is positioned after the text.
7937+
Returns 0 when successful, 1 when not editing the command
7938+
line.
7939+
7940+
Can also be used as a |method|: >
7941+
GetText()->setcmdline()
7942+
79287943
setcmdpos({pos}) *setcmdpos()*
79297944
Set the cursor position in the command line to byte position
79307945
{pos}. The first position is 1.
@@ -7937,8 +7952,8 @@ setcmdpos({pos}) *setcmdpos()*
79377952
before inserting the resulting text.
79387953
When the number is too big the cursor is put at the end of the
79397954
line. A number smaller than one has undefined results.
7940-
Returns FALSE when successful, TRUE when not editing the
7941-
command line.
7955+
Returns 0 when successful, 1 when not editing the command
7956+
line.
79427957

79437958
Can also be used as a |method|: >
79447959
GetPos()->setcmdpos()

runtime/doc/usr_41.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,7 @@ Command line: *command-line-functions*
10381038
getcmdpos() get position of the cursor in the command line
10391039
getcmdscreenpos() get screen position of the cursor in the
10401040
command line
1041+
setcmdline() set the current command line
10411042
setcmdpos() set position of the cursor in the command line
10421043
getcmdtype() return the current command-line type
10431044
getcmdwintype() return the current command-line window type

src/evalfunc.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,6 +2369,8 @@ static funcentry_T global_functions[] =
23692369
ret_number_bool, f_setcharpos},
23702370
{"setcharsearch", 1, 1, FEARG_1, arg1_dict_any,
23712371
ret_void, f_setcharsearch},
2372+
{"setcmdline", 1, 2, FEARG_1, arg2_string_number,
2373+
ret_number_bool, f_setcmdline},
23722374
{"setcmdpos", 1, 1, FEARG_1, arg1_number,
23732375
ret_number_bool, f_setcmdpos},
23742376
{"setcursorcharpos", 1, 3, FEARG_1, arg13_cursor,
@@ -3607,7 +3609,6 @@ f_debugbreak(typval_T *argvars, typval_T *rettv)
36073609
f_deepcopy(typval_T *argvars, typval_T *rettv)
36083610
{
36093611
varnumber_T noref = 0;
3610-
int copyID;
36113612

36123613
if (in_vim9script()
36133614
&& (check_for_opt_bool_arg(argvars, 1) == FAIL))
@@ -3618,10 +3619,8 @@ f_deepcopy(typval_T *argvars, typval_T *rettv)
36183619
if (noref < 0 || noref > 1)
36193620
semsg(_(e_using_number_as_bool_nr), noref);
36203621
else
3621-
{
3622-
copyID = get_copyID();
3623-
item_copy(&argvars[0], rettv, TRUE, TRUE, noref == 0 ? copyID : 0);
3624-
}
3622+
item_copy(&argvars[0], rettv, TRUE, TRUE,
3623+
noref == 0 ? get_copyID() : 0);
36253624
}
36263625

36273626
/*

src/ex_getln.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4211,6 +4211,35 @@ f_getcmdscreenpos(typval_T *argvars UNUSED, typval_T *rettv)
42114211
rettv->vval.v_number = get_cmdline_screen_pos() + 1;
42124212
}
42134213

4214+
// Set the command line str to "str".
4215+
// Returns 1 when failed, 0 when OK.
4216+
int
4217+
set_cmdline_str(char_u *str, int pos)
4218+
{
4219+
cmdline_info_T *p = get_ccline_ptr();
4220+
int cmdline_type;
4221+
int len;
4222+
4223+
if (p == NULL)
4224+
return 1;
4225+
4226+
len = (int)STRLEN(str);
4227+
realloc_cmdbuff(len + 1);
4228+
p->cmdlen = len;
4229+
STRCPY(p->cmdbuff, str);
4230+
4231+
p->cmdpos = pos < 0 || pos > p->cmdlen ? p->cmdlen : pos;
4232+
new_cmdpos = p->cmdpos;
4233+
4234+
redrawcmd();
4235+
4236+
// Trigger CmdlineChanged autocommands.
4237+
cmdline_type = ccline.cmdfirstc == NUL ? '-' : ccline.cmdfirstc;
4238+
trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINECHANGED);
4239+
4240+
return 0;
4241+
}
4242+
42144243
/*
42154244
* Set the command line byte position to "pos". Zero is the first position.
42164245
* Only works when the command line is being edited.
@@ -4234,6 +4263,35 @@ set_cmdline_pos(
42344263
return 0;
42354264
}
42364265

4266+
// "setcmdline()" function
4267+
void
4268+
f_setcmdline(typval_T *argvars, typval_T *rettv)
4269+
{
4270+
int pos = -1;
4271+
4272+
if (argvars[0].v_type != VAR_STRING || argvars[0].vval.v_string == NULL)
4273+
{
4274+
emsg(_(e_string_required));
4275+
return;
4276+
}
4277+
4278+
if (argvars[1].v_type != VAR_UNKNOWN)
4279+
{
4280+
int error = FALSE;
4281+
4282+
pos = (int)tv_get_number_chk(&argvars[1], &error) - 1;
4283+
if (error)
4284+
return;
4285+
if (pos < 0)
4286+
{
4287+
emsg(_(e_argument_must_be_positive));
4288+
return;
4289+
}
4290+
}
4291+
4292+
rettv->vval.v_number = set_cmdline_str(argvars[0].vval.v_string, pos);
4293+
}
4294+
42374295
/*
42384296
* "setcmdpos()" function
42394297
*/

src/proto/ex_getln.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ void f_getcmdcompltype(typval_T *argvars, typval_T *rettv);
3434
void f_getcmdline(typval_T *argvars, typval_T *rettv);
3535
void f_getcmdpos(typval_T *argvars, typval_T *rettv);
3636
void f_getcmdscreenpos(typval_T *argvars, typval_T *rettv);
37+
int set_cmdline_str(char_u *str, int pos);
38+
void f_setcmdline(typval_T *argvars, typval_T *rettv);
3739
void f_setcmdpos(typval_T *argvars, typval_T *rettv);
3840
void f_getcmdtype(typval_T *argvars, typval_T *rettv);
3941
int get_cmdline_firstc(void);

src/testdir/test_cmdline.vim

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3262,4 +3262,44 @@ func Test_wildmenu_pum_disable_while_shown()
32623262
set wildoptions& wildmenu&
32633263
endfunc
32643264

3265+
func Test_setcmdline()
3266+
func SetText(text, pos)
3267+
call assert_equal(0, setcmdline(a:text))
3268+
call assert_equal(a:text, getcmdline())
3269+
call assert_equal(len(a:text) + 1, getcmdpos())
3270+
3271+
call assert_equal(0, setcmdline(a:text, a:pos))
3272+
call assert_equal(a:text, getcmdline())
3273+
call assert_equal(a:pos, getcmdpos())
3274+
3275+
call assert_fails('call setcmdline("' .. a:text .. '", -1)', 'E487:')
3276+
call assert_fails('call setcmdline({}, 0)', 'E928:')
3277+
call assert_fails('call setcmdline("' .. a:text .. '", {})', 'E728:')
3278+
3279+
return ''
3280+
endfunc
3281+
3282+
call feedkeys(":\<C-R>=SetText('set rtp?', 2)\<CR>\<CR>", 'xt')
3283+
call assert_equal('set rtp?', @:)
3284+
3285+
" setcmdline() returns 1 when not editing the command line.
3286+
call assert_equal(1, 'foo'->setcmdline())
3287+
3288+
" Called in custom function
3289+
func CustomComplete(A, L, P)
3290+
call assert_equal(0, setcmdline("DoCmd "))
3291+
return "January\nFebruary\nMars\n"
3292+
endfunc
3293+
3294+
com! -nargs=* -complete=custom,CustomComplete DoCmd :
3295+
call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx')
3296+
call assert_equal('"DoCmd January February Mars', @:)
3297+
3298+
" Called in <expr>
3299+
cnoremap <expr>a setcmdline('let foo=')
3300+
call feedkeys(":a\<CR>", 'tx')
3301+
call assert_equal('let foo=0', @:)
3302+
cunmap a
3303+
endfunc
3304+
32653305
" vim: shiftwidth=2 sts=2 expandtab

src/testdir/test_vim9_builtin.vim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3657,6 +3657,12 @@ def Test_setcharsearch()
36573657
assert_equal(d, getcharsearch())
36583658
enddef
36593659

3660+
def Test_setcmdline()
3661+
v9.CheckDefAndScriptSuccess(['setcmdline("ls", 2)'])
3662+
v9.CheckDefAndScriptFailure(['setcmdline(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E928: String required'])
3663+
v9.CheckDefAndScriptFailure(['setcmdline("ls", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1030: Using a String as a Number'])
3664+
enddef
3665+
36603666
def Test_setcmdpos()
36613667
v9.CheckDefAndScriptFailure(['setcmdpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1'])
36623668
enddef

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,8 @@ static char *(features[]) =
707707

708708
static int included_patches[] =
709709
{ /* Add new patch number below this line */
710+
/**/
711+
285,
710712
/**/
711713
284,
712714
/**/

0 commit comments

Comments
 (0)