patch 9.1.0754: fixed order of items in insert-mode completion menu

Commit: 
https://github.com/vim/vim/commit/6a89c94a9eeee53481ced1a1260a177bffde4c0f
Author: glepnir <glephun...@gmail.com>
Date:   Tue Oct 1 20:32:12 2024 +0200

    patch 9.1.0754: fixed order of items in insert-mode completion menu
    
    Problem:  fixed order of items in insert-mode completion menu
    Solution: Introduce the 'completeitemalign' option with default
              value "abbr,kind,menu" (glepnir).
    
    Adding an new option `completeitemalign` abbr is `cia` to custom
    the complete-item order in popupmenu.
    
    closes: #14006
    closes: #15760
    
    Signed-off-by: glepnir <glephun...@gmail.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 49087d373..39806015e 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2102,6 +2102,16 @@ A jump table for the options with a short description 
can be found at |Q_op|.
        This option cannot be set from a |modeline| or in the |sandbox|, for
        security reasons.
 
+                                               *'completeitemalign'* *'cia'*
+'completeitemalign' 'cia' string (default: "abbr,kind,menu")
+                         global
+       A comma-separated list of |complete-items| that controls the alignment
+       and display order of items in the popup menu during Insert mode
+       completion. The supported values are abbr, kind, and menu. These
+       options allow to customize how the completion items are shown in the
+       popup menu.  Note: must always contain those three values in any
+       order.
+
                                                *'completeopt'* *'cot'*
 'completeopt' 'cot'    string  (default: "menu,preview")
                        global or local to buffer |global-local|
diff --git a/runtime/doc/tags b/runtime/doc/tags
index 8b0a9598f..77ef32ecb 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -134,6 +134,7 @@ $quote      eval.txt        /*$quote*
 'character'    intro.txt       /*'character'*
 'charconvert'  options.txt     /*'charconvert'*
 'ci'   options.txt     /*'ci'*
+'cia'  options.txt     /*'cia'*
 'cin'  options.txt     /*'cin'*
 'cindent'      options.txt     /*'cindent'*
 'cink' options.txt     /*'cink'*
@@ -161,6 +162,7 @@ $quote      eval.txt        /*$quote*
 'compatible'   options.txt     /*'compatible'*
 'complete'     options.txt     /*'complete'*
 'completefunc' options.txt     /*'completefunc'*
+'completeitemalign'    options.txt     /*'completeitemalign'*
 'completeopt'  options.txt     /*'completeopt'*
 'completepopup'        options.txt     /*'completepopup'*
 'completeslash'        options.txt     /*'completeslash'*
diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index 147f34526..d684b4905 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2024 Sep 23
+*version9.txt*  For Vim version 9.1.  Last change: 2024 Oct 01
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41642,6 +41642,8 @@ Commands: ~
 
 Options: ~
 
+'completeitemalign'    Order of |complete-items| in Insert mode completion
+                       popup
 'winfixbuf'            Keep buffer focused in a window
 'tabclose'             Which tab page to focus after closing a tab page
 't_xo'                 Terminal uses XON/XOFF handshaking (e.g. vt420)
diff --git a/runtime/optwin.vim b/runtime/optwin.vim
index 8306ed39f..99b1ecfd2 100644
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -849,6 +849,8 @@ if has("insert_expand")
   call <SID>OptionL("cpt")
   call <SID>AddOption("completeopt", gettext("whether to use a popup menu for 
Insert mode completion"))
   call <SID>OptionL("cot")
+  call <SID>AddOption("completeitemalign", gettext("popup menu item align 
order"))
+  call <SID>OptionG("cia", &cia)
   if exists("+completepopup")
     call <SID>AddOption("completepopup", gettext("options for the Insert mode 
completion info popup"))
     call <SID>OptionG("cpp", &cpp)
diff --git a/src/insexpand.c b/src/insexpand.c
index 63bf0700d..a774a3309 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -87,15 +87,6 @@ static char *ctrl_x_mode_names[] = {
 };
 #endif
 
-/*
- * Array indexes used for cp_text[].
- */
-#define CPT_ABBR       0       // "abbr"
-#define CPT_MENU       1       // "menu"
-#define CPT_KIND       2       // "kind"
-#define CPT_INFO       3       // "info"
-#define CPT_COUNT      4       // Number of entries
-
 /*
  * Structure used to store one match for insert completion.
  */
