Patch 9.0.0285
Problem: It is not easy to change the command line from a plugin.
Solution: Add setcmdline(). (Shougo Matsushita, closes #10869)
Files: runtime/doc/builtin.txt, runtime/doc/usr_41.txt, src/evalfunc.c,
src/ex_getln.c, src/proto/
ex_getln.pro,
src/testdir/test_cmdline.vim, src/testdir/test_vim9_builtin.vim
*** ../vim-9.0.0284/runtime/doc/builtin.txt 2022-08-26 17:52:47.886406161 +0100
--- runtime/doc/builtin.txt 2022-08-27 12:02:26.610486853 +0100
***************
*** 505,510 ****
--- 505,511 ----
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
***************
*** 3419,3425 ****
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()|.
Returns an empty string when completion is not defined.
getcmdline() *getcmdline()*
--- 3426,3433 ----
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()|, |getcmdline()| and
! |setcmdline()|.
Returns an empty string when completion is not defined.
getcmdline() *getcmdline()*
***************
*** 3428,3434 ****
|c_CTRL-R_=|.
Example: >
:cmap <F7> <C-\>eescape(getcmdline(), ' \')<CR>
! < Also see |getcmdtype()|, |getcmdpos()| and |setcmdpos()|.
Returns an empty string when entering a password or using
|inputsecret()|.
--- 3436,3443 ----
|c_CTRL-R_=|.
Example: >
:cmap <F7> <C-\>eescape(getcmdline(), ' \')<CR>
! < Also see |getcmdtype()|, |getcmdpos()|, |setcmdpos()| and
! |setcmdline()|.
Returns an empty string when entering a password or using
|inputsecret()|.
***************
*** 3438,3444 ****
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()|.
getcmdscreenpos() *getcmdscreenpos()*
Return the screen position of the cursor in the command line
--- 3447,3454 ----
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()|, |getcmdline()| and
! |setcmdline()|.
getcmdscreenpos() *getcmdscreenpos()*
Return the screen position of the cursor in the command line
***************
*** 3447,3453 ****
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()|.
getcmdtype() *getcmdtype()*
Return the current command-line type. Possible return values
--- 3457,3464 ----
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()|, |getcmdline()| and
! |setcmdline()|.
getcmdtype() *getcmdtype()*
Return the current command-line type. Possible return values
***************
*** 7914,7919 ****
--- 7930,7945 ----
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.
***************
*** 7926,7933 ****
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.
Can also be used as a |method|: >
GetPos()->setcmdpos()
--- 7952,7959 ----
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 0 when successful, 1 when not editing the command
! line.
Can also be used as a |method|: >
GetPos()->setcmdpos()
*** ../vim-9.0.0284/runtime/doc/usr_41.txt 2022-08-22 13:14:31.892769316 +0100
--- runtime/doc/usr_41.txt 2022-08-27 11:59:20.763638005 +0100
***************
*** 1037,1042 ****
--- 1038,1044 ----
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
*** ../vim-9.0.0284/src/evalfunc.c 2022-08-26 21:33:00.662738976 +0100
--- src/evalfunc.c 2022-08-27 12:04:21.213870737 +0100
***************
*** 2369,2374 ****
--- 2369,2376 ----
ret_number_bool, f_setcharpos},
{"setcharsearch", 1, 1, FEARG_1, arg1_dict_any,
ret_void, f_setcharsearch},
+ {"setcmdline", 1, 2, FEARG_1, arg2_string_number,
+ ret_number_bool, f_setcmdline},
{"setcmdpos", 1, 1, FEARG_1, arg1_number,
ret_number_bool, f_setcmdpos},
{"setcursorcharpos", 1, 3, FEARG_1, arg13_cursor,
***************
*** 3607,3613 ****
f_deepcopy(typval_T *argvars, typval_T *rettv)
{
varnumber_T noref = 0;
- int copyID;
if (in_vim9script()
&& (check_for_opt_bool_arg(argvars, 1) == FAIL))
--- 3609,3614 ----
***************
*** 3618,3627 ****
if (noref < 0 || noref > 1)
semsg(_(e_using_number_as_bool_nr), noref);
else
! {
! copyID = get_copyID();
! item_copy(&argvars[0], rettv, TRUE, TRUE, noref == 0 ? copyID : 0);
! }
}
/*
--- 3619,3626 ----
if (noref < 0 || noref > 1)
semsg(_(e_using_number_as_bool_nr), noref);
else
! item_copy(&argvars[0], rettv, TRUE, TRUE,
! noref == 0 ? get_copyID() : 0);
}
/*
*** ../vim-9.0.0284/src/ex_getln.c 2022-08-26 16:58:46.139489368 +0100
--- src/ex_getln.c 2022-08-27 12:09:50.684366120 +0100
***************
*** 4211,4216 ****
--- 4211,4245 ----
rettv->vval.v_number = get_cmdline_screen_pos() + 1;
}
+ // Set the command line str to "str".
+ // Returns 1 when failed, 0 when OK.
+ int
+ set_cmdline_str(char_u *str, int pos)
+ {
+ cmdline_info_T *p = get_ccline_ptr();
+ int cmdline_type;
+ int len;
+
+ if (p == NULL)
+ return 1;
+
+ 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.
+ cmdline_type = ccline.cmdfirstc == NUL ? '-' : ccline.cmdfirstc;
+ trigger_cmd_autocmd(cmdline_type, EVENT_CMDLINECHANGED);
+
+ return 0;
+ }
+
/*
* Set the command line byte position to "pos". Zero is the first position.
* Only works when the command line is being edited.
***************
*** 4234,4239 ****
--- 4263,4297 ----
return 0;
}
+ // "setcmdline()" function
+ void
+ f_setcmdline(typval_T *argvars, typval_T *rettv)
+ {
+ int pos = -1;
+
+ if (argvars[0].v_type != VAR_STRING || argvars[0].vval.v_string == NULL)
+ {
+ emsg(_(e_string_required));
+ return;
+ }
+
+ if (argvars[1].v_type != VAR_UNKNOWN)
+ {
+ int error = FALSE;
+
+ pos = (int)tv_get_number_chk(&argvars[1], &error) - 1;
+ if (error)
+ return;
+ if (pos < 0)
+ {
+ emsg(_(e_argument_must_be_positive));
+ return;
+ }
+ }
+
+ rettv->vval.v_number = set_cmdline_str(argvars[0].vval.v_string, pos);
+ }
+
/*
* "setcmdpos()" function
*/
*** ../vim-9.0.0284/src/proto/
ex_getln.pro 2022-06-27 23:15:05.000000000 +0100
--- src/proto/
ex_getln.pro 2022-08-27 12:09:27.656461542 +0100
***************
*** 34,39 ****
--- 34,41 ----
void f_getcmdline(typval_T *argvars, typval_T *rettv);
void f_getcmdpos(typval_T *argvars, typval_T *rettv);
void f_getcmdscreenpos(typval_T *argvars, typval_T *rettv);
+ int set_cmdline_str(char_u *str, int pos);
+ void f_setcmdline(typval_T *argvars, typval_T *rettv);
void f_setcmdpos(typval_T *argvars, typval_T *rettv);
void f_getcmdtype(typval_T *argvars, typval_T *rettv);
int get_cmdline_firstc(void);
*** ../vim-9.0.0284/src/testdir/test_cmdline.vim 2022-08-21 18:38:15.012358856 +0100
--- src/testdir/test_cmdline.vim 2022-08-27 12:14:51.723207479 +0100
***************
*** 3262,3265 ****
--- 3262,3305 ----
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
*** ../vim-9.0.0284/src/testdir/test_vim9_builtin.vim 2022-08-25 17:39:26.805017714 +0100
--- src/testdir/test_vim9_builtin.vim 2022-08-27 12:19:46.345898363 +0100
***************
*** 3657,3662 ****
--- 3657,3668 ----
assert_equal(d, getcharsearch())
enddef
+ def Test_setcmdline()
+ v9.CheckDefAndScriptSuccess(['setcmdline("ls", 2)'])
+ v9.CheckDefAndScriptFailure(['setcmdline(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E928: String required'])
+ v9.CheckDefAndScriptFailure(['setcmdline("ls", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1030: Using a String as a Number'])
+ enddef
+
def Test_setcmdpos()
v9.CheckDefAndScriptFailure(['setcmdpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1'])
enddef
*** ../vim-9.0.0284/src/version.c 2022-08-26 22:36:32.480565634 +0100
--- src/version.c 2022-08-27 12:01:18.802882439 +0100
***************
*** 709,710 ****
--- 709,712 ----
{ /* Add new patch number below this line */
+ /**/
+ 285,
/**/
--
<Beeth> Girls are like internet domain names,
the ones I like are already taken.
<honx> Well, you can stil get one from a strange country :-P
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///