diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-03-21 07:50:12 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-21 07:50:12 +0800 |
commit | c1c6c1ee12fa601194a410f78ecde11a9982a793 (patch) | |
tree | b4d9bd7d18728b191debbb4f519ae8b29eeb39dd /src | |
parent | cfc9fcc91f780022e5e9397626ac6ab5cde91d62 (diff) | |
download | rneovim-c1c6c1ee12fa601194a410f78ecde11a9982a793.tar.gz rneovim-c1c6c1ee12fa601194a410f78ecde11a9982a793.tar.bz2 rneovim-c1c6c1ee12fa601194a410f78ecde11a9982a793.zip |
vim-patch:9.1.0190: complete_info() returns wrong order of items (#27955)
Problem: complete_info() returns wrong order of items
(after v9.0.2018)
Solution: Revert Patch v9.0.2018
(Girish Palya)
bug fix: complete_info() gives wrong results
1) complete_info() reverses list of items during <c-p>
2) 'selected' item index is wrong during <c-p>
3) number of items returnd can be wrong
Solution:
- Decouple 'cp_number' from 'selected' index since they need not be
correlated
- Do not iterate the list backwards
- Add targeted tests
Regression introduced by https://github.com/vim/vim/commit/69fb5afb3bc9da24c2fb0eafb0027ba9c6502fc2
Following are unnecessary commits to patch problems from above:
https://github.com/vim/vim/commit/fef66301665027f1801a18d796f74584666f41ef
https://github.com/vim/vim/commit/daef8c74375141974d61b85199b383017644978c
All the tests from above commits are retained though.
fixes: vim/vim#14204
closes: vim/vim#14241
https://github.com/vim/vim/commit/8950bf7f8b85c1287d4e696965d88091fcc60594
Remove EMPTY_IF_NULL() as it has been unnecessary since #12673.
Co-authored-by: Girish Palya <girishji@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/insexpand.c | 139 |
1 files changed, 51 insertions, 88 deletions
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 526a17cfd4..46936ea2bd 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -1104,11 +1104,11 @@ static dict_T *ins_compl_dict_alloc(compl_T *match) { // { word, abbr, menu, kind, info } dict_T *dict = tv_dict_alloc_lock(VAR_FIXED); - tv_dict_add_str(dict, S_LEN("word"), EMPTY_IF_NULL(match->cp_str)); - tv_dict_add_str(dict, S_LEN("abbr"), EMPTY_IF_NULL(match->cp_text[CPT_ABBR])); - tv_dict_add_str(dict, S_LEN("menu"), EMPTY_IF_NULL(match->cp_text[CPT_MENU])); - tv_dict_add_str(dict, S_LEN("kind"), EMPTY_IF_NULL(match->cp_text[CPT_KIND])); - tv_dict_add_str(dict, S_LEN("info"), EMPTY_IF_NULL(match->cp_text[CPT_INFO])); + tv_dict_add_str(dict, S_LEN("word"), match->cp_str); + tv_dict_add_str(dict, S_LEN("abbr"), match->cp_text[CPT_ABBR]); + tv_dict_add_str(dict, S_LEN("menu"), match->cp_text[CPT_MENU]); + tv_dict_add_str(dict, S_LEN("kind"), match->cp_text[CPT_KIND]); + tv_dict_add_str(dict, S_LEN("info"), match->cp_text[CPT_INFO]); if (match->cp_user_data.v_type == VAR_UNKNOWN) { tv_dict_add_str(dict, S_LEN("user_data"), ""); } else { @@ -2730,72 +2730,6 @@ static void ins_compl_update_sequence_numbers(void) } } -static int info_add_completion_info(list_T *li) -{ - if (compl_first_match == NULL) { - return OK; - } - - bool forward = compl_dir_forward(); - compl_T *match = compl_first_match; - // There are four cases to consider here: - // 1) when just going forward through the menu, - // compl_first_match should point to the initial entry with - // number zero and CP_ORIGINAL_TEXT flag set - // 2) when just going backwards, - // compl-first_match should point to the last entry before - // the entry with the CP_ORIGINAL_TEXT flag set - // 3) when first going forwards and then backwards, e.g. - // pressing C-N, C-P, compl_first_match points to the - // last entry before the entry with the CP_ORIGINAL_TEXT - // flag set and next-entry moves opposite through the list - // compared to case 2, so pretend the direction is forward again - // 4) when first going backwards and then forwards, e.g. - // pressing C-P, C-N, compl_first_match points to the - // first entry with the CP_ORIGINAL_TEXT - // flag set and next-entry moves in opposite direction through the list - // compared to case 1, so pretend the direction is backwards again - // - // But only do this when the 'noselect' option is not active! - - if (!compl_no_select) { - if (forward && !match_at_original_text(match)) { - forward = false; - } else if (!forward && match_at_original_text(match)) { - forward = true; - } - } - - // Skip the element with the CP_ORIGINAL_TEXT flag at the beginning, in case of - // forward completion, or at the end, in case of backward completion. - match = (forward || match->cp_prev == NULL - ? match->cp_next - : (compl_no_select && match_at_original_text(match) - ? match->cp_prev - : match->cp_prev->cp_prev)); - - while (match != NULL && !match_at_original_text(match)) { - dict_T *di = tv_dict_alloc(); - - tv_list_append_dict(li, di); - tv_dict_add_str(di, S_LEN("word"), EMPTY_IF_NULL(match->cp_str)); - tv_dict_add_str(di, S_LEN("abbr"), EMPTY_IF_NULL(match->cp_text[CPT_ABBR])); - tv_dict_add_str(di, S_LEN("menu"), EMPTY_IF_NULL(match->cp_text[CPT_MENU])); - tv_dict_add_str(di, S_LEN("kind"), EMPTY_IF_NULL(match->cp_text[CPT_KIND])); - tv_dict_add_str(di, S_LEN("info"), EMPTY_IF_NULL(match->cp_text[CPT_INFO])); - if (match->cp_user_data.v_type == VAR_UNKNOWN) { - // Add an empty string for backwards compatibility - tv_dict_add_str(di, S_LEN("user_data"), ""); - } else { - tv_dict_add_tv(di, S_LEN("user_data"), &match->cp_user_data); - } - - match = forward ? match->cp_next : match->cp_prev; - } - - return OK; -} - /// Get complete information static void get_complete_info(list_T *what_list, dict_T *retdict) { @@ -2839,25 +2773,54 @@ static void get_complete_info(list_T *what_list, dict_T *retdict) ret = tv_dict_add_nr(retdict, S_LEN("pum_visible"), pum_visible()); } - if (ret == OK && (what_flag & CI_WHAT_ITEMS)) { - list_T *li = tv_list_alloc(get_compl_len()); - ret = tv_dict_add_list(retdict, S_LEN("items"), li); - if (ret == OK) { - ret = info_add_completion_info(li); + if (ret == OK && (what_flag & CI_WHAT_ITEMS || what_flag & CI_WHAT_SELECTED)) { + list_T *li; + int selected_idx = -1; + if (what_flag & CI_WHAT_ITEMS) { + li = tv_list_alloc(kListLenMayKnow); + ret = tv_dict_add_list(retdict, S_LEN("items"), li); } - } - - if (ret == OK && (what_flag & CI_WHAT_SELECTED)) { - if (compl_curr_match != NULL && compl_curr_match->cp_number == -1) { - ins_compl_update_sequence_numbers(); + if (ret == OK && what_flag & CI_WHAT_SELECTED) { + if (compl_curr_match != NULL && compl_curr_match->cp_number == -1) { + ins_compl_update_sequence_numbers(); + } } - ret = tv_dict_add_nr(retdict, S_LEN("selected"), - (compl_curr_match != NULL) - ? compl_curr_match->cp_number - 1 : -1); - win_T *wp = win_float_find_preview(); - if (wp != NULL) { - tv_dict_add_nr(retdict, S_LEN("preview_winid"), wp->handle); - tv_dict_add_nr(retdict, S_LEN("preview_bufnr"), wp->w_buffer->handle); + if (ret == OK && compl_first_match != NULL) { + int list_idx = 0; + compl_T *match = compl_first_match; + do { + if (!match_at_original_text(match)) { + if (what_flag & CI_WHAT_ITEMS) { + dict_T *di = tv_dict_alloc(); + tv_list_append_dict(li, di); + tv_dict_add_str(di, S_LEN("word"), match->cp_str); + tv_dict_add_str(di, S_LEN("abbr"), match->cp_text[CPT_ABBR]); + tv_dict_add_str(di, S_LEN("menu"), match->cp_text[CPT_MENU]); + tv_dict_add_str(di, S_LEN("kind"), match->cp_text[CPT_KIND]); + tv_dict_add_str(di, S_LEN("info"), match->cp_text[CPT_INFO]); + if (match->cp_user_data.v_type == VAR_UNKNOWN) { + // Add an empty string for backwards compatibility + tv_dict_add_str(di, S_LEN("user_data"), ""); + } else { + tv_dict_add_tv(di, S_LEN("user_data"), &match->cp_user_data); + } + } + if (compl_curr_match != NULL + && compl_curr_match->cp_number == match->cp_number) { + selected_idx = list_idx; + } + list_idx += 1; + } + match = match->cp_next; + } while (match != NULL && !is_first_match(match)); + } + if (ret == OK && (what_flag & CI_WHAT_SELECTED)) { + ret = tv_dict_add_nr(retdict, S_LEN("selected"), selected_idx); + win_T *wp = win_float_find_preview(); + if (wp != NULL) { + tv_dict_add_nr(retdict, S_LEN("preview_winid"), wp->handle); + tv_dict_add_nr(retdict, S_LEN("preview_bufnr"), wp->w_buffer->handle); + } } } |