summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-10-07 14:31:45 +0100
committerBram Moolenaar <Bram@vim.org>2022-10-07 14:31:45 +0100
commitbdc09a18fca32715687d9911a431da69186528cc (patch)
tree9d27853365bffdc04e51cfe7fc6cb75dafc8a0b0
parentcf3d0eaf47a56a52b355d8faf4e59685396f9c05 (diff)
downloadvim-git-bdc09a18fca32715687d9911a431da69186528cc.tar.gz
patch 9.0.0683: cannot specify a time for :echowindowv9.0.0683
Problem: Cannot specify a time for :echowindow. Solution: A count can be used to specify the display time. Add popup_findecho().
-rw-r--r--runtime/doc/builtin.txt1
-rw-r--r--runtime/doc/eval.txt5
-rw-r--r--runtime/doc/popup.txt6
-rw-r--r--runtime/doc/usr_41.txt1
-rw-r--r--src/eval.c2
-rw-r--r--src/evalfunc.c2
-rw-r--r--src/ex_cmds.h4
-rw-r--r--src/popupwin.c22
-rw-r--r--src/proto/popupwin.pro3
-rw-r--r--src/proto/vim9cmds.pro2
-rw-r--r--src/proto/vim9instr.pro1
-rw-r--r--src/testdir/dumps/Test_echowindow_8.dump2
-rw-r--r--src/testdir/dumps/Test_echowindow_9.dump8
-rw-r--r--src/testdir/test_messages.vim9
-rw-r--r--src/testdir/test_vim9_disassemble.vim4
-rw-r--r--src/version.c2
-rw-r--r--src/vim9.h7
-rw-r--r--src/vim9cmds.c18
-rw-r--r--src/vim9compile.c41
-rw-r--r--src/vim9execute.c18
-rw-r--r--src/vim9instr.c14
21 files changed, 147 insertions, 25 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 686cc84cc..2ed73999c 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -396,6 +396,7 @@ popup_create({what}, {options}) Number create a popup window
popup_dialog({what}, {options}) Number create a popup window used as a dialog
popup_filter_menu({id}, {key}) Number filter for a menu popup window
popup_filter_yesno({id}, {key}) Number filter for a dialog popup window
+popup_findecho() Number get window ID of popup for `:echowin`
popup_findinfo() Number get window ID of info popup window
popup_findpreview() Number get window ID of preview popup window
popup_getoptions({id}) Dict get options of popup window {id}
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index fe7516963..b1bf1a924 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -3392,7 +3392,7 @@ text...
when the screen is redrawn.
*:echow* *:echowin* *:echowindow*
-:echow[indow] {expr1} ..
+:[N]echow[indow] {expr1} ..
Like |:echomsg| but when the messages popup window is
available the message is displayed there. This means
it will show for three seconds and avoid a
@@ -3400,6 +3400,9 @@ text...
that, press Esc in Normal mode (when it would
otherwise beep). If it disappears too soon you can
use `:messages` to see the text.
+ When [N] is given then the window will show up for
+ this number of seconds. The last `:echowindow` with a
+ count matters, it is used once only.
The message window is available when Vim was compiled
with the +timer and the +popupwin features.
diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt
index d11557c79..59896ecfc 100644
--- a/runtime/doc/popup.txt
+++ b/runtime/doc/popup.txt
@@ -347,6 +347,12 @@ popup_filter_yesno({id}, {key}) *popup_filter_yesno()*
See the example here: |popup_dialog-example|
+popup_findecho() *popup_findecho()*
+ Get the |window-ID| for the popup that shows messages for the
+ `:echowindow` command. Return zero if there is none.
+ Mainly useful to hide the popup.
+
+
popup_findinfo() *popup_findinfo()*
Get the |window-ID| for the popup info window, as it used by
the popup menu. See |complete-popup|. The info popup is
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index e2d5cfe68..97e1d5ce9 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -1289,6 +1289,7 @@ Popup window: *popup-window-functions*
popup_filter_yesno() block until 'y' or 'n' is pressed
popup_getoptions() get current options for a popup
popup_getpos() get actual position and size of a popup
+ popup_findecho() get window ID for popup used for `:echowindow`
popup_findinfo() get window ID for popup info window
popup_findpreview() get window ID for popup preview window
popup_list() get list of all popup window IDs
diff --git a/src/eval.c b/src/eval.c
index 342f93ca2..c37765fd8 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -6916,7 +6916,7 @@ ex_execute(exarg_T *eap)
else if (eap->cmdidx == CMD_echowindow)
{
#ifdef HAS_MESSAGE_WINDOW
- start_echowindow();
+ start_echowindow(eap->addr_count > 0 ? eap->line2 : 0);
#endif
msg_attr(ga.ga_data, echo_attr);
#ifdef HAS_MESSAGE_WINDOW
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 22aa03b47..590b33cbb 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -2273,6 +2273,8 @@ static funcentry_T global_functions[] =
ret_bool, PROP_FUNC(f_popup_filter_menu)},
{"popup_filter_yesno", 2, 2, 0, arg2_number_string,
ret_bool, PROP_FUNC(f_popup_filter_yesno)},
+ {"popup_findecho", 0, 0, 0, NULL,
+ ret_number, PROP_FUNC(f_popup_findecho)},
{"popup_findinfo", 0, 0, 0, NULL,
ret_number, PROP_FUNC(f_popup_findinfo)},
{"popup_findpreview", 0, 0, 0, NULL,
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 8f7c48f8b..ca7f292c9 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -552,8 +552,8 @@ EXCMD(CMD_echon, "echon", ex_echo,
EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
ADDR_NONE),
EXCMD(CMD_echowindow, "echowindow", ex_execute,
- EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
- ADDR_NONE),
+ EX_RANGE|EX_EXTRA|EX_NOTRLCOM|EX_EXPR_ARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
+ ADDR_OTHER),
EXCMD(CMD_else, "else", ex_else,
EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_WHOLE,
ADDR_NONE),
diff --git a/src/popupwin.c b/src/popupwin.c
index aae546566..f9cbcef48 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -32,6 +32,9 @@ static poppos_entry_T poppos_entries[] = {
// Window used for ":echowindow"
static win_T *message_win = NULL;
+// Time used for the next ":echowindow" message in msec.
+static int message_win_time = 3000;
+
// Flag set when a message is added to the message window, timer is started
// when the message window is drawn. This might be after pressing Enter at the
// hit-enter prompt.
@@ -4379,6 +4382,16 @@ popup_find_info_window(void)
#endif
void
+f_popup_findecho(typval_T *argvars UNUSED, typval_T *rettv)
+{
+#ifdef HAS_MESSAGE_WINDOW
+ rettv->vval.v_number = message_win == NULL ? 0 : message_win->w_id;
+#else
+ rettv->vval.v_number = 0;
+#endif
+}
+
+ void
f_popup_findinfo(typval_T *argvars UNUSED, typval_T *rettv)
{
#ifdef FEAT_QUICKFIX
@@ -4537,7 +4550,11 @@ may_start_message_win_timer(win_T *wp)
if (wp == message_win && start_message_win_timer)
{
if (message_win->w_popup_timer != NULL)
+ {
+ message_win->w_popup_timer->tr_interval = message_win_time;
timer_start(message_win->w_popup_timer);
+ message_win_time = 3000;
+ }
start_message_win_timer = FALSE;
}
}
@@ -4568,15 +4585,18 @@ static int ew_msg_col = 0;
/*
* Invoked before outputting a message for ":echowindow".
+ * "time_sec" is the display time, zero means using the default 3 sec.
*/
void
-start_echowindow(void)
+start_echowindow(int time_sec)
{
in_echowindow = TRUE;
save_msg_didout = msg_didout;
save_msg_col = msg_col;
msg_didout = ew_msg_didout;
msg_col = ew_msg_col;
+ if (time_sec != 0)
+ message_win_time = time_sec * 1000;
}
/*
diff --git a/src/proto/popupwin.pro b/src/proto/popupwin.pro
index 12be54f1f..1ff995085 100644
--- a/src/proto/popupwin.pro
+++ b/src/proto/popupwin.pro
@@ -57,6 +57,7 @@ int set_ref_in_popups(int copyID);
int popup_is_popup(win_T *wp);
win_T *popup_find_preview_window(void);
win_T *popup_find_info_window(void);
+void f_popup_findecho(typval_T *argvars, typval_T *rettv);
void f_popup_findinfo(typval_T *argvars, typval_T *rettv);
void f_popup_findpreview(typval_T *argvars, typval_T *rettv);
int popup_create_preview_window(int info);
@@ -67,7 +68,7 @@ win_T *popup_get_message_win(void);
void popup_show_message_win(void);
int popup_message_win_visible(void);
void popup_hide_message_win(void);
-void start_echowindow(void);
+void start_echowindow(int time_sec);
void end_echowindow(void);
int popup_win_closed(win_T *win);
void popup_set_title(win_T *wp);
diff --git a/src/proto/vim9cmds.pro b/src/proto/vim9cmds.pro
index 4d9e9839b..bd2b5c248 100644
--- a/src/proto/vim9cmds.pro
+++ b/src/proto/vim9cmds.pro
@@ -25,7 +25,7 @@ char_u *compile_throw(char_u *arg, cctx_T *cctx);
char_u *compile_eval(char_u *arg, cctx_T *cctx);
int get_defer_var_idx(cctx_T *cctx);
char_u *compile_defer(char_u *arg_start, cctx_T *cctx);
-char_u *compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx);
+char_u *compile_mult_expr(char_u *arg, int cmdidx, long cmd_count, cctx_T *cctx);
char_u *compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx);
char_u *compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx);
char_u *compile_script(char_u *line, cctx_T *cctx);
diff --git a/src/proto/vim9instr.pro b/src/proto/vim9instr.pro
index f0298f949..87914f36d 100644
--- a/src/proto/vim9instr.pro
+++ b/src/proto/vim9instr.pro
@@ -60,6 +60,7 @@ int generate_DEFER(cctx_T *cctx, int var_idx, int argcount);
int generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len);
int generate_ECHO(cctx_T *cctx, int with_white, int count);
int generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count);
+int generate_ECHOWINDOW(cctx_T *cctx, int count, long time);
int generate_SOURCE(cctx_T *cctx, int sid);
int generate_PUT(cctx_T *cctx, int regname, linenr_T lnum);
int generate_EXEC_copy(cctx_T *cctx, isntype_T isntype, char_u *line);
diff --git a/src/testdir/dumps/Test_echowindow_8.dump b/src/testdir/dumps/Test_echowindow_8.dump
index d57d43787..cb5b50dcd 100644
--- a/src/testdir/dumps/Test_echowindow_8.dump
+++ b/src/testdir/dumps/Test_echowindow_8.dump
@@ -4,5 +4,5 @@
|═+0#e000002&@74
|l|a|t|e|r| |m|e|s@1|a|g|e| @61
|m|o|r|e| @70
-|:+0#0000000&|e|c|h|o|w|i|n| |'|m|o|r|e|'| @59
+|:+0#0000000&|7|e|c|h|o|w|i|n| |'|m|o|r|e|'| @58
@57|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/dumps/Test_echowindow_9.dump b/src/testdir/dumps/Test_echowindow_9.dump
new file mode 100644
index 000000000..2efdef062
--- /dev/null
+++ b/src/testdir/dumps/Test_echowindow_9.dump
@@ -0,0 +1,8 @@
+| +8#0000001#e0e0e08|+| |[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@49|X+8#0000001#e0e0e08
+> +0#0000000#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|c|a|l@1| |H|i|d|e|W|i|n|(|)| @59
+@57|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim
index 24995f1ed..ab33caad5 100644
--- a/src/testdir/test_messages.vim
+++ b/src/testdir/test_messages.vim
@@ -511,6 +511,10 @@ func Test_echowindow()
echo 'two'
echo 'three'
enddef
+
+ def HideWin()
+ popup_hide(popup_findecho())
+ enddef
END
call writefile(lines, 'XtestEchowindow', 'D')
let buf = RunVimInTerminal('-S XtestEchowindow', #{rows: 8})
@@ -536,9 +540,12 @@ func Test_echowindow()
call VerifyScreenDump(buf, 'Test_echowindow_7', {})
call term_sendkeys(buf, ":tabnew\<CR>")
- call term_sendkeys(buf, ":echowin 'more'\<CR>")
+ call term_sendkeys(buf, ":7echowin 'more'\<CR>")
call VerifyScreenDump(buf, 'Test_echowindow_8', {})
+ call term_sendkeys(buf, ":call HideWin()\<CR>")
+ call VerifyScreenDump(buf, 'Test_echowindow_9', {})
+
" clean up
call StopVimInTerminal(buf)
endfunc
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index a59b55d1a..56d7f0c66 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -2367,6 +2367,7 @@ def s:Echomsg()
echoerr 'went' .. 'wrong'
var local = 'window'
echowin 'in' local
+ :5echowin 'five'
enddef
def Test_disassemble_echomsg()
@@ -2389,6 +2390,9 @@ def Test_disassemble_echomsg()
'\d\+ PUSHS "in"\_s*' ..
'\d\+ LOAD $0\_s*' ..
'\d\+ ECHOWINDOW 2\_s*' ..
+ ":5echowin 'five'\\_s*" ..
+ '\d\+ PUSHS "five"\_s*' ..
+ '\d\+ ECHOWINDOW 1 (5 sec)\_s*' ..
'\d\+ RETURN void',
res)
enddef
diff --git a/src/version.c b/src/version.c
index 37ece8919..8be8b3820 100644
--- a/src/version.c
+++ b/src/version.c
@@ -700,6 +700,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 683,
+/**/
682,
/**/
681,
diff --git a/src/vim9.h b/src/vim9.h
index fe193b1d6..095fd2755 100644
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -457,6 +457,12 @@ typedef struct {
int defer_argcount; // number of arguments
} deferins_T;
+// arguments to ISN_ECHOWINDOW
+typedef struct {
+ int ewin_count; // number of arguments
+ long ewin_time; // time argument (msec)
+} echowin_T;
+
/*
* Instruction
*/
@@ -507,6 +513,7 @@ struct isn_S {
getitem_T getitem;
debug_T debug;
deferins_T defer;
+ echowin_T echowin;
} isn_arg;
};
diff --git a/src/vim9cmds.c b/src/vim9cmds.c
index 3c561d1ef..d209a1664 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -1971,10 +1971,11 @@ compile_defer(char_u *arg_start, cctx_T *cctx)
* compile "echomsg expr"
* compile "echoerr expr"
* compile "echoconsole expr"
+ * compile "echowindow expr" - may have cmd_count set
* compile "execute expr"
*/
char_u *
-compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
+compile_mult_expr(char_u *arg, int cmdidx, long cmd_count, cctx_T *cctx)
{
char_u *p = arg;
char_u *prev = arg;
@@ -1982,6 +1983,7 @@ compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
int count = 0;
int start_ctx_lnum = cctx->ctx_lnum;
type_T *type;
+ int r = OK;
for (;;)
{
@@ -2015,23 +2017,23 @@ compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
cctx->ctx_lnum = start_ctx_lnum;
if (cmdidx == CMD_echo || cmdidx == CMD_echon)
- generate_ECHO(cctx, cmdidx == CMD_echo, count);
+ r = generate_ECHO(cctx, cmdidx == CMD_echo, count);
else if (cmdidx == CMD_execute)
- generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
+ r = generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
else if (cmdidx == CMD_echomsg)
- generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
+ r = generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
#ifdef HAS_MESSAGE_WINDOW
else if (cmdidx == CMD_echowindow)
- generate_MULT_EXPR(cctx, ISN_ECHOWINDOW, count);
+ r = generate_ECHOWINDOW(cctx, count, cmd_count);
#endif
else if (cmdidx == CMD_echoconsole)
- generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
+ r = generate_MULT_EXPR(cctx, ISN_ECHOCONSOLE, count);
else
- generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
+ r = generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
cctx->ctx_lnum = save_lnum;
}
- return p;
+ return r == OK ? p : NULL;
}
/*
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 53c8e5a7f..38edbab2b 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2683,6 +2683,32 @@ check_args_shadowing(ufunc_T *ufunc, cctx_T *cctx)
}
/*
+ * Get a count before a command. Can only be a number.
+ * Returns zero if there is no count.
+ * Returns -1 if there is something wrong.
+ */
+ static long
+get_cmd_count(char_u *line, exarg_T *eap)
+{
+ char_u *p;
+
+ // skip over colons and white space
+ for (p = line; *p == ':' || VIM_ISWHITE(*p); ++p)
+ ;
+ if (!isdigit(*p))
+ {
+ // the command must be following
+ if (p < eap->cmd)
+ {
+ emsg(_(e_invalid_range));
+ return -1;
+ }
+ return 0;
+ }
+ return atol((char *)p);
+}
+
+/*
* Get the compilation type that should be used for "ufunc".
* Keep in sync with INSTRUCTIONS().
*/
@@ -3309,16 +3335,23 @@ compile_def_function(
line = compile_defer(p, &cctx);
break;
+#ifdef HAS_MESSAGE_WINDOW
+ case CMD_echowindow:
+ {
+ long cmd_count = get_cmd_count(line, &ea);
+ if (cmd_count >= 0)
+ line = compile_mult_expr(p, ea.cmdidx,
+ cmd_count, &cctx);
+ }
+ break;
+#endif
case CMD_echo:
case CMD_echon:
case CMD_echoconsole:
case CMD_echoerr:
case CMD_echomsg:
-#ifdef HAS_MESSAGE_WINDOW
- case CMD_echowindow:
-#endif
case CMD_execute:
- line = compile_mult_expr(p, ea.cmdidx, &cctx);
+ line = compile_mult_expr(p, ea.cmdidx, 0, &cctx);
break;
case CMD_put:
diff --git a/src/vim9execute.c b/src/vim9execute.c
index df18f9ebb..c90736007 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -3269,7 +3269,7 @@ exec_instructions(ectx_T *ectx)
case ISN_ECHOCONSOLE:
case ISN_ECHOERR:
{
- int count = iptr->isn_arg.number;
+ int count;
garray_T ga;
char_u buf[NUMBUFLEN];
char_u *p;
@@ -3277,6 +3277,10 @@ exec_instructions(ectx_T *ectx)
int failed = FALSE;
int idx;
+ if (iptr->isn_type == ISN_ECHOWINDOW)
+ count = iptr->isn_arg.echowin.ewin_count;
+ else
+ count = iptr->isn_arg.number;
ga_init2(&ga, 1, 80);
for (idx = 0; idx < count; ++idx)
{
@@ -3339,7 +3343,8 @@ exec_instructions(ectx_T *ectx)
#ifdef HAS_MESSAGE_WINDOW
else if (iptr->isn_type == ISN_ECHOWINDOW)
{
- start_echowindow();
+ start_echowindow(
+ iptr->isn_arg.echowin.ewin_time);
msg_attr(ga.ga_data, echo_attr);
end_echowindow();
}
@@ -6094,8 +6099,13 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
(varnumber_T)(iptr->isn_arg.number));
break;
case ISN_ECHOWINDOW:
- smsg("%s%4d ECHOWINDOW %lld", pfx, current,
- (varnumber_T)(iptr->isn_arg.number));
+ if (iptr->isn_arg.echowin.ewin_time > 0)
+ smsg("%s%4d ECHOWINDOW %d (%ld sec)", pfx, current,
+ iptr->isn_arg.echowin.ewin_count,
+ iptr->isn_arg.echowin.ewin_time);
+ else
+ smsg("%s%4d ECHOWINDOW %d", pfx, current,
+ iptr->isn_arg.echowin.ewin_count);
break;
case ISN_ECHOCONSOLE:
smsg("%s%4d ECHOCONSOLE %lld", pfx, current,
diff --git a/src/vim9instr.c b/src/vim9instr.c
index 18dad1168..4407d5924 100644
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -1879,7 +1879,21 @@ generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
return FAIL;
isn->isn_arg.number = count;
+ return OK;
+}
+/*
+ * Generate an ISN_ECHOWINDOW instruction
+ */
+ int
+generate_ECHOWINDOW(cctx_T *cctx, int count, long time)
+{
+ isn_T *isn;
+
+ if ((isn = generate_instr_drop(cctx, ISN_ECHOWINDOW, count)) == NULL)
+ return FAIL;
+ isn->isn_arg.echowin.ewin_count = count;
+ isn->isn_arg.echowin.ewin_time = time;
return OK;
}