mirror of
https://github.com/neovim/neovim.git
synced 2025-09-14 15:28:17 +00:00
vim-patch:8.2.1907: complete_info().selected may be wrong
Problem: Complete_info().selected may be wrong.
Solution: Update cp_number if it was never set. (issue vim/vim#6945)
f9d51354de
Misc changes:
For variables and function parameters that use "Direction" enum values,
update their type from from "int" to "Direction".
It is hard to review function parameters that must accept
"Direction" enum values only.
This commit is contained in:
118
src/nvim/edit.c
118
src/nvim/edit.c
@@ -196,8 +196,8 @@ static int ctrl_x_mode = CTRL_X_NORMAL;
|
|||||||
|
|
||||||
static int compl_matches = 0;
|
static int compl_matches = 0;
|
||||||
static char_u *compl_pattern = NULL;
|
static char_u *compl_pattern = NULL;
|
||||||
static int compl_direction = FORWARD;
|
static Direction compl_direction = FORWARD;
|
||||||
static int compl_shows_dir = FORWARD;
|
static Direction compl_shows_dir = FORWARD;
|
||||||
static int compl_pending = 0; // > 1 for postponed CTRL-N
|
static int compl_pending = 0; // > 1 for postponed CTRL-N
|
||||||
static pos_T compl_startpos;
|
static pos_T compl_startpos;
|
||||||
static colnr_T compl_col = 0; /* column where the text starts
|
static colnr_T compl_col = 0; /* column where the text starts
|
||||||
@@ -2156,7 +2156,7 @@ static bool ins_compl_accept_char(int c)
|
|||||||
///
|
///
|
||||||
/// @param[in] cont_s_ipos next ^X<> will set initial_pos
|
/// @param[in] cont_s_ipos next ^X<> will set initial_pos
|
||||||
int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname,
|
int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname,
|
||||||
int dir, bool cont_s_ipos)
|
Direction dir, bool cont_s_ipos)
|
||||||
FUNC_ATTR_NONNULL_ARG(1)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
char_u *str = str_arg;
|
char_u *str = str_arg;
|
||||||
@@ -2308,7 +2308,7 @@ static int ins_compl_add(char_u *const str, int len,
|
|||||||
FUNC_ATTR_NONNULL_ARG(1)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
compl_T *match;
|
compl_T *match;
|
||||||
int dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
|
const Direction dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
|
||||||
int flags = flags_arg;
|
int flags = flags_arg;
|
||||||
|
|
||||||
os_breakcheck();
|
os_breakcheck();
|
||||||
@@ -2511,7 +2511,7 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase)
|
|||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
int add_r = OK;
|
int add_r = OK;
|
||||||
int dir = compl_direction;
|
Direction dir = compl_direction;
|
||||||
|
|
||||||
for (int i = 0; i < num_matches && add_r != FAIL; i++) {
|
for (int i = 0; i < num_matches && add_r != FAIL; i++) {
|
||||||
if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, false, NULL, dir,
|
if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, false, NULL, dir,
|
||||||
@@ -2864,7 +2864,7 @@ ins_compl_dictionaries (
|
|||||||
char_u **files;
|
char_u **files;
|
||||||
int count;
|
int count;
|
||||||
int save_p_scs;
|
int save_p_scs;
|
||||||
int dir = compl_direction;
|
Direction dir = compl_direction;
|
||||||
|
|
||||||
if (*dict == NUL) {
|
if (*dict == NUL) {
|
||||||
/* When 'dictionary' is empty and spell checking is enabled use
|
/* When 'dictionary' is empty and spell checking is enabled use
|
||||||
@@ -2945,7 +2945,10 @@ theend:
|
|||||||
xfree(buf);
|
xfree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir)
|
static void ins_compl_files(int count, char_u **files, int thesaurus,
|
||||||
|
int flags, regmatch_T *regmatch, char_u *buf,
|
||||||
|
Direction *dir)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2, 7)
|
||||||
{
|
{
|
||||||
char_u *ptr;
|
char_u *ptr;
|
||||||
int i;
|
int i;
|
||||||
@@ -3137,6 +3140,56 @@ bool ins_compl_active(void)
|
|||||||
return compl_started;
|
return compl_started;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ins_compl_update_sequence_numbers(void)
|
||||||
|
{
|
||||||
|
int number = 0;
|
||||||
|
compl_T *match;
|
||||||
|
|
||||||
|
if (compl_direction == FORWARD) {
|
||||||
|
// search backwards for the first valid (!= -1) number.
|
||||||
|
// This should normally succeed already at the first loop
|
||||||
|
// cycle, so it's fast!
|
||||||
|
for (match = compl_curr_match->cp_prev;
|
||||||
|
match != NULL && match != compl_first_match;
|
||||||
|
match = match->cp_prev) {
|
||||||
|
if (match->cp_number != -1) {
|
||||||
|
number = match->cp_number;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match != NULL) {
|
||||||
|
// go up and assign all numbers which are not assigned yet
|
||||||
|
for (match = match->cp_next;
|
||||||
|
match != NULL && match->cp_number == -1;
|
||||||
|
match = match->cp_next) {
|
||||||
|
match->cp_number = ++number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // BACKWARD
|
||||||
|
assert(compl_direction == BACKWARD);
|
||||||
|
// search forwards (upwards) for the first valid (!= -1)
|
||||||
|
// number. This should normally succeed already at the
|
||||||
|
// first loop cycle, so it's fast!
|
||||||
|
for (match = compl_curr_match->cp_next;
|
||||||
|
match != NULL && match != compl_first_match;
|
||||||
|
match = match->cp_next) {
|
||||||
|
if (match->cp_number != -1) {
|
||||||
|
number = match->cp_number;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match != NULL) {
|
||||||
|
// go down and assign all numbers which are not
|
||||||
|
// assigned yet
|
||||||
|
for (match = match->cp_prev;
|
||||||
|
match && match->cp_number == -1;
|
||||||
|
match = match->cp_prev) {
|
||||||
|
match->cp_number = ++number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get complete information
|
// Get complete information
|
||||||
void get_complete_info(list_T *what_list, dict_T *retdict)
|
void get_complete_info(list_T *what_list, dict_T *retdict)
|
||||||
{
|
{
|
||||||
@@ -3214,6 +3267,9 @@ void get_complete_info(list_T *what_list, dict_T *retdict)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret == OK && (what_flag & CI_WHAT_SELECTED)) {
|
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"),
|
ret = tv_dict_add_nr(retdict, S_LEN("selected"),
|
||||||
(compl_curr_match != NULL)
|
(compl_curr_match != NULL)
|
||||||
? compl_curr_match->cp_number - 1 : -1);
|
? compl_curr_match->cp_number - 1 : -1);
|
||||||
@@ -3865,7 +3921,7 @@ theend:
|
|||||||
*/
|
*/
|
||||||
static void ins_compl_add_list(list_T *const list)
|
static void ins_compl_add_list(list_T *const list)
|
||||||
{
|
{
|
||||||
int dir = compl_direction;
|
Direction dir = compl_direction;
|
||||||
|
|
||||||
// Go through the List with matches and add each of them.
|
// Go through the List with matches and add each of them.
|
||||||
TV_LIST_ITER(list, li, {
|
TV_LIST_ITER(list, li, {
|
||||||
@@ -5242,53 +5298,11 @@ static int ins_complete(int c, bool enable_pum)
|
|||||||
} else if (compl_curr_match->cp_next == compl_curr_match->cp_prev) {
|
} else if (compl_curr_match->cp_next == compl_curr_match->cp_prev) {
|
||||||
edit_submode_extra = (char_u *)_("The only match");
|
edit_submode_extra = (char_u *)_("The only match");
|
||||||
edit_submode_highl = HLF_COUNT;
|
edit_submode_highl = HLF_COUNT;
|
||||||
compl_curr_match->cp_number = 0;
|
compl_curr_match->cp_number = 1;
|
||||||
} else {
|
} else {
|
||||||
// Update completion sequence number when needed.
|
// Update completion sequence number when needed.
|
||||||
if (compl_curr_match->cp_number == -1) {
|
if (compl_curr_match->cp_number == -1) {
|
||||||
int number = 0;
|
ins_compl_update_sequence_numbers();
|
||||||
compl_T *match;
|
|
||||||
|
|
||||||
if (compl_direction == FORWARD) {
|
|
||||||
/* search backwards for the first valid (!= -1) number.
|
|
||||||
* This should normally succeed already at the first loop
|
|
||||||
* cycle, so it's fast! */
|
|
||||||
for (match = compl_curr_match->cp_prev; match != NULL
|
|
||||||
&& match != compl_first_match;
|
|
||||||
match = match->cp_prev)
|
|
||||||
if (match->cp_number != -1) {
|
|
||||||
number = match->cp_number;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (match != NULL)
|
|
||||||
/* go up and assign all numbers which are not assigned
|
|
||||||
* yet */
|
|
||||||
for (match = match->cp_next;
|
|
||||||
match != NULL && match->cp_number == -1;
|
|
||||||
match = match->cp_next)
|
|
||||||
match->cp_number = ++number;
|
|
||||||
} else { // BACKWARD
|
|
||||||
// search forwards (upwards) for the first valid (!= -1)
|
|
||||||
// number. This should normally succeed already at the
|
|
||||||
// first loop cycle, so it's fast!
|
|
||||||
for (match = compl_curr_match->cp_next;
|
|
||||||
match != NULL && match != compl_first_match;
|
|
||||||
match = match->cp_next) {
|
|
||||||
if (match->cp_number != -1) {
|
|
||||||
number = match->cp_number;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (match != NULL) {
|
|
||||||
// go down and assign all numbers which are not
|
|
||||||
// assigned yet
|
|
||||||
for (match = match->cp_prev;
|
|
||||||
match && match->cp_number == -1;
|
|
||||||
match = match->cp_prev) {
|
|
||||||
match->cp_number = ++number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The match should always have a sequence number now, this is
|
/* The match should always have a sequence number now, this is
|
||||||
|
@@ -89,7 +89,7 @@ static struct spat spats[2] =
|
|||||||
static int last_idx = 0; /* index in spats[] for RE_LAST */
|
static int last_idx = 0; /* index in spats[] for RE_LAST */
|
||||||
|
|
||||||
static char_u lastc[2] = { NUL, NUL }; // last character searched for
|
static char_u lastc[2] = { NUL, NUL }; // last character searched for
|
||||||
static int lastcdir = FORWARD; // last direction of character search
|
static Direction lastcdir = FORWARD; // last direction of character search
|
||||||
static int last_t_cmd = true; // last search t_cmd
|
static int last_t_cmd = true; // last search t_cmd
|
||||||
static char_u lastc_bytes[MB_MAXBYTES + 1];
|
static char_u lastc_bytes[MB_MAXBYTES + 1];
|
||||||
static int lastc_bytelen = 1; // >1 for multi-byte char
|
static int lastc_bytelen = 1; // >1 for multi-byte char
|
||||||
@@ -437,7 +437,7 @@ void set_last_csearch(int c, char_u *s, int len)
|
|||||||
memset(lastc_bytes, 0, sizeof(lastc_bytes));
|
memset(lastc_bytes, 0, sizeof(lastc_bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_csearch_direction(int cdir)
|
void set_csearch_direction(Direction cdir)
|
||||||
{
|
{
|
||||||
lastcdir = cdir;
|
lastcdir = cdir;
|
||||||
}
|
}
|
||||||
@@ -1430,7 +1430,7 @@ end_do_search:
|
|||||||
* ADDING is set. If p_ic is set then the pattern must be in lowercase.
|
* ADDING is set. If p_ic is set then the pattern must be in lowercase.
|
||||||
* Return OK for success, or FAIL if no line found.
|
* Return OK for success, or FAIL if no line found.
|
||||||
*/
|
*/
|
||||||
int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat)
|
int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
|
||||||
{
|
{
|
||||||
linenr_T start = 0;
|
linenr_T start = 0;
|
||||||
char_u *ptr;
|
char_u *ptr;
|
||||||
@@ -1496,10 +1496,11 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat)
|
|||||||
* Return FAIL or OK.
|
* Return FAIL or OK.
|
||||||
*/
|
*/
|
||||||
int searchc(cmdarg_T *cap, int t_cmd)
|
int searchc(cmdarg_T *cap, int t_cmd)
|
||||||
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
int c = cap->nchar; /* char to search for */
|
int c = cap->nchar; // char to search for
|
||||||
int dir = cap->arg; /* TRUE for searching forward */
|
Direction dir = cap->arg; // TRUE for searching forward
|
||||||
long count = cap->count1; /* repeat count */
|
long count = cap->count1; // repeat count
|
||||||
int col;
|
int col;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int len;
|
int len;
|
||||||
@@ -4462,7 +4463,7 @@ static void search_stat(int dirc, pos_T *pos,
|
|||||||
void
|
void
|
||||||
find_pattern_in_path(
|
find_pattern_in_path(
|
||||||
char_u *ptr, // pointer to search pattern
|
char_u *ptr, // pointer to search pattern
|
||||||
int dir, // direction of expansion
|
Direction dir, // direction of expansion
|
||||||
size_t len, // length of search pattern
|
size_t len, // length of search pattern
|
||||||
bool whole, // match whole words only
|
bool whole, // match whole words only
|
||||||
bool skip_comments, // don't match inside comments
|
bool skip_comments, // don't match inside comments
|
||||||
|
@@ -79,7 +79,6 @@
|
|||||||
/* for offsetof() */
|
/* for offsetof() */
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "nvim/vim.h"
|
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/spell.h"
|
#include "nvim/spell.h"
|
||||||
#include "nvim/buffer.h"
|
#include "nvim/buffer.h"
|
||||||
@@ -6653,7 +6652,7 @@ void
|
|||||||
spell_dump_compl (
|
spell_dump_compl (
|
||||||
char_u *pat, // leading part of the word
|
char_u *pat, // leading part of the word
|
||||||
int ic, // ignore case
|
int ic, // ignore case
|
||||||
int *dir, // direction for adding matches
|
Direction *dir, // direction for adding matches
|
||||||
int dumpflags_arg // DUMPFLAG_*
|
int dumpflags_arg // DUMPFLAG_*
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -6820,7 +6819,9 @@ spell_dump_compl (
|
|||||||
|
|
||||||
// Dumps one word: apply case modifications and append a line to the buffer.
|
// Dumps one word: apply case modifications and append a line to the buffer.
|
||||||
// When "lnum" is zero add insert mode completion.
|
// When "lnum" is zero add insert mode completion.
|
||||||
static void dump_word(slang_T *slang, char_u *word, char_u *pat, int *dir, int dumpflags, int wordflags, linenr_T lnum)
|
static void dump_word(slang_T *slang, char_u *word, char_u *pat,
|
||||||
|
Direction *dir, int dumpflags, int wordflags,
|
||||||
|
linenr_T lnum)
|
||||||
{
|
{
|
||||||
bool keepcap = false;
|
bool keepcap = false;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
@@ -6906,7 +6907,7 @@ dump_prefixes (
|
|||||||
slang_T *slang,
|
slang_T *slang,
|
||||||
char_u *word, // case-folded word
|
char_u *word, // case-folded word
|
||||||
char_u *pat,
|
char_u *pat,
|
||||||
int *dir,
|
Direction *dir,
|
||||||
int dumpflags,
|
int dumpflags,
|
||||||
int flags, // flags with prefix ID
|
int flags, // flags with prefix ID
|
||||||
linenr_T startlnum
|
linenr_T startlnum
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include "nvim/spell_defs.h"
|
#include "nvim/spell_defs.h"
|
||||||
#include "nvim/ex_cmds_defs.h"
|
#include "nvim/ex_cmds_defs.h"
|
||||||
#include "nvim/globals.h"
|
#include "nvim/globals.h"
|
||||||
|
#include "nvim/vim.h"
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "spell.h.generated.h"
|
# include "spell.h.generated.h"
|
||||||
|
@@ -324,7 +324,7 @@ func Test_completefunc_info()
|
|||||||
set completeopt=menuone
|
set completeopt=menuone
|
||||||
set completefunc=CompleteTest
|
set completefunc=CompleteTest
|
||||||
call feedkeys("i\<C-X>\<C-U>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
|
call feedkeys("i\<C-X>\<C-U>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
|
||||||
call assert_equal("matched{'pum_visible': 1, 'mode': 'function', 'selected': -1, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
|
call assert_equal("matched{'pum_visible': 1, 'mode': 'function', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
|
||||||
bwipe!
|
bwipe!
|
||||||
set completeopt&
|
set completeopt&
|
||||||
set completefunc&
|
set completefunc&
|
||||||
|
Reference in New Issue
Block a user