]> granicus.if.org Git - vim/commitdiff
patch 9.0.0285: it is not easy to change the command line from a plugin v9.0.0285
authorShougo Matsushita <Shougo.Matsu@gmail.com>
Sat, 27 Aug 2022 11:22:25 +0000 (12:22 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 27 Aug 2022 11:22:25 +0000 (12:22 +0100)
Problem:    It is not easy to change the command line from a plugin.
Solution:   Add setcmdline(). (Shougo Matsushita, closes #10869)

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
src/version.c

index 7aae8a0f6d94e1013e99b077f066406a788c3d88..556418f10e77ef151ba5e97fd3172f17d0c969c3 100644 (file)
@@ -505,6 +505,7 @@ setbufvar({buf}, {varname}, {val})
 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
@@ -3425,7 +3426,8 @@ getcmdcompltype()                                 *getcmdcompltype()*
                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()|.
+               Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
+               |setcmdline()|.
                Returns an empty string when completion is not defined.
 
 getcmdline()                                           *getcmdline()*
@@ -3434,7 +3436,8 @@ getcmdline()                                              *getcmdline()*
                |c_CTRL-R_=|.
                Example: >
                        :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
                |inputsecret()|.
 
@@ -3444,7 +3447,8 @@ getcmdpos()                                               *getcmdpos()*
                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()|.
+               Also see |getcmdtype()|, |setcmdpos()|, |getcmdline()| and
+               |setcmdline()|.
 
 getcmdscreenpos()                                      *getcmdscreenpos()*
                Return the screen position of the cursor in the command line
@@ -3453,7 +3457,8 @@ getcmdscreenpos()                                 *getcmdscreenpos()*
                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()|.
+               Also see |getcmdpos()|, |setcmdpos()|, |getcmdline()| and
+               |setcmdline()|.
 
 getcmdtype()                                           *getcmdtype()*
                Return the current command-line type. Possible return values
@@ -7925,6 +7930,16 @@ setcharsearch({dict})                                    *setcharsearch()*
                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.
@@ -7937,8 +7952,8 @@ setcmdpos({pos})                                  *setcmdpos()*
                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.
+               Returns 0 when successful, 1 when not editing the command
+               line.
 
                Can also be used as a |method|: >
                        GetPos()->setcmdpos()
index 57cdb11e82a46622e803f1d11ecb4e7e46a41c8c..e2d32f94fc40029054b2e73b6c18ee0e40b374bc 100644 (file)
@@ -1038,6 +1038,7 @@ Command line:                                     *command-line-functions*
        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
index d2cc8fc769555effdd21653c71eb73ac8f5e079c..1b629ff8435718a6cf538daa86903416702cf31d 100644 (file)
@@ -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);
 }
 
 /*
index 2ef66abb19fc7e49b38beb9971378be04f3a0ab6..587a9ff3dfd3cbcf4ab61439e6befdf18f7aee68 100644 (file)
@@ -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
  */
index bcc310c7dd0e28965b9fd42b8979b99d602a8aa4..2eb32ab42252264bd120113a9e35dcf1fb63481c 100644 (file)
@@ -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);
index 3372e8dd31c22ed6b78bf3c0330395b25483aa9c..121ff250d14c1e710171efb2f66e201f12499939 100644 (file)
@@ -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
index 931fe671c9b1e44721ac2ce4fad4856b9b656037..227e28c712ec3a913ef3a41819762f6848947ec8 100644 (file)
@@ -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
index 2e4868744766e686157cdbc91d55a052fd3d7c66..6b4bdfab29b2468b68e681144578a2fb86a0ea66 100644 (file)
@@ -707,6 +707,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    285,
 /**/
     284,
 /**/