]> granicus.if.org Git - vim/commitdiff
patch 8.1.1553: not easy to change the text in a popup window v8.1.1553
authorBram Moolenaar <Bram@vim.org>
Sun, 16 Jun 2019 13:32:14 +0000 (15:32 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 16 Jun 2019 13:32:14 +0000 (15:32 +0200)
Problem:    Not easy to change the text in a popup window.
Solution:   Add popup_settext(). (Ben Jackson, closes #4549)
            Also display a space for an empty popup.

12 files changed:
runtime/doc/popup.txt
src/evalfunc.c
src/popupwin.c
src/proto/popupwin.pro
src/testdir/dumps/Test_popup_settext_01.dump [new file with mode: 0644]
src/testdir/dumps/Test_popup_settext_02.dump [new file with mode: 0644]
src/testdir/dumps/Test_popup_settext_03.dump [new file with mode: 0644]
src/testdir/dumps/Test_popup_settext_04.dump [new file with mode: 0644]
src/testdir/dumps/Test_popup_settext_05.dump [new file with mode: 0644]
src/testdir/dumps/Test_popup_settext_06.dump [new file with mode: 0644]
src/testdir/test_popupwin.vim
src/version.c

index a9f55be2799c7250d9a5ed0cbc4ffc21fb6cc552..02c66c3b3002964db4a9361776e27a66dc937186 100644 (file)
@@ -104,15 +104,18 @@ TODO:
   incomplete cell.
 - Can the buffer be re-used, to avoid using up lots of buffer numbers?
 - Use a popup window for the "info" item of completion instead of using a
-  preview window.
+  preview window.  Ideas in issue #4544.
+  How to add highlighting?
+- When the lines do not fit show a scrollbar (like in the popup menu).
+  Use the mouse wheel for scrolling.
 - Implement:
        popup_filter_menu({id}, {key})
        popup_menu({text}, {options})
        popup_setoptions({id}, {options})
-       flip option
        hidden option
        tabpage option with number
        title option
+       flip option
        transparent text property
 
 
@@ -134,6 +137,7 @@ Manipulating a popup window:
        |popup_show()|          show a previously hidden popup
        |popup_move()|          change the position and size of a popup
        |popup_setoptions()|    override options of a popup
+       |popup_settext()|       replace the popup buffer contents
 
 Closing popup windows:
        |popup_close()|         close one popup
@@ -330,6 +334,11 @@ popup_setoptions({id}, {options})                  *popup_setoptions()*
                {not implemented yet}
                Override options in popup {id} with entries in {options}.
 
+popup_settext({id}, {text})                            *popup_settext()*
+               Set the text of the buffer in poup win {id}. {text} is the
+               same as supplied to |popup_create()|.
+               Does not change the window size or position, other than caused
+               by the different text.
 
 
 POPUP BUFFER AND WINDOW                                        *popup-buffer*
@@ -365,8 +374,9 @@ need them.
 
 POPUP_CREATE() ARGUMENTS                               *popup_create-usage*
 
-The first argument of |popup_create()| specifies the text to be displayed, and
-optionally text properties.  It is in one of three forms:
+The first argument of |popup_create()| (and the second argument to
+|popup_setttext()|) specifies the text to be displayed, and optionally text
+properties.  It is in one of three forms:
 - a string
 - a list of strings
 - a list of dictionaries, where each dictionary has these entries:
@@ -404,7 +414,9 @@ The second argument of |popup_create()| is a dictionary with options:
        flip            When TRUE (the default) and the position is relative
                        to the cursor, flip to below or above the cursor to
                        avoid overlap with the |popupmenu-completion| or
-                       another popup with a higher "zindex".
+                       another popup with a higher "zindex".  When there is
+                       no space above/below the cursor then show the popup to
+                       the side of the popup or popup menu.
                        {not implemented yet}
        maxheight       Maximum height of the contents, excluding border and
                        padding.
@@ -434,7 +446,9 @@ The second argument of |popup_create()| is a dictionary with options:
        wrap            TRUE to make the lines wrap (default TRUE).
        drag            TRUE to allow the popup to be dragged with the mouse
                        by grabbing at at the border.  Has no effect if the
-                       popup does not have a border.
+                       popup does not have a border. As soon as dragging
+                       starts and "pos" is "center" it is changed to
+                       "topleft".
        highlight       Highlight group name to use for the text, stored in
                        the 'wincolor' option.
        padding         List with numbers, defining the padding
index d371c28b664fa220ba78c46b7c0c1700b14e3ac1..8c8bb4d6382e500f44fcc4d2b7d13f00c465ecae 100644 (file)
@@ -822,6 +822,7 @@ static struct fst
     {"popup_hide",     1, 1, f_popup_hide},
     {"popup_move",     2, 2, f_popup_move},
     {"popup_notification", 2, 2, f_popup_notification},
+    {"popup_settext",  2, 2, f_popup_settext},
     {"popup_show",     1, 1, f_popup_show},
 #endif
 #ifdef FEAT_FLOAT
index c0b5e1300cea66557758892e8ecbb7d244f8a704..99ef2908cd4c4987fe01aea4f1e2cbf566dcae63 100644 (file)
@@ -601,8 +601,10 @@ popup_adjust_position(win_T *wp)
        wp->w_topline = wp->w_buffer->b_ml.ml_line_count;
 
     // Compute width based on longest text line and the 'wrap' option.
+    // Use a minimum width of one, so that something shows when there is no
+    // text.
     // TODO: more accurate wrapping
-    wp->w_width = 0;
+    wp->w_width = 1;
     for (lnum = wp->w_topline; lnum <= wp->w_buffer->b_ml.ml_line_count; ++lnum)
     {
        int len = vim_strsize(ml_get_buf(wp->w_buffer, lnum, FALSE));
@@ -703,6 +705,48 @@ typedef enum
     TYPE_DIALOG
 } create_type_T;
 
+/*
+ * Make "buf" empty and set the contents to "text".
+ * Used by popup_create() and popup_settext().
+ */
+    static void
+popup_set_buffer_text(buf_T *buf, typval_T text)
+{
+    int            lnum;
+
+    // Clear the buffer, then replace the lines.
+    curbuf = buf;
+    for (lnum = buf->b_ml.ml_line_count; lnum > 0; --lnum)
+       ml_delete(lnum, FALSE);
+    curbuf = curwin->w_buffer;
+
+    // Add text to the buffer.
+    if (text.v_type == VAR_STRING)
+    {
+       // just a string
+       ml_append_buf(buf, 0, text.vval.v_string, (colnr_T)0, TRUE);
+    }
+    else
+    {
+       list_T *l = text.vval.v_list;
+
+       if (l->lv_len > 0)
+       {
+           if (l->lv_first->li_tv.v_type == VAR_STRING)
+               // list of strings
+               add_popup_strings(buf, l);
+           else
+               // list of dictionaries
+               add_popup_dicts(buf, l);
+       }
+    }
+
+    // delete the line that was in the empty buffer
+    curbuf = buf;
+    ml_delete(buf->b_ml.ml_line_count, FALSE);
+    curbuf = curwin->w_buffer;
+}
+
 /*
  * popup_create({text}, {options})
  * popup_atcursor({text}, {options})
@@ -789,31 +833,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
        // TODO: find tab page "nr"
        emsg("Not implemented yet");
 
-    // Add text to the buffer.
-    if (argvars[0].v_type == VAR_STRING)
-    {
-       // just a string
-       ml_append_buf(buf, 0, argvars[0].vval.v_string, (colnr_T)0, TRUE);
-    }
-    else
-    {
-       list_T *l = argvars[0].vval.v_list;
-
-       if (l->lv_len > 0)
-       {
-           if (l->lv_first->li_tv.v_type == VAR_STRING)
-               // list of strings
-               add_popup_strings(buf, l);
-           else
-               // list of dictionaries
-               add_popup_dicts(buf, l);
-       }
-    }
-
-    // Delete the line of the empty buffer.
-    curbuf = buf;
-    ml_delete(buf->b_ml.ml_line_count, FALSE);
-    curbuf = curwin->w_buffer;
+    popup_set_buffer_text(buf, argvars[0]);
 
     if (type == TYPE_ATCURSOR)
     {
@@ -1112,6 +1132,22 @@ f_popup_show(typval_T *argvars, typval_T *rettv UNUSED)
     }
 }
 
+/*
+ * popup_settext({id}, {text})
+ */
+    void
+f_popup_settext(typval_T *argvars, typval_T *rettv UNUSED)
+{
+    int                id = (int)tv_get_number(&argvars[0]);
+    win_T      *wp = find_popup_win(id);
+
+    if (wp != NULL)
+    {
+       popup_set_buffer_text(wp->w_buffer, argvars[1]);
+       popup_adjust_position(wp);
+    }
+}
+
     static void
 popup_free(win_T *wp)
 {
index 6e93791e61ae4b0b6c25a8caa9b4c5c46b6350ed..e026506c5ab7c6fbe7229483cdacf9e5160a5ea3 100644 (file)
@@ -14,6 +14,7 @@ void f_popup_notification(typval_T *argvars, typval_T *rettv);
 void f_popup_close(typval_T *argvars, typval_T *rettv);
 void f_popup_hide(typval_T *argvars, typval_T *rettv);
 void f_popup_show(typval_T *argvars, typval_T *rettv);
+void f_popup_settext(typval_T *argvars, typval_T *rettv);
 void popup_close(int id);
 void popup_close_tabpage(tabpage_T *tp, int id);
 void close_all_popups(void);
diff --git a/src/testdir/dumps/Test_popup_settext_01.dump b/src/testdir/dumps/Test_popup_settext_01.dump
new file mode 100644 (file)
index 0000000..768c1bd
--- /dev/null
@@ -0,0 +1,10 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @28|t+0#0000001#ffd7ff255|h|i|s| |i|s| |a| |t|e|x|t| +0#4040ff13#ffffff0@30
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| 
diff --git a/src/testdir/dumps/Test_popup_settext_02.dump b/src/testdir/dumps/Test_popup_settext_02.dump
new file mode 100644 (file)
index 0000000..565e97f
--- /dev/null
@@ -0,0 +1,10 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @35| +0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|p|,| |'@1|)| @30|0|,|0|-|1| @8|A|l@1| 
diff --git a/src/testdir/dumps/Test_popup_settext_03.dump b/src/testdir/dumps/Test_popup_settext_03.dump
new file mode 100644 (file)
index 0000000..b2c0504
--- /dev/null
@@ -0,0 +1,10 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @35|a+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
+|~| @35|b+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
+|~| @35|c+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|p|,| |[|'|a|'|,|'|b|'|,|'|c|'|]|)| @19|0|,|0|-|1| @8|A|l@1| 
diff --git a/src/testdir/dumps/Test_popup_settext_04.dump b/src/testdir/dumps/Test_popup_settext_04.dump
new file mode 100644 (file)
index 0000000..8e20916
--- /dev/null
@@ -0,0 +1,10 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @35|a+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|p|,| |[|'|a|'|]|)| @27|0|,|0|-|1| @8|A|l@1| 
diff --git a/src/testdir/dumps/Test_popup_settext_05.dump b/src/testdir/dumps/Test_popup_settext_05.dump
new file mode 100644 (file)
index 0000000..1ae670e
--- /dev/null
@@ -0,0 +1,10 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @35| +0#0000001#ffd7ff255| +0#4040ff13#ffffff0@36
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|p|,| |[|]|)| @30|0|,|0|-|1| @8|A|l@1| 
diff --git a/src/testdir/dumps/Test_popup_settext_06.dump b/src/testdir/dumps/Test_popup_settext_06.dump
new file mode 100644 (file)
index 0000000..99c32c8
--- /dev/null
@@ -0,0 +1,10 @@
+> +0&#ffffff0@74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @33|a+0#0000001#ffd7ff255@3| +0#4040ff13#ffffff0@35
+|~| @33|b+0#0000001#ffd7ff255@3| +0#4040ff13#ffffff0@35
+|~| @33|c+0#0000001#ffd7ff255@3| +0#4040ff13#ffffff0@35
+|~| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| 
index ae41512be5b46935b9f68bdc2036cd28905a2493..ebe24004ae684d51db690e4b2fc42d680281bfd1 100644 (file)
@@ -916,13 +916,13 @@ func Test_popup_empty()
   let winid = popup_create('', {'padding': [2,2,2,2]})
   redraw
   let pos = popup_getpos(winid)
