diff options
author | glepnir <glephunter@gmail.com> | 2024-10-03 06:45:01 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-03 06:45:01 +0800 |
commit | 6a2f8958e832aebc20cf42d8ade4cb58fe33df9e (patch) | |
tree | e2d5750f75a126a32cc7128ab9c5d1e869b5437a /src | |
parent | d3b4772ddcd4c890dc5bc38e1f1b36a08aed0c04 (diff) | |
download | rneovim-6a2f8958e832aebc20cf42d8ade4cb58fe33df9e.tar.gz rneovim-6a2f8958e832aebc20cf42d8ade4cb58fe33df9e.tar.bz2 rneovim-6a2f8958e832aebc20cf42d8ade4cb58fe33df9e.zip |
vim-patch:9.1.0754: fixed order of items in insert-mode completion menu (#30619)
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: vim/vim#14006
closes: vim/vim#15760
https://github.com/vim/vim/commit/6a89c94a9eeee53481ced1a1260a177bffde4c0f
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/insexpand.c | 7 | ||||
-rw-r--r-- | src/nvim/insexpand.h | 9 | ||||
-rw-r--r-- | src/nvim/option_vars.h | 2 | ||||
-rw-r--r-- | src/nvim/options.lua | 20 | ||||
-rw-r--r-- | src/nvim/optionstr.c | 45 | ||||
-rw-r--r-- | src/nvim/popupmenu.c | 78 |
6 files changed, 122 insertions, 39 deletions
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index c17bd27daa..84dd55fa78 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -151,13 +151,6 @@ static char *ctrl_x_mode_names[] = { "cmdline", }; -// 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. typedef struct compl_S compl_T; struct compl_S { diff --git a/src/nvim/insexpand.h b/src/nvim/insexpand.h index b880e64ea4..8c05590b79 100644 --- a/src/nvim/insexpand.h +++ b/src/nvim/insexpand.h @@ -8,3 +8,12 @@ #ifdef INCLUDE_GENERATED_DECLARATIONS # include "insexpand.h.generated.h" #endif + +/// 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; diff --git a/src/nvim/option_vars.h b/src/nvim/option_vars.h index b9c61160e1..8be437e477 100644 --- a/src/nvim/option_vars.h +++ b/src/nvim/option_vars.h @@ -429,6 +429,8 @@ EXTERN char *p_cms; ///< 'commentstring' EXTERN char *p_cpt; ///< 'complete' EXTERN OptInt p_columns; ///< 'columns' EXTERN int p_confirm; ///< 'confirm' +EXTERN char *p_cia; ///< 'completeitemalign' +EXTERN unsigned cia_flags; ///< order flags of 'completeitemalign' EXTERN char *p_cot; ///< 'completeopt' EXTERN unsigned cot_flags; ///< flags from 'completeopt' // Keep in sync with p_cot_values in optionstr.c diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 825bde5c85..0da954d052 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1427,6 +1427,26 @@ return { varname = 'p_cfu', }, { + abbreviation = 'cia', + cb = 'did_set_completeitemalign', + defaults = { if_true = 'abbr,kind,menu' }, + deny_duplicates = true, + desc = [=[ + 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. + ]=], + full_name = 'completeitemalign', + list = 'onecomma', + scope = { 'global' }, + short_desc = N_('Insert mode completion item align order'), + type = 'string', + varname = 'p_cia', + }, + { abbreviation = 'cot', cb = 'did_set_completeopt', defaults = { if_true = 'menu,preview' }, diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index a9651084b7..c8f19d7ccf 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -995,6 +995,51 @@ int expand_set_complete(optexpand_T *args, int *numMatches, char ***matches) matches); } +/// The 'completeitemalign' option is changed. +const char *did_set_completeitemalign(optset_T *args) +{ + char *p = p_cia; + unsigned new_cia_flags = 0; + bool seen[3] = { false, false, false }; + int count = 0; + char buf[10]; + while (*p) { + copy_option_part(&p, buf, sizeof(buf), ","); + if (count >= 3) { + return e_invarg; + } + if (strequal(buf, "abbr")) { + if (seen[CPT_ABBR]) { + return e_invarg; + } + new_cia_flags = new_cia_flags * 10 + CPT_ABBR; + seen[CPT_ABBR] = true; + count++; + } else if (strequal(buf, "kind")) { + if (seen[CPT_KIND]) { + return e_invarg; + } + new_cia_flags = new_cia_flags * 10 + CPT_KIND; + seen[CPT_KIND] = true; + count++; + } else if (strequal(buf, "menu")) { + if (seen[CPT_MENU]) { + return e_invarg; + } + new_cia_flags = new_cia_flags * 10 + CPT_MENU; + seen[CPT_MENU] = true; + count++; + } else { + return e_invarg; + } + } + if (new_cia_flags == 0 || count != 3) { + return e_invarg; + } + cia_flags = new_cia_flags; + return NULL; +} + /// The 'completeopt' option is changed. const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) { diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index f836a1bf17..b7892da867 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -525,6 +525,27 @@ static void pum_grid_puts_with_attrs(int col, int cells, const char *text, int t } } +static inline void pum_align_order(int *order) +{ + bool 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 *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". void pum_redraw(void) { @@ -621,34 +642,27 @@ void pum_redraw(void) } // 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 int grid_col = col_off; int totwidth = 0; - - for (int round = 0; round < 3; round++) { - hlf = hlfs[round]; + int order[3]; + int items_width_array[3] = { pum_base_width, pum_kind_width, pum_extra_width }; + pum_align_order(order); + int basic_width = items_width_array[order[0]]; // first item width + bool last_isabbr = order[2] == CPT_ABBR; + for (int j = 0; j < 3; j++) { + int item_type = order[j]; + hlf = hlfs[item_type]; attr = win_hl_attr(curwin, (int)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); } int width = 0; char *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)) { if (s == NULL) { @@ -737,31 +751,31 @@ void pum_redraw(void) } } - 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; } + bool next_isempty = false; + 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; } if (pum_rl) { - grid_line_fill(col_off - pum_base_width - n + 1, grid_col + 1, schar_from_ascii(' '), attr); - grid_col = col_off - pum_base_width - n; + grid_line_fill(col_off - basic_width - n + 1, grid_col + 1, schar_from_ascii(' '), attr); + grid_col = col_off - basic_width - n; } else { - grid_line_fill(grid_col, col_off + pum_base_width + n, schar_from_ascii(' '), attr); - grid_col = col_off + pum_base_width + n; + grid_line_fill(grid_col, col_off + basic_width + n, schar_from_ascii(' '), attr); + grid_col = col_off + basic_width + n; } - totwidth = pum_base_width + n; + totwidth = basic_width + n; } if (pum_rl) { |