To: vim_dev@googlegroups.com Subject: Patch 9.0.0285 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 eescape(getcmdline(), ' \') ! < Also see |getcmdtype()|, |getcmdpos()| and |setcmdpos()|. Returns an empty string when entering a password or using |inputsecret()|. --- 3436,3443 ---- |c_CTRL-R_=|. Example: > :cmap eescape(getcmdline(), ' \') ! < 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(":\=SetText('set rtp?', 2)\\", '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 \\\"\", 'tx') + call assert_equal('"DoCmd January February Mars', @:) + + " Called in + cnoremap a setcmdline('let foo=') + call feedkeys(":a\", '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, /**/ -- Girls are like internet domain names, the ones I like are already taken. Well, you can stil get one from a strange country :-P /// Bram Moolenaar -- Bram@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 ///