]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.0683: cannot specify a time for :echowindow v9.0.0683
authorBram Moolenaar <Bram@vim.org>
Fri, 7 Oct 2022 13:31:45 +0000 (14:31 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 7 Oct 2022 13:31:45 +0000 (14:31 +0100)
Problem:    Cannot specify a time for :echowindow.
Solution:   A count can be used to specify the display time. Add
            popup_findecho().

21 files changed:
runtime/doc/builtin.txt
runtime/doc/eval.txt
runtime/doc/popup.txt
runtime/doc/usr_41.txt
src/eval.c
src/evalfunc.c
src/ex_cmds.h
src/popupwin.c
src/proto/popupwin.pro
src/proto/vim9cmds.pro
src/proto/vim9instr.pro
src/testdir/dumps/Test_echowindow_8.dump
src/testdir/dumps/Test_echowindow_9.dump [new file with mode: 0644]
src/testdir/test_messages.vim
src/testdir/test_vim9_disassemble.vim
src/version.c
src/vim9.h
src/vim9cmds.c
src/vim9compile.c
src/vim9execute.c
src/vim9instr.c

index 686cc84cca0d3c0331c151b872949111c5abe218..2ed73999cc1012db160aaf73c4ef34ee2636ba72 100644 (file)
@@ -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}
index fe75169632ae61b52821849ca8f90599e09fe66f..b1bf1a924d7d8d0d17f00646d7c64f18fe7f719b 100644 (file)
@@ -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.
 
index d11557c79920be13e893d9c163339fad2b9e6f94..59896ecfcf203664a6ff7a03b0cef3f3187a5f19 100644 (file)
@@ -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
index e2d5cfe68d25d3bfbac226921a119b87ee8873ff..97e1d5ce915873af13eeaefd3f8fd81fad5575e1 100644 (file)
@@ -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
index 342f93ca2e3e10cef06535d86f27df01b73f21e4..c37765fd89774260df9a8f28dc39f40dbc27b331 100644 (file)
@@ -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
index 22aa03b47dac4c1c385a3d1e0f0952667f238af2..590b33cbb8b8396689bb5fe3c2176a954d3a3943 100644 (file)
@@ -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,
index 8f7c48f8b4b3e82addefc50ad57c68a70d35e5fd..ca7f292c9d6cf45fd171155a5a171f8143017480 100644 (file)
@@ -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),
index aae546566efc556bd5539aa414a0370ca5b366c1..f9cbcef48e9ee5a282c4f5c8aed0549ebef54fd7 100644 (file)
@@ -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.
@@ -4378,6 +4381,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)
 {
@@ -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;
 }
 
 /*
index 12be54f1f8056d4d32f06f9a64615b143794c84b..1ff995085afcd09afb375c444ad7060a2526cea0 100644 (file)
@@ -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);
index 4d9e9839b285f0e177c09dd03ed0e98a94be3aa8..bd2b5c248736df65fa922ac32b66cfade3bc58f0 100644 (file)
@@ -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);
index f0298f949a658f2a03b11e3b2fd1e96161f760dd..87914f36d260dfb7feba505b211510bfb43b0a7f 100644 (file)
@@ -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);
index d57d43787b08674cf3c1e71da74352895a6341e9..cb5b50dcd82b22443113a03be2c73e8a38c64bd9 100644 (file)
@@ -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 (file)
index 0000000..2efdef0
--- /dev/null
@@ -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| 
index 24995f1ed8b539be5cef58b8d785d53debfb463c..ab33caad5277ec215eb3ff21d0ba82a1e124373c 100644 (file)
@@ -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
index a59b55d1acd25f68e849f3be2a5dae8968604465..56d7f0c66f06a0001b9301916b34cee50f502cf8 100644 (file)
@@ -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
index 37ece8919cf2f245f86a67a11f1b9ffa21031130..8be8b3820b8695bfb92ad5ad75baa17e2e79a3bd 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    683,
 /**/
     682,
 /**/
index fe193b1d616d4d4397223f73db59710d70fbf1b4..095fd275519ed2e5c680d67ed481d636f9478309 100644 (file)
@@ -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;
 };
 
index 3c561d1ef55ad51b2d599c2611ee7e3e974c20ec..d209a16640486a0d13e9fd7ee78a1efd454927f2 100644 (file)
@@ -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;
 }
 
 /*
index 53c8e5a7ff02549f73d49df01dae45ed68939753..38edbab2b8eece80e67cd14b439b4d14021fb9a1 100644 (file)
@@ -2682,6 +2682,32 @@ check_args_shadowing(ufunc_T *ufunc, cctx_T *cctx)
     return r;
 }
 
+/*
+ * 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:
index df18f9ebb51851105809dbac35b9f078d623d397..c90736007579f243baf2987f598b18382252d086 100644 (file)
@@ -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,
index 18dad116889d6f5ef4c3387a59667806764c31bf..4407d5924efa6a758cb825fc1d0baa05431e909c 100644 (file)
@@ -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;
 }