@@ -1338,8 +1329,7 @@ ins_compl_build_pum(void)
            }
 
            if (compl->cp_text[CPT_ABBR] != NULL)
-               compl_match_array[i].pum_text =
-                   compl->cp_text[CPT_ABBR];
+               compl_match_array[i].pum_text = compl->cp_text[CPT_ABBR];
            else
                compl_match_array[i].pum_text = compl->cp_str;
            compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND];
diff --git a/src/option.h b/src/option.h
index fba267287..ef39031aa 100644
--- a/src/option.h
+++ b/src/option.h
@@ -513,6 +513,8 @@ EXTERN char_u       *p_cpt;         // 'complete'
 EXTERN int     p_confirm;      // 'confirm'
 #endif
 EXTERN int     p_cp;           // 'compatible'
+EXTERN char_u  *p_cia;         // 'completeitemalign'
+EXTERN unsigned cia_flags;     // order flags of 'completeitemalign'
 EXTERN char_u  *p_cot;         // 'completeopt'
 EXTERN unsigned        cot_flags;      // flags from 'completeopt'
 // Keep in sync with p_cot_values in optionstr.c
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 8982ac600..4a5bd638c 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -653,6 +653,10 @@ static struct vimoption options[] =
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCTX_INIT},
+    {"completeitemalign", "cia", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
+                           (char_u *)&p_cia, PV_NONE, 
did_set_completeitemalign, NULL,
+                           {(char_u *)"abbr,kind,menu", (char_u *)0L}
+                           SCTX_INIT},
     {"completeopt",   "cot",  P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
                            (char_u *)&p_cot, PV_COT, did_set_completeopt, 
expand_set_completeopt,
                            {(char_u *)"menu,preview", (char_u *)0L}
diff --git a/src/optionstr.c b/src/optionstr.c
index b6249a2f3..bf7135ab0 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -1635,6 +1635,58 @@ expand_set_completeopt(optexpand_T *args, int 
*numMatches, char_u ***matches)
            matches);
 }
 
+/*
+ * The 'completeitemalign' option is changed.
+ */
+    char *
+did_set_completeitemalign(optset_T *args UNUSED)
+{
+    char_u     *p = p_cia;
+    unsigned   new_cia_flags = 0;
+    int                seen[3] = { FALSE, FALSE, FALSE };
+    int                count = 0;
+    char_u     buf[10];
+
+    while (*p)
+    {
+       copy_option_part(&p, buf, sizeof(buf), ",");
+       if (count >= 3)
+           return e_invalid_argument;
+
+       if (STRCMP(buf, "abbr") == 0)
+       {
+           if (seen[CPT_ABBR])
+               return e_invalid_argument;
+           new_cia_flags = new_cia_flags * 10 + CPT_ABBR;
+           seen[CPT_ABBR] = TRUE;
+           count++;
+       }
+       else if (STRCMP(buf, "kind") == 0)
+       {
+           if (seen[CPT_KIND])
+               return e_invalid_argument;
+           new_cia_flags = new_cia_flags * 10 + CPT_KIND;
+           seen[CPT_KIND] = TRUE;
+           count++;
+       }
+       else if (STRCMP(buf, "menu") == 0)
+       {
+           if (seen[CPT_MENU])
+               return e_invalid_argument;
+           new_cia_flags = new_cia_flags * 10 + CPT_MENU;
+           seen[CPT_MENU] = TRUE;
+           count++;
+       }
+       else
+           return e_invalid_argument;
+    }
+    if (new_cia_flags == 0 || count != 3)
+       return e_invalid_argument;
+
+    cia_flags = new_cia_flags;
+    return NULL;
+}
+
 #if (defined(FEAT_PROP_POPUP) && defined(FEAT_QUICKFIX)) || defined(PROTO)
 /*
  * The 'completepopup' option is changed.
diff --git a/src/popupmenu.c b/src/popupmenu.c
index da8241b91..010a9872f 100644
--- a/src/popupmenu.c
+++ b/src/popupmenu.c
@@ -536,6 +536,28 @@ pum_screen_puts_with_attrs(
     }
 }
 
+
+    static inline void
+pum_align_order(int *order)
+{
+    int is_default = cia_flags == 0;
+    order[0] = is_default ? CPT_ABBR : cia_flags / 100;
+    order[1] = is_default ? CPT_KIND : (cia_flags / 10) % 10;
+    order[2] = is_default ? CPT_MENU : cia_flags % 10;
+}
+
+    static inline char_u *
+pum_get_item(int index, int type)
+{
+    switch(type)
+    {
+       case CPT_ABBR: return pum_array[index].pum_text;
+       case CPT_KIND: return pum_array[index].pum_kind;
+       case CPT_MENU: return pum_array[index].pum_extra;
+    }
+    return NULL;
+}
+
 /*
  * Redraw the popup menu, using "pum_first" and "pum_selected".
  */
