]> granicus.if.org Git - vim/commitdiff
patch 8.1.2192: cannot easily fill the info popup asynchronously v8.1.2192
authorBram Moolenaar <Bram@vim.org>
Sun, 20 Oct 2019 16:17:57 +0000 (18:17 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 20 Oct 2019 16:17:57 +0000 (18:17 +0200)
Problem:    Cannot easily fill the info popup asynchronously.
Solution:   Add the "popuphidden" value to 'completeopt'. (closes #4924)

15 files changed:
runtime/doc/insert.txt
runtime/doc/options.txt
src/ex_cmds.c
src/optionstr.c
src/popupmenu.c
src/popupwin.c
src/proto/ex_cmds.pro
src/proto/popupmenu.pro
src/proto/popupwin.pro
src/testdir/dumps/Test_popupwin_infopopup_hidden_1.dump [new file with mode: 0644]
src/testdir/dumps/Test_popupwin_infopopup_hidden_2.dump [new file with mode: 0644]
src/testdir/dumps/Test_popupwin_infopopup_hidden_3.dump [new file with mode: 0644]
src/testdir/test_popupwin.vim
src/version.c
src/vim.h

index dfc3541f5526b03b16510df637f077758ea85b90..d28bf59984d31cd66cd2c708e4ebd8ebe7c92281 100644 (file)
@@ -1,4 +1,4 @@
-*insert.txt*    For Vim version 8.1.  Last change: 2019 Sep 27
+*insert.txt*    For Vim version 8.1.  Last change: 2019 Oct 20
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1138,6 +1138,27 @@ below the text, and the bottom of the menu otherwise.
 After the info popup is created it can be found with |popup_findinfo()| and
 properties can be changed with |popup_setoptions()|.
 
+                                               *complete-popuphidden*
+If the information for the popup is obtained asynchronously, use "popuphidden"
+in 'completeopt'.  The info popup will then be initally hidden and
+|popup_show()| must be called once it has been filled with the info.  This can
+be done with a |CompleteChanged| autocommand, something like this: >
+       set completeopt+=popuphidden
+       au CompleteChanged * call UpdateCompleteInfo()
+       func UpdateCompleteInfo()
+         " Cancel any pending info fetch
+         let item = v:event.completed_item
+         " Start fetching info for the item then call ShowCompleteInfo(info)
+       endfunc
+       func ShowCompleteInfo(info)
+         let id = popup_findinfo()
+         if id
+           call popup_settext(id, 'async info: ' .. a:info)
+           call popup_show(id)
+         endif
+       endfunc
+
+<                                              *complete-item-kind*
 The "kind" item uses a single letter to indicate the kind of completion.  This
 may be used to show the completion differently (different color or icon).
 Currently these types can be used:
index 8436c8a0dfc3d1afcf1cc97f5cc7dfb6021a2544..e62ee8974ea19055a99f8728d66abd8a27ec83db 100644 (file)
@@ -1,4 +1,4 @@
-*options.txt*  For Vim version 8.1.  Last change: 2019 Sep 28
+*options.txt*  For Vim version 8.1.  Last change: 2019 Oct 20
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1919,6 +1919,13 @@ A jump table for the options with a short description can be found at |Q_op|.
                    See |'completepopup'| for specifying properties.
                    {only works when compiled with the |+textprop| feature}
 
+          popuphidden
+                   Just like "popup" but initially hide the popup.  Use a
+                   |CompleteChanged| autocommand to fetch the info and call
+                   |popup_show()| once the popup has been filled.
+                   See the example at |complete-popuphidden|.
+                   {only works when compiled with the |+textprop| feature}
+
           noinsert Do not insert any text for a match until the user selects
                    a match from the menu. Only works in combination with
                    "menu" or "menuone". No effect if "longest" is present.
index fc70e2cfef1878060da29bd336dee714fc17e822..bcff7ee71678e2c293a7bca96d5e0206a135e749 100644 (file)
@@ -4919,13 +4919,14 @@ free_old_sub(void)
 #if defined(FEAT_QUICKFIX) || defined(PROTO)
 /*
  * Set up for a tagpreview.
+ * Makes the preview window the current window.
  * Return TRUE when it was created.
  */
     int
 prepare_tagpreview(
     int                undo_sync,          // sync undo when leaving the window
     int                use_previewpopup,   // use popup if 'previewpopup' set
-    int                use_popup)          // use other popup window
+    use_popup_T        use_popup)          // use other popup window
 {
     win_T      *wp;
 
@@ -4945,11 +4946,16 @@ prepare_tagpreview(
            if (wp != NULL)
                popup_set_wantpos_cursor(wp, wp->w_minwidth);
        }
-       else if (use_popup)
+       else if (use_popup != USEPOPUP_NONE)
        {
            wp = popup_find_info_window();
            if (wp != NULL)
-               popup_show(wp);
+           {
+               if (use_popup == USEPOPUP_NORMAL)
+                   popup_show(wp);
+               else
+                   popup_hide(wp);
+           }
        }
        else
 # endif
@@ -4966,8 +4972,9 @@ prepare_tagpreview(
             * There is no preview window open yet.  Create one.
             */
 # ifdef FEAT_TEXT_PROP
-           if ((use_previewpopup && *p_pvp != NUL) || use_popup)
-               return popup_create_preview_window(use_popup);
+           if ((use_previewpopup && *p_pvp != NUL)
+                                                || use_popup != USEPOPUP_NONE)
+               return popup_create_preview_window(use_popup != USEPOPUP_NONE);
 # endif
            if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0) == FAIL)
                return FALSE;
index 7b83aed2503a9001540703ed02da0a5eff3cb410..bcc737eb17da3344e1f20147cb4cdf008a5225c7 100644 (file)
@@ -76,7 +76,7 @@ static char *(p_fdm_values[]) = {"manual", "expr", "marker", "indent", "syntax",
                                NULL};
 static char *(p_fcl_values[]) = {"all", NULL};
 #endif
-static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", "popup", "noinsert", "noselect", NULL};
+static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", "popup", "popuphidden", "noinsert", "noselect", NULL};
 #ifdef BACKSLASH_IN_FILENAME
 static char *(p_csl_values[]) = {"slash", "backslash", NULL};
 #endif
index b88c6531c16afe873ef3dfb3b8a23ee01b57728f..005adb20ba1abd058911123c47a2afbf8b1a7c5a 100644 (file)
@@ -622,33 +622,36 @@ pum_redraw(void)
 }
 
 #if defined(FEAT_TEXT_PROP) && defined(FEAT_QUICKFIX)
