diff options
author | Shougo Matsushita <Shougo.Matsu@gmail.com> | 2022-08-27 12:22:25 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-08-27 12:22:25 +0100 |
commit | 07ea5f1509fe8dafe3262ed2702b4d0fc99e288b (patch) | |
tree | 1b409138b5a115619cb2852ece07194edca7ed51 /src | |
parent | 5ff595d9db2d9a33aa10cc9f18f256826226862f (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.c | 9 | ||||
-rw-r--r-- | src/ex_getln.c | 58 | ||||
-rw-r--r-- | src/proto/ex_getln.pro | 2 | ||||
-rw-r--r-- | src/testdir/test_cmdline.vim | 40 | ||||
-rw-r--r-- | src/testdir/test_vim9_builtin.vim | 6 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |