vim-patch:ffc89e4 runtime(doc): clarify complete_match() and 'isexpand' option

clarify complete_match() documentation to better explain its backward
search behavior, argument handling, and return value format and add an
example of isexpand

closes: https://github.com/vim/vim/pull/17212

ffc89e47d0
This commit is contained in:
glepnir
2025-04-28 14:03:52 +08:00
parent 31e31273bc
commit e7e665b489
13 changed files with 115 additions and 122 deletions

View File

@@ -558,7 +558,7 @@ struct file_buffer {
char *b_p_fo; ///< 'formatoptions'
char *b_p_flp; ///< 'formatlistpat'
int b_p_inf; ///< 'infercase'
char *b_p_ise; ///< 'isexpand'
char *b_p_ise; ///< 'isexpand' local value
char *b_p_isk; ///< 'iskeyword'
char *b_p_def; ///< 'define' local value
char *b_p_inc; ///< 'include'

View File

@@ -1481,8 +1481,11 @@ M.funcs = {
args = { 0, 2 },
base = 0,
desc = [=[
Returns a List of matches found according to the 'isexpand'
option. Each match is represented as a List containing
Searches backward from the given position and returns a List
of matches according to the 'isexpand' option. When no
arguments are provided, uses the current cursor position.
Each match is represented as a List containing
[startcol, trigger_text] where:
- startcol: column position where completion should start,
or -1 if no trigger position is found. For multi-character
@@ -1494,39 +1497,34 @@ M.funcs = {
When 'isexpand' is empty, uses the 'iskeyword' pattern
"\k\+$" to find the start of the current keyword.
When no arguments are provided, uses the current cursor
position.
Examples: >
Examples: >vim
set isexpand=.,->,/,/*,abc
func CustomComplete()
let res = complete_match()
if res->len() == 0 | return | endif
let [col, trigger] = res[0]
let items = []
if trigger == '/*'
let items = ['/** */']
elseif trigger == '/'
let items = ['/*! */', '// TODO:', '// fixme:']
elseif trigger == '.'
let items = ['length()']
elseif trigger =~ '^\->'
let items = ['map()', 'reduce()']
elseif trigger =~ '^\abc'
let items = ['def', 'ghk']
endif
if items->len() > 0
let startcol = trigger =~ '^/' ? col : col + len(trigger)
call complete(startcol, items)
endif
let res = complete_match()
if res->len() == 0 | return | endif
let [col, trigger] = res[0]
let items = []
if trigger == '/*'
let items = ['/** */']
elseif trigger == '/'
let items = ['/*! */', '// TODO:', '// fixme:']
elseif trigger == '.'
let items = ['length()']
elseif trigger =~ '^\->'
let items = ['map()', 'reduce()']
elseif trigger =~ '^\abc'
let items = ['def', 'ghk']
endif
if items->len() > 0
let startcol = trigger =~ '^/' ? col : col + len(trigger)
call complete(startcol, items)
endif
endfunc
inoremap <Tab> <Cmd>call CustomComplete()<CR>
<
Return type: list<list<any>>
<
]=],
name = 'complete_match',
params = { { 'lnum', 'integer?' }, { 'col', 'integer?' } },
params = { { 'lnum', 'integer' }, { 'col', 'integer' } },
returns = 'table',
signature = 'complete_match([{lnum}, {col}])',
},

View File

@@ -3082,24 +3082,18 @@ void f_complete_check(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
/// Add match item to the return list.
/// Returns FAIL if out of memory, OK otherwise.
static int add_match_to_list(typval_T *rettv, char *str, int pos)
static void add_match_to_list(typval_T *rettv, char *str, int pos)
{
list_T *match = tv_list_alloc(kListLenMayKnow);
if (match == NULL) {
return FAIL;
}
list_T *match = tv_list_alloc(2);
tv_list_append_number(match, pos + 1);
tv_list_append_string(match, str, -1);
tv_list_append_list(rettv->vval.v_list, match);
return OK;
}
/// "complete_match()" function
void f_complete_match(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_list_alloc_ret(rettv, kListLenUnknown);
tv_list_alloc_ret(rettv, kListLenUnknown);
char *ise = curbuf->b_p_ise[0] != NUL ? curbuf->b_p_ise : p_ise;
@@ -3131,9 +3125,6 @@ void f_complete_match(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
char *before_cursor = xstrnsave(line, (size_t)col);
if (before_cursor == NULL) {
return;
}
if (ise == NULL || *ise == NUL) {
regmatch_T regmatch;
@@ -3141,19 +3132,9 @@ void f_complete_match(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (regmatch.regprog != NULL) {
if (vim_regexec_nl(&regmatch, before_cursor, (colnr_T)0)) {
char *trig = xstrnsave(regmatch.startp[0], (size_t)(regmatch.endp[0] - regmatch.startp[0]));
if (trig == NULL) {
xfree(before_cursor);
return;
}
int bytepos = (int)(regmatch.startp[0] - before_cursor);
int ret = add_match_to_list(rettv, trig, bytepos);
add_match_to_list(rettv, trig, bytepos);
xfree(trig);
if (ret == FAIL) {
xfree(before_cursor);
vim_regfree(regmatch.regprog);
return;
}
}
vim_regfree(regmatch.regprog);
}
@@ -3166,10 +3147,7 @@ void f_complete_match(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (len > 0 && (int)len <= col) {
if (strncmp(cur_end - len, part, len) == 0) {
int bytepos = col - (int)len;
if (add_match_to_list(rettv, part, bytepos) == FAIL) {
xfree(before_cursor);
return;
}
add_match_to_list(rettv, part, bytepos);
}
}
}

View File

@@ -4460,10 +4460,10 @@ void *get_varp_scope_from(vimoption_T *p, int opt_flags, buf_T *buf, win_T *win)
return &(buf->b_p_def);
case kOptInclude:
return &(buf->b_p_inc);
case kOptIsexpand:
return &(buf->b_p_ise);
case kOptCompleteopt:
return &(buf->b_p_cot);
case kOptIsexpand:
return &(buf->b_p_ise);
case kOptDictionary:
return &(buf->b_p_dict);
case kOptThesaurus:
@@ -4547,10 +4547,10 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
return *buf->b_p_def != NUL ? &(buf->b_p_def) : p->var;
case kOptInclude:
return *buf->b_p_inc != NUL ? &(buf->b_p_inc) : p->var;
case kOptIsexpand:
return *buf->b_p_ise != NUL ? &(buf->b_p_ise) : p->var;
case kOptCompleteopt:
return *buf->b_p_cot != NUL ? &(buf->b_p_cot) : p->var;
case kOptIsexpand:
return *buf->b_p_ise != NUL ? &(buf->b_p_ise) : p->var;
case kOptDictionary:
return *buf->b_p_dict != NUL ? &(buf->b_p_dict) : p->var;
case kOptThesaurus:
@@ -5242,6 +5242,7 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_cot_flags = 0;
buf->b_p_dict = empty_string_option;
buf->b_p_tsr = empty_string_option;
buf->b_p_ise = empty_string_option;
buf->b_p_tsrfu = empty_string_option;
buf->b_p_qe = xstrdup(p_qe);
COPY_OPT_SCTX(buf, kBufOptQuoteescape);

View File

@@ -374,9 +374,9 @@ EXTERN int p_is; ///< 'incsearch'
EXTERN char *p_inde; ///< 'indentexpr'
EXTERN char *p_indk; ///< 'indentkeys'
EXTERN char *p_icm; ///< 'inccommand'
EXTERN char *p_ise; ///< 'isexpand'
EXTERN char *p_isf; ///< 'isfname'
EXTERN char *p_isi; ///< 'isident'
EXTERN char *p_ise; ///< 'isexpand'
EXTERN char *p_isk; ///< 'iskeyword'
EXTERN char *p_isp; ///< 'isprint'
EXTERN int p_js; ///< 'joinspaces'

View File

@@ -4632,7 +4632,7 @@ local options = {
abbreviation = 'ise',
cb = 'did_set_isexpand',
defaults = '',
deny_duplicates = false,
deny_duplicates = true,
desc = [=[
Defines characters and patterns for completion in insert mode. Used by
the |complete_match()| function to determine the starting position for
@@ -4643,6 +4643,10 @@ local options = {
Note: Use "\\," to add a literal comma as trigger character, see
|option-backslash|.
Examples: >vim
set isexpand=.,->,/*,\\,
<
]=],
full_name = 'isexpand',
list = 'onecomma',