summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShougo Matsushita <Shougo.Matsu@gmail.com>2022-08-27 12:22:25 +0100
committerBram Moolenaar <Bram@vim.org>2022-08-27 12:22:25 +0100
commit07ea5f1509fe8dafe3262ed2702b4d0fc99e288b (patch)
tree1b409138b5a115619cb2852ece07194edca7ed51 /src
parent5ff595d9db2d9a33aa10cc9f18f256826226862f (diff)
patch 9.0.0285: it is not easy to change the command line from a pluginv9.0.0285
Problem: It is not easy to change the command line from a plugin. Solution: Add setcmdline(). (Shougo Matsushita, closes #10869)
Diffstat (limited to 'src')
-rw-r--r--src/evalfunc.c9
-rw-r--r--src/ex_getln.c58
-rw-r--r--src/proto/ex_getln.pro2
-rw-r--r--src/testdir/test_cmdline.vim40
-rw-r--r--src/testdir/test_vim9_builtin.vim6
-rw-r--r--src/version.c2
6 files changed, 112 insertions, 5 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index d2cc8fc769..1b629ff843 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -2369,6 +2369,8 @@ static funcentry_T global_functions[] =
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,7 +3609,6 @@ f_debugbreak(typval_T *argvars, typval_T *rettv)
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))
@@ -3618,10 +3619,8 @@ f_deepcopy(typval_T *argvars, typval_T *rettv)
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);
- }
+ item_copy(&argvars[0], rettv, TRUE, TRUE,
+ noref == 0 ? get_copyID() : 0);
}
/*
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 2ef66abb19..587a9ff3df 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -4211,6 +4211,35 @@ f_getcmdscreenpos(typval_T *argvars UNUSED, typval_T *rettv)
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,6 +4263,35 @@ set_cmdline_pos(
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
*/
diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro
index bcc310c7dd..2eb32ab422 100644
--- a/src/proto/ex_getln.pro
+++ b/src/proto/ex_getln.pro
@@ -34,6 +34,8 @@ void f_getcmdcompltype(typval_T *argvars, typval_T *rettv);
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);
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 3372e8dd31..121ff250d1 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -3262,4 +3262,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
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 931fe671c9..227e28c712 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -3657,6 +3657,12 @@ def Test_setcharsearch()
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
diff --git a/src/version.c b/src/version.c
index 2e48687447..6b4bdfab29 100644
--- a/src/version.c
+++ b/src/version.c
@@ -708,6 +708,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 285,
+/**/
284,
/**/
283,