@@ -549,19 +571,25 @@ pum_redraw(void)
     hlf_T      *hlfs; // array used for highlights
     hlf_T      hlf;
     int                attr;
-    int                i;
+    int                i, j;
     int                idx;
     char_u     *s;
     char_u     *p = NULL;
-    int                totwidth, width, w;
+    int                totwidth, width, w;  // total-width item-width 
char-width
     int                thumb_pos = 0;
     int                thumb_height = 1;
-    int                round;
+    int                item_type;
+    int                order[3];
+    int                next_isempty = FALSE;
     int                n;
+    int                items_width_array[3] = { pum_base_width, pum_kind_width,
+                                                           pum_extra_width };
+    int                basic_width;  // first item width
+    int                last_isabbr = FALSE;
 
     hlf_T      hlfsNorm[3];
     hlf_T      hlfsSel[3];
-    // "word"
+    // "word"/"abbr"
     hlfsNorm[0] = HLF_PNI;
     hlfsSel[0] = HLF_PSI;
     // "kind"
@@ -621,28 +649,24 @@ pum_redraw(void)
                screen_putchar(' ', row, pum_col - 1, attr);
 
        // Display each entry, use two spaces for a Tab.
-       // Do this 3 times:
-       // 0 - main text
-       // 1 - kind
-       // 2 - extra info
+       // Do this 3 times and order from p_cia
        col = pum_col;
        totwidth = 0;
