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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220827112301.BBB5B1C066C%40moolenaar.net.

Raspunde prin e-mail lui