-  call assert_equal(4, pos.width)
+  call assert_equal(5, pos.width)
   call assert_equal(5, pos.height)
 
   let winid = popup_create([], {'border': []})
   redraw
   let pos = popup_getpos(winid)
-  call assert_equal(2, pos.width)
+  call assert_equal(3, pos.width)
   call assert_equal(3, pos.height)
 endfunc
 
@@ -1231,3 +1231,47 @@ func Test_notifications()
   call StopVimInTerminal(buf)
   call delete('XtestNotifications')
 endfunc
+
+function Test_popup_settext()
+  if !CanRunVimInTerminal()
+    throw 'Skipped: cannot make screendumps'
+  endif
+
+  let lines =<< trim END
+    let opts = {'wrap': 0}
+    let p = popup_create('test', opts)
+    call popup_settext(p, 'this is a text')
+  END
+
+  call writefile( lines, 'XtestPopupSetText' )
+  let buf = RunVimInTerminal('-S XtestPopupSetText', {'rows': 10})
+  call VerifyScreenDump(buf, 'Test_popup_settext_01', {})
+
+  " Setting to empty string clears it
+  call term_sendkeys(buf, ":call popup_settext(p, '')\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_settext_02', {})
+
+  " Setting a list
+  call term_sendkeys(buf, ":call popup_settext(p, ['a','b','c'])\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_settext_03', {})
+
+  " Shrinking with a list
+  call term_sendkeys(buf, ":call popup_settext(p, ['a'])\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_settext_04', {})
+
+  " Growing with a list
+  call term_sendkeys(buf, ":call popup_settext(p, ['a','b','c'])\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_settext_03', {})
+
+  " Empty list clears
+  call term_sendkeys(buf, ":call popup_settext(p, [])\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_settext_05', {})
+
+  " Dicts
+  call term_sendkeys(buf, ":call popup_settext(p, [{'text': 'aaaa'}, {'text': 'bbbb'}, {'text': 'cccc'}])\<CR>")
+  call VerifyScreenDump(buf, 'Test_popup_settext_06', {})
+
+  " clean up
+  call StopVimInTerminal(buf)
+  call delete('XtestPopupSetText')
+endfunction
index f960d52fa33d567e6c303e771e433b547ad4c13c..aa11b7ebc4e22a5b0aa017a8057064ce6070656f 100644 (file)
@@ -777,6 +777,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1553,
 /**/
     1552,
 /**/