-       for (round = 0; round < 3; ++round)
+       pum_align_order(order);
+       basic_width = items_width_array[order[0]];
+       last_isabbr = order[2] == CPT_ABBR;
+       for (j = 0; j < 3; ++j)
        {
-           hlf = hlfs[round];
+           item_type = order[j];
+           hlf = hlfs[item_type];
            attr = highlight_attr[hlf];
            if (pum_array[idx].pum_user_hlattr > 0)
                attr = hl_combine_attr(attr, pum_array[idx].pum_user_hlattr);
-           if (round == 1 && pum_array[idx].pum_user_kind_hlattr > 0)
+           if (item_type == CPT_KIND && pum_array[idx].pum_user_kind_hlattr > 
0)
                attr = hl_combine_attr(attr, 
pum_array[idx].pum_user_kind_hlattr);
            width = 0;
            s = NULL;
-           switch (round)
-           {
-               case 0: p = pum_array[idx].pum_text; break;
-               case 1: p = pum_array[idx].pum_kind; break;
-               case 2: p = pum_array[idx].pum_extra; break;
-           }
+           p = pum_get_item(idx, item_type);
            if (p != NULL)
                for ( ; ; MB_PTR_ADV(p))
                {
@@ -774,33 +798,35 @@ pum_redraw(void)
                        width += w;
                }
 
-           if (round > 0)
-               n = pum_kind_width + 1;
+           if (j > 0)
+               n = items_width_array[order[1]] + (last_isabbr ? 0 : 1);
            else
-               n = 1;
+               n = order[j] == CPT_ABBR ? 1 : 0;
+
+           if (j + 1 < 3)
+               next_isempty = pum_get_item(idx, order[j + 1]) == NULL;
 
            // Stop when there is nothing more to display.
-           if (round == 2
-                   || (round == 1 && pum_array[idx].pum_extra == NULL)
-                   || (round == 0 && pum_array[idx].pum_kind == NULL
-                                         && pum_array[idx].pum_extra == NULL)
+           if (j == 2
+                   || (next_isempty && (j == 1 || (j == 0
+                               && pum_get_item(idx, order[j + 2]) == NULL)))
                    || pum_base_width + n >= pum_width)
                break;
 #ifdef FEAT_RIGHTLEFT
            if (pum_rl)
            {
-               screen_fill(row, row + 1, pum_col - pum_base_width - n + 1,
+               screen_fill(row, row + 1, pum_col - basic_width - n + 1,
                                                    col + 1, ' ', ' ', attr);
-               col = pum_col - pum_base_width - n;
+               col = pum_col - basic_width - n;
            }
            else
 #endif
            {
-               screen_fill(row, row + 1, col, pum_col + pum_base_width + n,
+               screen_fill(row, row + 1, col, pum_col + basic_width + n,
                                                              ' ', ' ', attr);
-               col = pum_col + pum_base_width + n;
+               col = pum_col + basic_width + n;
            }
-           totwidth = pum_base_width + n;
+           totwidth = basic_width + n;
        }
 
 #ifdef FEAT_RIGHTLEFT
diff --git a/src/proto/optionstr.pro b/src/proto/optionstr.pro
index 39c40f39b..c034c1192 100644
--- a/src/proto/optionstr.pro
+++ b/src/proto/optionstr.pro
@@ -42,6 +42,7 @@ char *did_set_complete(optset_T *args);
 int expand_set_complete(optexpand_T *args, int *numMatches, char_u ***matches);
 char *did_set_completeopt(optset_T *args);
 int expand_set_completeopt(optexpand_T *args, int *numMatches, char_u 
***matches);
+char *did_set_completeitemalign(optset_T *args);
 char *did_set_completepopup(optset_T *args);
 char *did_set_completeslash(optset_T *args);
 int expand_set_completeslash(optexpand_T *args, int *numMatches, char_u 
***matches);
diff --git a/src/testdir/dumps/Test_pum_completeitemalign_01.dump 
b/src/testdir/dumps/Test_pum_completeitemalign_01.dump
new file mode 100644
index 000000000..2a2f6f017
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_completeitemalign_01.dump
@@ -0,0 +1,20 @@
+|f+0&#ffffff0|o@1> @71
+|f+0#0000001#e0e0e08|o@1| @1|S| |m|e|n|u| @3| +0#4040ff13#ffffff0@59
+|b+0#0000001#ffd7ff255|a|r| @1|T| |m|e|n|u| @3| +0#4040ff13#ffffff0@59
+|你*0#0000001#ffd7ff255|好| +&|C| |中*&|文| +&@3| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| 
|m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@34
diff --git a/src/testdir/dumps/Test_pum_completeitemalign_02.dump 
b/src/testdir/dumps/Test_pum_completeitemalign_02.dump
new file mode 100644
index 000000000..f0068271e
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_completeitemalign_02.dump
@@ -0,0 +1,20 @@
+|f+0&#ffffff0|o@1> @71
+|f+0#0000001#e0e0e08|o@1| @1|m|e|n|u| |S| @3| +0#4040ff13#ffffff0@59
+|b+0#0000001#ffd7ff255|a|r| @1|m|e|n|u| |T| @3| +0#4040ff13#ffffff0@59
+|你*0#0000001#ffd7ff255|好| +&|中*&|文| +&|C| @3| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| 
|m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@34
diff --git a/src/testdir/dumps/Test_pum_completeitemalign_03.dump 
b/src/testdir/dumps/Test_pum_completeitemalign_03.dump
new file mode 100644
index 000000000..a16954f7f
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_completeitemalign_03.dump
@@ -0,0 +1,20 @@
+|f+0&#ffffff0|o@1> @71
+|S+0#0000001#e0e0e08| |f|o@1| @1|m|e|n|u| @3| +0#4040ff13#ffffff0@59
+|T+0#0000001#ffd7ff255| |b|a|r| @1|m|e|n|u| @3| +0#4040ff13#ffffff0@59
+|C+0#0000001#ffd7ff255| |你*&|好| +&|中*&|文| +&@3| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| 
|m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@34
diff --git a/src/testdir/dumps/Test_pum_completeitemalign_04.dump 
b/src/testdir/dumps/Test_pum_completeitemalign_04.dump
new file mode 100644
index 000000000..8c9123afa
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_completeitemalign_04.dump
@@ -0,0 +1,20 @@
+|f+0&#ffffff0|o@1> @71
+|S+0#0000001#e0e0e08| |m|e|n|u| |f|o@1| @4| +0#4040ff13#ffffff0@59
+|T+0#0000001#ffd7ff255| |m|e|n|u| |b|a|r| @4| +0#4040ff13#ffffff0@59
+|C+0#0000001#ffd7ff255| |中*&|文| +&|你*&|好| +&@3| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| 
|m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@34
diff --git a/src/testdir/dumps/Test_pum_completeitemalign_05.dump 
b/src/testdir/dumps/Test_pum_completeitemalign_05.dump
new file mode 100644
index 000000000..7209c85e6
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_completeitemalign_05.dump
@@ -0,0 +1,20 @@
+|f+0&#ffffff0|o@1> @71
+|m+0#0000001#e0e0e08|e|n|u| |f|o@1| @1|S| @3| +0#4040ff13#ffffff0@59
+|m+0#0000001#ffd7ff255|e|n|u| |b|a|r| @1|T| @3| +0#4040ff13#ffffff0@59
+|中*0#0000001#ffd7ff255|文| +&|你*&|好| +&|C| @3| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| 
|m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@34
diff --git a/src/testdir/dumps/Test_pum_completeitemalign_06.dump 
b/src/testdir/dumps/Test_pum_completeitemalign_06.dump
new file mode 100644
index 000000000..03210acbb
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_completeitemalign_06.dump
@@ -0,0 +1,20 @@
+|f+0&#ffffff0|o@1> @71
+|m+0#0000001#e0e0e08|e|n|u| |S| |f|o@1| @4| +0#4040ff13#ffffff0@59
+|m+0#0000001#ffd7ff255|e|n|u| |T| |b|a|r| @4| +0#4040ff13#ffffff0@59
+|中*0#0000001#ffd7ff255|文| +&|C| |你*&|好| +&@3| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| 
|m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@34
diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim
index c601158c2..936a0fa86 100644
--- a/src/testdir/gen_opt_test.vim
+++ b/src/testdir/gen_opt_test.vim
@@ -80,6 +80,7 @@ let test_values = {
       \ 'complete': [['', 'w,b'], ['xxx']],
       \ 'concealcursor': [['', 'n', 'nvic'], ['xxx']],
       \ 'completeopt': [['', 'menu', 'menu,longest'], ['xxx', 
'menu,,,longest,']],
+      \ 'completeitemalign': [['abbr,kind,menu'], 
['xxx','abbr,menu','abbr,menu,kind,abbr', 'abbr', 'abbr1234,kind', '']],
       \ 'completepopup': [['', 'height:13', 'highlight:That', 
'width:10,height:234,highlight:Mine'], ['height:yes', 'width:no', 'xxx', 
'xxx:99', 'border:maybe', 'border:1']],
       \ 'completeslash': [['', 'slash', 'backslash'], ['xxx']],
       \ 'cryptmethod': [['', 'zip'], ['xxx']],
diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim
index caec8ff0f..1758f7498 100644
--- a/src/testdir/test_popup.vim
+++ b/src/testdir/test_popup.vim
@@ -1581,4 +1581,64 @@ func Test_pum_user_kind_hlgroup()
   call StopVimInTerminal(buf)
 endfunc
 
+func Test_pum_completeitemalign()
+  CheckScreendump
+  let lines =<< trim END
+    func Omni_test(findstart, base)
+      if a:findstart
+        return col(".")
+      endif
+      return {
+            \ 'words': [
+            \ { 'word': 'foo', 'kind': 'S', 'menu': 'menu' },
+            \ { 'word': 'bar', 'kind': 'T', 'menu': 'menu' },
+            \ { 'word': '你好', 'kind': 'C', 'menu': '中文' },
+            \]}
+    endfunc
+    set omnifunc=Omni_test
+    command! -nargs=0 T1 set cia=abbr,kind,menu
+    command! -nargs=0 T2 set cia=abbr,menu,kind
+    command! -nargs=0 T3 set cia=kind,abbr,menu
+    command! -nargs=0 T4 set cia=kind,menu,abbr
+    command! -nargs=0 T5 set cia=menu,abbr,kind
+    command! -nargs=0 T6 set cia=menu,kind,abbr
+    command! -nargs=0 T7 set cia&
+  END
+  call writefile(lines, 'Xscript', 'D')
+  let  buf = RunVimInTerminal('-S Xscript', {})
+  call TermWait(buf)
+
+  " T1 is default
+  call term_sendkeys(buf, ":T1\<CR>S\<C-X>\<C-O>")
+  call VerifyScreenDump(buf, 'Test_pum_completeitemalign_01', {})
+  call term_sendkeys(buf, "\<C-E>\<Esc>")
+
+  " T2
+  call term_sendkeys(buf, ":T2\<CR>S\<C-X>\<C-O>")
+  call VerifyScreenDump(buf, 'Test_pum_completeitemalign_02', {})
+  call term_sendkeys(buf, "\<C-E>\<Esc>")
+
+  " T3
+  call term_sendkeys(buf, ":T3\<CR>S\<C-X>\<C-O>")
+  call VerifyScreenDump(buf, 'Test_pum_completeitemalign_03', {})
+  call term_sendkeys(buf, "\<C-E>\<Esc>")
+
+  " T4
+  call term_sendkeys(buf, ":T4\<CR>S\<C-X>\<C-O>")
+  call VerifyScreenDump(buf, 'Test_pum_completeitemalign_04', {})
+  call term_sendkeys(buf, "\<C-E>\<Esc>")
+
+  " T5
+  call term_sendkeys(buf, ":T5\<CR>S\<C-X>\<C-O>")
+  call VerifyScreenDump(buf, 'Test_pum_completeitemalign_05', {})
+  call term_sendkeys(buf, "\<C-E>\<Esc>")
+
+  " T6
+  call term_sendkeys(buf, ":T6\<CR>S\<C-X>\<C-O>")
+  call VerifyScreenDump(buf, 'Test_pum_completeitemalign_06', {})
+  call term_sendkeys(buf, "\<C-E>\<Esc>:T7\<CR>")
+
+  call StopVimInTerminal(buf)
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index f5d85cb67..8cc38ccc6 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    754,
 /**/
     753,
 /**/
diff --git a/src/vim.h b/src/vim.h
index 9c1434cc6..ebca6ae85 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2372,6 +2372,17 @@ typedef enum {
     FCERR_FAILED,      // error while executing the function
 } funcerror_T;
 
+/*
+ * Array indexes used for cp_text[].
+ */
+typedef enum {
+    CPT_ABBR,          // "abbr"
+    CPT_KIND,          // "kind"
+    CPT_MENU,          // "menu"
+    CPT_INFO,          // "info"
+    CPT_COUNT,         // Number of entries
+} cpitem_T;
+
 /*
  * Type for the callback function that is invoked after an option value is
  * changed to validate and apply the new value.

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1svhrr-004rIo-BC%40256bit.org.

Raspunde prin e-mail lui