mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
fix(lua): find length of completion prefix earlier (#29384)
Do the expansion right after setting the expand context, so that the length of the completion prefix can be set, but don't do that directly in set_one_cmd_context(), as that's also called by getcmdcompltype().
This commit is contained in:
parent
9d200c78a5
commit
948f2beed4
@ -240,6 +240,9 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
||||
|
||||
if (xp->xp_numfiles == -1) {
|
||||
set_expand_context(xp);
|
||||
if (xp->xp_context == EXPAND_LUA) {
|
||||
nlua_expand_pat(xp, xp->xp_pattern);
|
||||
}
|
||||
cmd_showtail = expand_showtail(xp);
|
||||
}
|
||||
|
||||
@ -287,11 +290,6 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
|
||||
use_options, type);
|
||||
xfree(p1);
|
||||
|
||||
// xp->xp_pattern might have been modified by ExpandOne (for example,
|
||||
// in lua completion), so recompute the pattern index and length
|
||||
i = (int)(xp->xp_pattern - ccline->cmdbuff);
|
||||
xp->xp_pattern_len = (size_t)ccline->cmdpos - (size_t)i;
|
||||
|
||||
// Longest match: make sure it is not shorter, happens with :help.
|
||||
if (p2 != NULL && type == WILD_LONGEST) {
|
||||
int j;
|
||||
@ -1061,6 +1059,9 @@ int showmatches(expand_T *xp, bool wildmenu)
|
||||
|
||||
if (xp->xp_numfiles == -1) {
|
||||
set_expand_context(xp);
|
||||
if (xp->xp_context == EXPAND_LUA) {
|
||||
nlua_expand_pat(xp, xp->xp_pattern);
|
||||
}
|
||||
int i = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
|
||||
&numMatches, &matches);
|
||||
showtail = expand_showtail(xp);
|
||||
@ -2797,8 +2798,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
|
||||
}
|
||||
|
||||
if (xp->xp_context == EXPAND_LUA) {
|
||||
ILOG("PAT %s", pat);
|
||||
return nlua_expand_pat(xp, pat, numMatches, matches);
|
||||
return nlua_expand_get_matches(numMatches, matches);
|
||||
}
|
||||
|
||||
if (!fuzzy) {
|
||||
@ -3610,7 +3610,10 @@ void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
}
|
||||
|
||||
theend:
|
||||
;
|
||||
if (xpc.xp_context == EXPAND_LUA) {
|
||||
nlua_expand_pat(&xpc, xpc.xp_pattern);
|
||||
xpc.xp_pattern_len = strlen(xpc.xp_pattern);
|
||||
}
|
||||
char *pat;
|
||||
if (cmdline_fuzzy_completion_supported(&xpc)) {
|
||||
// when fuzzy matching, don't modify the search string
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "nvim/indent_c.h"
|
||||
#include "nvim/insexpand.h"
|
||||
#include "nvim/keycodes.h"
|
||||
#include "nvim/lua/executor.h"
|
||||
#include "nvim/macros_defs.h"
|
||||
#include "nvim/mark_defs.h"
|
||||
#include "nvim/mbyte.h"
|
||||
@ -4144,6 +4145,9 @@ static int get_cmdline_compl_info(char *line, colnr_T curs_col)
|
||||
compl_pattern = xstrnsave(line, (size_t)curs_col);
|
||||
compl_patternlen = (size_t)curs_col;
|
||||
set_cmd_context(&compl_xp, compl_pattern, (int)compl_patternlen, curs_col, false);
|
||||
if (compl_xp.xp_context == EXPAND_LUA) {
|
||||
nlua_expand_pat(&compl_xp, compl_xp.xp_pattern);
|
||||
}
|
||||
if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
|
||||
|| compl_xp.xp_context == EXPAND_NOTHING) {
|
||||
// No completion possible, use an empty pattern to get a
|
||||
|
@ -1924,10 +1924,14 @@ static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
|
||||
lua_setfield(lstate, -2, "_ts_get_minimum_language_version");
|
||||
}
|
||||
|
||||
int nlua_expand_pat(expand_T *xp, char *pat, int *num_results, char ***results)
|
||||
static garray_T expand_result_array = GA_EMPTY_INIT_VALUE;
|
||||
|
||||
/// Finds matches for Lua cmdline completion and advances xp->xp_pattern after prefix.
|
||||
/// This should be called before xp->xp_pattern is first used.
|
||||
void nlua_expand_pat(expand_T *xp, const char *pat)
|
||||
{
|
||||
lua_State *const lstate = global_lstate;
|
||||
int ret = OK;
|
||||
int status = OK;
|
||||
|
||||
// [ vim ]
|
||||
lua_getglobal(lstate, "vim");
|
||||
@ -1942,54 +1946,54 @@ int nlua_expand_pat(expand_T *xp, char *pat, int *num_results, char ***results)
|
||||
if (nlua_pcall(lstate, 1, 2) != 0) {
|
||||
nlua_error(lstate,
|
||||
_("Error executing vim._expand_pat: %.*s"));
|
||||
return FAIL;
|
||||
return;
|
||||
}
|
||||
|
||||
Error err = ERROR_INIT;
|
||||
|
||||
*num_results = 0;
|
||||
*results = NULL;
|
||||
|
||||
Arena arena = ARENA_EMPTY;
|
||||
int prefix_len = (int)nlua_pop_Integer(lstate, &arena, &err);
|
||||
if (ERROR_SET(&err)) {
|
||||
ret = FAIL;
|
||||
status = FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
Array completions = nlua_pop_Array(lstate, &arena, &err);
|
||||
if (ERROR_SET(&err)) {
|
||||
ret = FAIL;
|
||||
status = FAIL;
|
||||
goto cleanup_array;
|
||||
}
|
||||
|
||||
garray_T result_array;
|
||||
ga_init(&result_array, (int)sizeof(char *), 80);
|
||||
ga_clear(&expand_result_array);
|
||||
ga_init(&expand_result_array, (int)sizeof(char *), 80);
|
||||
for (size_t i = 0; i < completions.size; i++) {
|
||||
Object v = completions.items[i];
|
||||
|
||||
if (v.type != kObjectTypeString) {
|
||||
ret = FAIL;
|
||||
status = FAIL;
|
||||
goto cleanup_array;
|
||||
}
|
||||
|
||||
GA_APPEND(char *, &result_array, string_to_cstr(v.data.string));
|
||||
GA_APPEND(char *, &expand_result_array, string_to_cstr(v.data.string));
|
||||
}
|
||||
|
||||
xp->xp_pattern += prefix_len;
|
||||
*results = result_array.ga_data;
|
||||
*num_results = result_array.ga_len;
|
||||
|
||||
cleanup_array:
|
||||
arena_mem_free(arena_finish(&arena));
|
||||
|
||||
cleanup:
|
||||
|
||||
if (ret == FAIL) {
|
||||
ga_clear(&result_array);
|
||||
if (status == FAIL) {
|
||||
ga_clear(&expand_result_array);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
int nlua_expand_get_matches(int *num_results, char ***results)
|
||||
{
|
||||
*results = expand_result_array.ga_data;
|
||||
*num_results = expand_result_array.ga_len;
|
||||
expand_result_array = (garray_T)GA_EMPTY_INIT_VALUE;
|
||||
return *num_results > 0;
|
||||
}
|
||||
|
||||
static int nlua_is_thread(lua_State *lstate)
|
||||
|
@ -812,11 +812,63 @@ describe('completion', function()
|
||||
}
|
||||
end)
|
||||
|
||||
it('prefix is not included in completion for cmdline mode', function()
|
||||
feed(':lua math.a<Tab>')
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{100:abs}{3: acos asin atan atan2 }|
|
||||
:lua math.abs^ |
|
||||
]])
|
||||
feed('<Tab>')
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{3:abs }{100:acos}{3: asin atan atan2 }|
|
||||
:lua math.acos^ |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('prefix is not included in completion for i_CTRL-X_CTRL-V #19623', function()
|
||||
feed('ilua math.a<C-X><C-V>')
|
||||
screen:expect([[
|
||||
lua math.abs^ |
|
||||
{1:~ }{12: abs }{1: }|
|
||||
{1:~ }{4: acos }{1: }|
|
||||
{1:~ }{4: asin }{1: }|
|
||||
{1:~ }{4: atan }{1: }|
|
||||
{1:~ }{4: atan2 }{1: }|
|
||||
{1:~ }|
|
||||
{5:-- Command-line completion (^V^N^P) }{6:match 1 of 5} |
|
||||
]])
|
||||
feed('<C-V>')
|
||||
screen:expect([[
|
||||
lua math.acos^ |
|
||||
{1:~ }{4: abs }{1: }|
|
||||
{1:~ }{12: acos }{1: }|
|
||||
{1:~ }{4: asin }{1: }|
|
||||
{1:~ }{4: atan }{1: }|
|
||||
{1:~ }{4: atan2 }{1: }|
|
||||
{1:~ }|
|
||||
{5:-- Command-line completion (^V^N^P) }{6:match 2 of 5} |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('provides completion from `getcompletion()`', function()
|
||||
eq({ 'vim' }, fn.getcompletion('vi', 'lua'))
|
||||
eq({ 'api' }, fn.getcompletion('vim.ap', 'lua'))
|
||||
eq({ 'tbl_filter' }, fn.getcompletion('vim.tbl_fil', 'lua'))
|
||||
eq({ 'vim' }, fn.getcompletion('print(vi', 'lua'))
|
||||
eq({ 'abs', 'acos', 'asin', 'atan', 'atan2' }, fn.getcompletion('math.a', 'lua'))
|
||||
eq({ 'abs', 'acos', 'asin', 'atan', 'atan2' }, fn.getcompletion('lua math.a', 'cmdline'))
|
||||
-- fuzzy completion is not supported, so the result should be the same
|
||||
command('set wildoptions+=fuzzy')
|
||||
eq({ 'vim' }, fn.getcompletion('vi', 'lua'))
|
||||
|
Loading…
Reference in New Issue
Block a user