]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.1.1407: popup_create() does not support text properties v8.1.1407
authorBram Moolenaar <Bram@vim.org>
Sun, 26 May 2019 21:32:06 +0000 (23:32 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 26 May 2019 21:32:06 +0000 (23:32 +0200)
Problem:    Popup_create() does not support text properties.
Solution:   Support the third form of the text argument.

runtime/doc/popup.txt
src/popupwin.c
src/proto/textprop.pro
src/screen.c
src/testdir/dumps/Test_popupwin_02.dump
src/testdir/dumps/Test_popupwin_03.dump
src/testdir/dumps/Test_popupwin_04.dump
src/testdir/test_popupwin.vim
src/textprop.c
src/version.c

index bbab6d03da0f532edf2e4ec1135f501e9cdd60c8..5697edec996e1e07b11890be42b1c29ee8305c54 100644 (file)
@@ -279,7 +279,6 @@ 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:
-       {not implemented yet}
        text            String with the text to display.
        props           A list of text properties.  Optional.
                        Each entry is a dictionary, like the third argument of
@@ -369,12 +368,16 @@ outside of the Vim window will not be displayed, thus truncated.
 
 POPUP TEXT PROPERTIES                                  *popup-props*
 
-{not implemented yet}
-These are similar to the third argument of |prop_add()|, but not exactly the
-same, since they only apply to one line.
+These are similar to the third argument of |prop_add()| except:
+- "lnum" is always the current line in the list
+- "bufnr" is always the buffer of the popup
+- "col" is in the Dict instead of a separate argument
+- "transparent" is extra
+So we get:
        col             starting column, counted in bytes, use one for the
                        first column.
        length          length of text in bytes; can be zero
+       end_lnum        line number for the end of the text
        end_col         column just after the text; not used when "length" is
                        present; when {col} and "end_col" are equal, this is a
                        zero-width text property
@@ -385,6 +388,7 @@ same, since they only apply to one line.
        transparent     do not show these characters, show the text under it;
                        if there is an border character to the right or below
                        it will be made transparent as well
+                       {not implemented yet}
 
 
 POPUP FILTER                                           *popup-filter*
index 0857f6b0a3ee176e14bd9591061950413f54e809..95a91f93916578b06fa44f04887ccda370a8c7df 100644 (file)
@@ -59,6 +59,91 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict)
                                                   str, OPT_FREE|OPT_LOCAL, 0);
 }
 
+/*
+ * Add lines to the popup from a list of strings.
+ */
+    static void
+add_popup_strings(buf_T *buf, list_T *l)
+{
+    listitem_T  *li;
+    linenr_T    lnum = 0;
+    char_u     *p;
+
+    for (li = l->lv_first; li != NULL; li = li->li_next)
+       if (li->li_tv.v_type == VAR_STRING)
+       {
+           p = li->li_tv.vval.v_string;
+           ml_append_buf(buf, lnum++,
+                              p == NULL ? (char_u *)"" : p, (colnr_T)0, TRUE);
+       }
+}
+
+/*
+ * Add lines to the popup from a list of dictionaries.
+ */
+    static void
+add_popup_dicts(buf_T *buf, list_T *l)
+{
+    listitem_T  *li;
+    listitem_T  *pli;
+    linenr_T    lnum = 0;
+    char_u     *p;
+    dict_T     *dict;
+
+    // first add the text lines
+    for (li = l->lv_first; li != NULL; li = li->li_next)
+    {
+       if (li->li_tv.v_type != VAR_DICT)
+       {
+           emsg(_(e_dictreq));
+           return;
+       }
+       dict = li->li_tv.vval.v_dict;
+       p = dict == NULL ? NULL
+                             : dict_get_string(dict, (char_u *)"text", FALSE);
+       ml_append_buf(buf, lnum++,
+                              p == NULL ? (char_u *)"" : p, (colnr_T)0, TRUE);
+    }
+
+    // add the text properties
+    lnum = 1;
+    for (li = l->lv_first; li != NULL; li = li->li_next, ++lnum)
+    {
+       dictitem_T      *di;
+       list_T          *plist;
+
+       dict = li->li_tv.vval.v_dict;
+       di = dict_find(dict, (char_u *)"props", -1);
+       if (di != NULL)
+       {
+           if (di->di_tv.v_type != VAR_LIST)
+           {
+               emsg(_(e_listreq));
+               return;
+           }
+           plist = di->di_tv.vval.v_list;
+           if (plist != NULL)
+           {
+               for (pli = plist->lv_first; pli != NULL; pli = pli->li_next)
+               {
+                   if (pli->li_tv.v_type != VAR_DICT)
+                   {
+                       emsg(_(e_dictreq));
+                       return;
+                   }
+                   dict = pli->li_tv.vval.v_dict;
+                   if (dict != NULL)
+                   {
+                       int col = dict_get_number(dict, (char_u *)"col");
+
+                       prop_add_common( lnum, col, dict, buf, NULL);
+                   }
+               }
+           }
+       }
+    }
+}
+
 /*
  * popup_create({text}, {options})
  */