-    static void
-pum_position_info_popup(void)
+/*
+ * Position the info popup relative to the popup menu item.
+ */
+    void
+pum_position_info_popup(win_T *wp)
 {
     int col = pum_col + pum_width + 1;
     int row = pum_row;
     int botpos = POPPOS_BOTLEFT;
 
-    curwin->w_popup_pos = POPPOS_TOPLEFT;
+    wp->w_popup_pos = POPPOS_TOPLEFT;
     if (Columns - col < 20 && Columns - col < pum_col)
     {
        col = pum_col - 1;
-       curwin->w_popup_pos = POPPOS_TOPRIGHT;
+       wp->w_popup_pos = POPPOS_TOPRIGHT;
        botpos = POPPOS_BOTRIGHT;
-       curwin->w_maxwidth = pum_col - 1;
+       wp->w_maxwidth = pum_col - 1;
     }
     else
-       curwin->w_maxwidth = Columns - col + 1;
-    curwin->w_maxwidth -= popup_extra_width(curwin);
+       wp->w_maxwidth = Columns - col + 1;
+    wp->w_maxwidth -= popup_extra_width(wp);
 
-    row -= popup_top_extra(curwin);
-    if (curwin->w_popup_flags & POPF_INFO_MENU)
+    row -= popup_top_extra(wp);
+    if (wp->w_popup_flags & POPF_INFO_MENU)
     {
        if (pum_row < pum_win_row)
        {
            // menu above cursor line, align with bottom
            row += pum_height;
-           curwin->w_popup_pos = botpos;
+           wp->w_popup_pos = botpos;
        }
        else
            // menu below cursor line, align with top
@@ -658,7 +661,7 @@ pum_position_info_popup(void)
        // align with the selected item
        row += pum_selected - pum_first + 1;
 
-    popup_set_wantpos_rowcol(curwin, row, col);
+    popup_set_wantpos_rowcol(wp, row, col);
 }
 #endif
 
@@ -756,15 +759,21 @@ pum_set_selected(int n, int repeat UNUSED)
            tabpage_T   *curtab_save = curtab;
            int         res = OK;
 # ifdef FEAT_TEXT_PROP
-           int         use_popup = strstr((char *)p_cot, "popup") != NULL;
+           use_popup_T use_popup;
 # else
-#  define use_popup 0
+#  define use_popup POPUP_NONE
 # endif
 # ifdef FEAT_TEXT_PROP
            has_info = TRUE;
+           if (strstr((char *)p_cot, "popuphidden") != NULL)
+               use_popup = USEPOPUP_HIDDEN;
+           else if (strstr((char *)p_cot, "popup") != NULL)
+               use_popup = USEPOPUP_NORMAL;
+           else
+               use_popup = USEPOPUP_NONE;
 # endif
-           // Open a preview window.  3 lines by default.  Prefer
-           // 'previewheight' if set and smaller.
+           // Open a preview window and set "curwin" to it.
+           // 3 lines by default, prefer 'previewheight' if set and smaller.
            g_do_tagpreview = 3;
            if (p_pvh > 0 && p_pvh < g_do_tagpreview)
                g_do_tagpreview = p_pvh;
@@ -838,7 +847,7 @@ pum_set_selected(int n, int repeat UNUSED)
 
                    /* Increase the height of the preview window to show the
                     * text, but no more than 'previewheight' lines. */
-                   if (repeat == 0 && !use_popup)
+                   if (repeat == 0 && use_popup == USEPOPUP_NONE)
                    {
                        if (lnum > p_pvh)
                            lnum = p_pvh;
@@ -863,9 +872,9 @@ pum_set_selected(int n, int repeat UNUSED)
                    curwin->w_cursor.lnum = curwin->w_topline;
                    curwin->w_cursor.col = 0;
 # ifdef FEAT_TEXT_PROP
-                   if (use_popup)
+                   if (use_popup != USEPOPUP_NONE)
                    {
-                       pum_position_info_popup();
+                       pum_position_info_popup(curwin);
                        if (win_valid(curwin_save))
                            redraw_win_later(curwin_save, SOME_VALID);
                    }
@@ -907,9 +916,16 @@ pum_set_selected(int n, int repeat UNUSED)
 
                        if (!resized && win_valid(curwin_save))
                        {
+# ifdef FEAT_TEXT_PROP
+                           win_T *wp = curwin;
+# endif
                            ++no_u_sync;
                            win_enter(curwin_save, TRUE);
                            --no_u_sync;
+# ifdef FEAT_TEXT_PROP
+                           if (use_popup == USEPOPUP_HIDDEN && win_valid(wp))
+                               popup_hide(wp);
+# endif
                        }
 
                        /* May need to update the screen again when there are
index f9c127a6c49a8410df4ff31e441a1bea220d4913..95435f8fe7e0bae5eea036e39e4510ae374f3d97 100644 (file)
@@ -2225,7 +2225,7 @@ f_popup_close(typval_T *argvars, typval_T *rettv UNUSED)
        popup_close_and_callback(wp, &argvars[1]);
 }
 
-    static void
+    void
 popup_hide(win_T *wp)
 {
     if ((wp->w_popup_flags & POPF_HIDDEN) == 0)
@@ -2272,7 +2272,11 @@ f_popup_show(typval_T *argvars, typval_T *rettv UNUSED)
     win_T      *wp = find_popup_win(id);
 
     if (wp != NULL)
+    {
        popup_show(wp);
+       if (wp->w_popup_flags & POPF_INFO)
+           pum_position_info_popup(wp);
+    }
 }
 
 /*
index a4d60ba166dc9d68f3ba875c080315447a3186b1..3693cf4265e8cadd04ef67f7c4d3d7b318efafdc 100644 (file)
@@ -35,7 +35,7 @@ void global_exe(char_u *cmd);
 char_u *get_old_sub(void);
 void set_old_sub(char_u *val);
 void free_old_sub(void);
-int prepare_tagpreview(int undo_sync, int use_previewpopup, int use_popup);
+int prepare_tagpreview(int undo_sync, int use_previewpopup, use_popup_T use_popup);
 void ex_help(exarg_T *eap);
 void ex_helpclose(exarg_T *eap);
 char_u *check_help_lang(char_u *arg);
index f5b6c0c90fb6476fcf4baa4cebe987eb92d336ee..c6527b8598a3cf2cb33c5c28b5bc7d8f22d46bbb 100644 (file)
@@ -3,6 +3,7 @@ void pum_display(pumitem_T *array, int size, int selected);
 void pum_call_update_screen(void);
 int pum_under_menu(int row, int col);
 void pum_redraw(void);
+void pum_position_info_popup(win_T *wp);
 void pum_undisplay(void);
 void pum_clear(void);
 int pum_visible(void);
index d6ba3e7f8b7a33e02e261ed31934c00369074be8..4ec4a748debcc4f842bc6730d60055b0e2c47f93 100644 (file)
@@ -26,6 +26,7 @@ void f_popup_dialog(typval_T *argvars, typval_T *rettv);
 void f_popup_menu(typval_T *argvars, typval_T *rettv);
 void f_popup_notification(typval_T *argvars, typval_T *rettv);
 void f_popup_close(typval_T *argvars, typval_T *rettv);
+void popup_hide(win_T *wp);
 void f_popup_hide(typval_T *argvars, typval_T *rettv);
 void popup_show(win_T *wp);
 void f_popup_show(typval_T *argvars, typval_T *rettv);
diff --git a/src/testdir/dumps/Test_popupwin_infopopup_hidden_1.dump b/src/testdir/dumps/Test_popupwin_infopopup_hidden_1.dump
new file mode 100644 (file)
index 0000000..f56ebc4
--- /dev/null
@@ -0,0 +1,14 @@
+|t+0&#ffffff0|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| |t|a|w|o|r|d> @43
+|~+0#4040ff13&| @23| +0#0000001#e0e0e08|w|r|d| @4|W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @23| +0#0000001#ffd7ff255|a|n|o|t|w|r|d| |W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @23| +0#0000001#ffd7ff255|n|o|a|w|r|d| @1|W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @23| +0#0000001#ffd7ff255|t|h|a|t|w|r|d| |W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |U|s|e|r| |d|e|f|i|n|e|d| |c|o|m|p|l|e|t|i|o|n| |(|^|U|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |4| +0#0000000&@26
diff --git a/src/testdir/dumps/Test_popupwin_infopopup_hidden_2.dump b/src/testdir/dumps/Test_popupwin_infopopup_hidden_2.dump
new file mode 100644 (file)
index 0000000..d834e57
--- /dev/null
@@ -0,0 +1,14 @@
+|t+0&#ffffff0|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| |t|a|n|o|t|h|e|r|w|o|r|d> @37
+|~+0#4040ff13&| @23| +0#0000001#ffd7ff255|w|r|d| @4|W| |e|x|t|r|a| |t|e|x|t| | +0&#e0e0e08|i|m@1|e|d|i|a|t|e| |i|n|f|o| |3| | +0#4040ff13#ffffff0@9
+|~| @23| +0#0000001#e0e0e08|a|n|o|t|w|r|d| |W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @23| +0#0000001#ffd7ff255|n|o|a|w|r|d| @1|W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @23| +0#0000001#ffd7ff255|t|h|a|t|w|r|d| |W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |U|s|e|r| |d|e|f|i|n|e|d| |c|o|m|p|l|e|t|i|o|n| |(|^|U|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |2| |o|f| |4| +0#0000000&@26
diff --git a/src/testdir/dumps/Test_popupwin_infopopup_hidden_3.dump b/src/testdir/dumps/Test_popupwin_infopopup_hidden_3.dump
new file mode 100644 (file)
index 0000000..410c393
--- /dev/null
@@ -0,0 +1,14 @@
+|t+0&#ffffff0|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| |t|n|o|i|n|f|o> @42
+|~+0#4040ff13&| @23| +0#0000001#ffd7ff255|w|r|d| @4|W| |e|x|t|r|a| |t|e|x|t| | +0&#e0e0e08|a|s|y|n|c| |i|n|f|o| |4| | +0#4040ff13#ffffff0@13
+|~| @23| +0#0000001#ffd7ff255|a|n|o|t|w|r|d| |W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @23| +0#0000001#e0e0e08|n|o|a|w|r|d| @1|W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @23| +0#0000001#ffd7ff255|t|h|a|t|w|r|d| |W| |e|x|t|r|a| |t|e|x|t| | +0#4040ff13#ffffff0@27
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |U|s|e|r| |d|e|f|i|n|e|d| |c|o|m|p|l|e|t|i|o|n| |(|^|U|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |3| |o|f| |4| +0#0000000&@26
index e84527bf7ff6def6ff5c38aea5f74d8c700a696d..2e2d1df80ed22b1db125ffa9df9d063945cbf7dd 100644 (file)
@@ -2498,6 +2498,41 @@ func Get_popupmenu_lines()
        let id = popup_findinfo()
        eval id->popup_setoptions(#{highlight: 'InfoPopup'})
       endfunc
+
+      func InfoHidden()
+       set completepopup=height:4,border:off,align:menu
+       set completeopt-=popup completeopt+=popuphidden
+       au CompleteChanged * call HandleChange()
+      endfunc
+
+      let s:counter = 0
+      func HandleChange()
+       let s:counter += 1
+       let selected = complete_info(['selected']).selected
+       if selected <= 0
+         " First time: do nothing, info remains hidden
+         return
+       endif
+       if selected == 1
+         " Second time: show info right away
+         let id = popup_findinfo()
+         if id
+           call popup_settext(id, 'immediate info ' .. s:counter)
+           call popup_show(id)
+         endif
+       else
+         " Third time: show info after a short delay
+         call timer_start(100, 'ShowInfo')
+       endif
+      endfunc
+
+      func ShowInfo(...)
+       let id = popup_findinfo()
+       if id
+         call popup_settext(id, 'async info ' .. s:counter)
+         call popup_show(id)
+       endif
+      endfunc
   END
   return lines
 endfunc
@@ -2580,6 +2615,30 @@ func Test_popupmenu_info_align_menu()
   call delete('XtestInfoPopupNb')
 endfunc
 
+func Test_popupmenu_info_hidden()
+  CheckScreendump
+
+  let lines = Get_popupmenu_lines()
+  call add(lines, 'call InfoHidden()')
+  call writefile(lines, 'XtestInfoPopupHidden')
+
+  let buf = RunVimInTerminal('-S XtestInfoPopupHidden', #{rows: 14})
+  call term_wait(buf, 50)
+
+  call term_sendkeys(buf, "A\<C-X>\<C-U>")
+  call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_1', {})
+
+  call term_sendkeys(buf, "\<C-N>")
+  call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_2', {})
+
+  call term_sendkeys(buf, "\<C-N>")
+  call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_3', {})
+
+  call term_sendkeys(buf, "\<Esc>")
+  call StopVimInTerminal(buf)
+  call delete('XtestInfoPopupHidden')
+endfunc
+
 func Test_popupwin_recycle_bnr()
   let bufnr = popup_notification('nothing wrong', {})->winbufnr()
   call popup_clear()
index c9c0943e1435482aa604e8a835cbc30cf2534cb8..76b4c1cf52fd3291ebfe4f753f1e2999abc2a09e 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2192,
 /**/
     2191,
 /**/
index e92352c65ca4b8df682c6ec06d0d71f909848049..43eecf09078ce7733dcac9f730a052a5e6e0ca18 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2112,6 +2112,13 @@ typedef enum {
     FLUSH_INPUT                // flush typebuf and inchar() input
 } flush_buffers_T;
 
+// Argument for prepare_tagpreview()
+typedef enum {
+    USEPOPUP_NONE,
+    USEPOPUP_NORMAL,   // use info popup
+    USEPOPUP_HIDDEN    // use info popup initially hidden
+} use_popup_T;
+
 #include "ex_cmds.h"       // Ex command defines
 #include "spell.h"         // spell checking stuff