aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShougo <Shougo.Matsu@gmail.com>2022-08-29 14:11:52 +0900
committerGitHub <noreply@github.com>2022-08-29 13:11:52 +0800
commit253f0ffd8d4784b7fca03f8f6c2455b9ee83ff9b (patch)
treec013d5603d348f69ea5d47c2bf0477df1504e623 /src
parent1dcaa75a6564b8a90e74a96e242803c6aa3f59cf (diff)
downloadrneovim-253f0ffd8d4784b7fca03f8f6c2455b9ee83ff9b.tar.gz
rneovim-253f0ffd8d4784b7fca03f8f6c2455b9ee83ff9b.tar.bz2
rneovim-253f0ffd8d4784b7fca03f8f6c2455b9ee83ff9b.zip
vim-patch:9.0.0285: it is not easy to change the command line from a plugin (#19979)
vim-patch:9.0.0285: it is not easy to change the command line from a plugin Problem: It is not easy to change the command line from a plugin. Solution: Add setcmdline(). (Shougo Matsushita, closes vim/vim#10869) https://github.com/vim/vim/commit/07ea5f1509fe8dafe3262ed2702b4d0fc99e288b
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c25
-rw-r--r--src/nvim/ex_getln.c38
-rw-r--r--src/nvim/testdir/test_cmdline.vim40
4 files changed, 101 insertions, 3 deletions
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 4863d8013d..3e89489459 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -332,6 +332,7 @@ return {
setcharpos={args=2, base=2},
setcharsearch={args=1, base=1},
setcmdpos={args=1, base=1},
+ setcmdline={args={1, 2}, base=1},
setcursorcharpos={args={1, 3}, base=1},
setenv={args=2, base=2},
setfperm={args=2, base=1},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 581f187140..2ed9ed34f4 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -7619,6 +7619,31 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt
}
}
+/// "setcmdline()" function
+static void f_setcmdline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ if (argvars[0].v_type != VAR_STRING || argvars[0].vval.v_string == NULL) {
+ emsg(_(e_stringreq));
+ return;
+ }
+
+ int pos = -1;
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ bool error = false;
+
+ pos = (int)tv_get_number_chk(&argvars[1], &error) - 1;
+ if (error) {
+ return;
+ }
+ if (pos < 0) {
+ emsg(_(e_positive));
+ return;
+ }
+ }
+
+ rettv->vval.v_number = set_cmdline_str(argvars[0].vval.v_string, pos);
+}
+
/// "setcmdpos()" function
static void f_setcmdpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 081aa80778..84eacf3997 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -2373,9 +2373,9 @@ end:
return cmdpreview_type != 0;
}
-static int command_line_changed(CommandLineState *s)
+/// Trigger CmdlineChanged autocommands.
+static void do_autocmd_cmdlinechanged(int firstc)
{
- // Trigger CmdlineChanged autocommands.
if (has_event(EVENT_CMDLINECHANGED)) {
TryState tstate;
Error err = ERROR_INIT;
@@ -2383,7 +2383,7 @@ static int command_line_changed(CommandLineState *s)
dict_T *dict = get_v_event(&save_v_event);
char firstcbuf[2];
- firstcbuf[0] = (char)(s->firstc > 0 ? s->firstc : '-');
+ firstcbuf[0] = (char)firstc;
firstcbuf[1] = 0;
// set v:event to a dictionary with information about the commandline
@@ -2403,6 +2403,12 @@ static int command_line_changed(CommandLineState *s)
redrawcmd();
}
}
+}
+
+static int command_line_changed(CommandLineState *s)
+{
+ // Trigger CmdlineChanged autocommands.
+ do_autocmd_cmdlinechanged(s->firstc > 0 ? s->firstc : '-');
if (s->firstc == ':'
&& current_sctx.sc_sid == 0 // only if interactive
@@ -3991,6 +3997,32 @@ int get_cmdline_screen_pos(void)
return p->cmdspos;
}
+/// Set the command line str to "str".
+/// @return 1 when failed, 0 when OK.
+int set_cmdline_str(const char *str, int pos)
+{
+ CmdlineInfo *p = get_ccline_ptr();
+
+ if (p == NULL) {
+ return 1;
+ }
+
+ int 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.
+ do_autocmd_cmdlinechanged(ccline.cmdfirstc == NUL ? '-' : ccline.cmdfirstc);
+
+ return 0;
+}
+
/*
* Set the command line byte position to "pos". Zero is the first position.
* Only works when the command line is being edited.
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 517509004a..a5a30b7953 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -2185,4 +2185,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