@@ -128,27 +213,21 @@ f_popup_create(typval_T *argvars, typval_T *rettv)
 
     // 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 if (argvars[0].vval.v_list->lv_first->li_tv.v_type == VAR_STRING)
-    {
-       listitem_T  *li;
-       linenr_T    lnum = 0;
-       char_u      *p;
-
-       // list of strings
-       for (li = argvars[0].vval.v_list->lv_first; li != NULL;
-                                                             li = li->li_next)
-           if (li->li_tv.v_type == VAR_STRING)
-           {
-               p = li->li_tv.vval.v_string;
-               ml_append_buf(buf, lnum++,
-                              p == NULL ? (char_u *)"" : p, (colnr_T)0, TRUE);
-           }
     }
     else
-       // TODO: handle a list of dictionaries
-       emsg("Not implemented yet");
+    {
+       list_T *l = argvars[0].vval.v_list;
+
+       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;
index 1301f31a514bfba60fb25ebb0d1848567e33435f..a6775dbfda62ccd9372e02c76cda7788e3d65ce8 100644 (file)
@@ -1,5 +1,6 @@
 /* textprop.c */
 void f_prop_add(typval_T *argvars, typval_T *rettv);
+void prop_add_common(linenr_T start_lnum, colnr_T start_col, dict_T *dict, buf_T *default_buf, typval_T *dict_arg);
 int get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change);
 proptype_T *text_prop_type_by_id(buf_T *buf, int id);
 void f_prop_clear(typval_T *argvars, typval_T *rettv);
index 40cff9acc2284b6c884f794865ef1075c7433ade..7354220cbb40986de7ffc560353d4ff89c0ab2a2 100644 (file)
@@ -4405,7 +4405,10 @@ win_line(
                char_attr = hl_combine_attr(line_attr, search_attr);
 # ifdef FEAT_TEXT_PROP
            else if (text_prop_type != NULL)
-               char_attr = hl_combine_attr(line_attr, text_prop_attr);
+           {
+               char_attr = hl_combine_attr(
+                       line_attr != 0 ? line_attr : win_attr, text_prop_attr);
+           }
 # endif
            else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL)
                                || vcol < fromcol || vcol_prev < fromcol_prev
@@ -4429,7 +4432,8 @@ win_line(
                        char_attr = hl_combine_attr(
                                                  syntax_attr, text_prop_attr);
                    else
-                       char_attr = text_prop_attr;
+                       char_attr = hl_combine_attr(
+                                                 win_attr, text_prop_attr);
                }
                else
 #endif
index c2aa7a287a35acae1822d63a128e4528ef3d4ff7..0de7f4954e8283664814d0a602c85973878c10b5 100644 (file)
@@ -2,9 +2,9 @@
 > +0#0000000#ffffff0@74
 |~+0#4040ff13&| @73
 |~| @6|o+0#0000001#ffd7ff255|t|h|e|r| |t|a|b| @10| +0#4040ff13#ffffff0@46
+|~| @6|a+0#0000001#ffd7ff255| |c+0#ff404010&|o|m@1|e|n|t| +0#0000001&|l|i|n|e| @5| +0#4040ff13#ffffff0@46
 |~| @73
 |~| @73
 |~| @73
 |~| @73
-|~| @73
-|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|c|r|e|a|t|e|(|'|o|t|h|e|r| |t|a|b|'|,| |{|'|l|i|n|e|'|:| |4|,| |'|c|o|l|'|:| |9|}|)| @2|0|,|0|-|1| @8|A|l@1| 
+| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| 
index 4f6f9ddc4ae7a89122d0e4d384a730371207c59f..d842654b78337f90f14e244aba1eace081eaf250 100644 (file)
@@ -7,4 +7,4 @@
 |6| @73
 |7| @73
 |8| @73
-|:|c|a|l@1| |p|o|p|u|p|_|c|r|e|a|t|e|(|'|o|t|h|e|r| |t|a|b|'|,| |{|'|l|i|n|e|'|:| |4|,| |'|c|o| @9|1|,|1| @10|T|o|p| 
+@57|1|,|1| @10|T|o|p| 
index a64245560c97fa2ad94a62e1f58d98ab9fecd9c1..c8b04389c41e15b73e86dc1753de18ff9075389d 100644 (file)
@@ -2,7 +2,7 @@
 |~+0#4040ff13&| @73
 |~| @73
 |~| @6|o+0#0000001#ffd7ff255|t|h|e|r| |t|a|b| @10| +0#4040ff13#ffffff0@46
-|~| @73
+|~| @6|a+0#0000001#ffd7ff255| |c+0#ff404010&|o|m@1|e|n|t| +0#0000001&|l|i|n|e| @5| +0#4040ff13#ffffff0@46
 |~| @73
 |~| @73
 |~| @73
index 73efe0a738ebc15b1cb56de384dd8be154a96850..f1394fbf872d8ed6341d6e14505ed309139aac1b 100644 (file)
@@ -14,6 +14,8 @@ func Test_simple_popup()
        \ "call setline(1, range(1, 100))",
        \ "hi PopupColor1 ctermbg=lightblue",
        \ "hi PopupColor2 ctermbg=lightcyan",
+       \ "hi Comment ctermfg=red",
+       \ "call prop_type_add('comment', {'highlight': 'Comment'})",
        \ "let winid = popup_create('hello there', {'line': 3, 'col': 11, 'highlight': 'PopupColor1'})",
        \ "let winid2 = popup_create(['another one', 'another two', 'another three'], {'line': 3, 'col': 25})",
        \ "call setwinvar(winid2, '&wincolor', 'PopupColor2')",
@@ -23,7 +25,12 @@ func Test_simple_popup()
 
   " Add a tabpage
   call term_sendkeys(buf, ":tabnew\<CR>")
-  call term_sendkeys(buf, ":call popup_create('other tab', {'line': 4, 'col': 9})\<CR>")
+  call term_sendkeys(buf, ":call popup_create(["
+       \ .. "{'text': 'other tab'},"
+       \ .. "{'text': 'a comment line', 'props': [{"
+       \ .. "'col': 3, 'length': 7, 'type': 'comment'"
+       \ .. "}]},"
+       \ .. "], {'line': 4, 'col': 9})\<CR>")
   call VerifyScreenDump(buf, 'Test_popupwin_02', {})
 
   " switch back to first tabpage
index 0abae13278b31b632ea0698e602122f8ddea6a3a..8ad795ac0906384a7f1b5051218e845206810a92 100644 (file)
@@ -142,23 +142,8 @@ get_bufnr_from_arg(typval_T *arg, buf_T **buf)
     void
 f_prop_add(typval_T *argvars, typval_T *rettv UNUSED)
 {
-    linenr_T   lnum;
     linenr_T   start_lnum;
-    linenr_T   end_lnum;
     colnr_T    start_col;
-    colnr_T    end_col;
-    dict_T     *dict;
-    char_u     *type_name;
-    proptype_T *type;
-    buf_T      *buf = curbuf;
-    int                id = 0;
-    char_u     *newtext;
-    int                proplen;
-    size_t     textlen;
-    char_u     *props = NULL;
-    char_u     *newprops;
-    textprop_T tmp_prop;
-    int                i;
 
     start_lnum = tv_get_number(&argvars[0]);
     start_col = tv_get_number(&argvars[1]);
@@ -172,7 +157,38 @@ f_prop_add(typval_T *argvars, typval_T *rettv UNUSED)
        emsg(_(e_dictreq));
        return;
     }
-    dict = argvars[2].vval.v_dict;
+
+    prop_add_common(start_lnum, start_col, argvars[2].vval.v_dict,
+                                                         curbuf, &argvars[2]);
+}
+
+/*
+ * Shared between prop_add() and popup_create().
+ * "dict_arg" is the function argument of a dict containing "bufnr".
+ * it is NULL for popup_create().
+ */
+    void
+prop_add_common(
+       linenr_T    start_lnum,
+       colnr_T     start_col,
+       dict_T      *dict,
+       buf_T       *default_buf,
+       typval_T    *dict_arg)
+{
+    linenr_T   lnum;
+    linenr_T   end_lnum;
+    colnr_T    end_col;
+    char_u     *type_name;
+    proptype_T *type;
+    buf_T      *buf = default_buf;
+    int                id = 0;
+    char_u     *newtext;
+    int                proplen;
+    size_t     textlen;
+    char_u     *props = NULL;
+    char_u     *newprops;
+    textprop_T tmp_prop;
+    int                i;
 
     if (dict == NULL || dict_find(dict, (char_u *)"type", -1) == NULL)
     {
@@ -221,7 +237,7 @@ f_prop_add(typval_T *argvars, typval_T *rettv UNUSED)
     if (dict_find(dict, (char_u *)"id", -1) != NULL)
        id = dict_get_number(dict, (char_u *)"id");
 
-    if (get_bufnr_from_arg(&argvars[2], &buf) == FAIL)
+    if (dict_arg != NULL && get_bufnr_from_arg(dict_arg, &buf) == FAIL)
        return;
 
     type = lookup_prop_type(type_name, buf);
@@ -278,12 +294,12 @@ f_prop_add(typval_T *argvars, typval_T *rettv UNUSED)
        mch_memmove(newtext, buf->b_ml.ml_line_ptr, textlen);
 
        // Find the index where to insert the new property.
-       // Since the text properties are not aligned properly when stored with the
-       // text, we need to copy them as bytes before using it as a struct.
+       // Since the text properties are not aligned properly when stored with
+       // the text, we need to copy them as bytes before using it as a struct.
        for (i = 0; i < proplen; ++i)
        {
            mch_memmove(&tmp_prop, props + i * sizeof(textprop_T),
-                                                              sizeof(textprop_T));
+                                                          sizeof(textprop_T));
            if (tmp_prop.tp_col >= col)
                break;
        }
@@ -298,7 +314,7 @@ f_prop_add(typval_T *argvars, typval_T *rettv UNUSED)
        tmp_prop.tp_flags = (lnum > start_lnum ? TP_FLAG_CONT_PREV : 0)
                          | (lnum < end_lnum ? TP_FLAG_CONT_NEXT : 0);
        mch_memmove(newprops + i * sizeof(textprop_T), &tmp_prop,
-                                                              sizeof(textprop_T));
+                                                          sizeof(textprop_T));
 
        if (i < proplen)
            mch_memmove(newprops + (i + 1) * sizeof(textprop_T),
index 5df9639743220925af6cd2ee92edf57f25ce673e..a208d326d0959d6c7940468d707d8ea767d50e54 100644 (file)
@@ -767,6 +767,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1407,
 /**/
     1406,
 /**/