mirror of
https://github.com/neovim/neovim.git
synced 2024-12-23 20:55:18 -07:00
vim-patch:9.0.1956: Custom completion skips orig cmdline if it invokes glob()
Problem: Custom cmdline completion skips original cmdline when pressing
Ctrl-P at first match if completion function invokes glob().
Solution: Move orig_save into struct expand_T.
closes: vim/vim#13216
28a23602e8
This commit is contained in:
parent
f5b43bf1f3
commit
d5c16d1bfe
@ -617,7 +617,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
|
||||
|
||||
/// Get the next or prev cmdline completion match. The index of the match is set
|
||||
/// in "xp->xp_selected"
|
||||
static char *get_next_or_prev_match(int mode, expand_T *xp, char *orig_save)
|
||||
static char *get_next_or_prev_match(int mode, expand_T *xp)
|
||||
{
|
||||
if (xp->xp_numfiles <= 0) {
|
||||
return NULL;
|
||||
@ -677,14 +677,14 @@ static char *get_next_or_prev_match(int mode, expand_T *xp, char *orig_save)
|
||||
|
||||
// When wrapping around, return the original string, set findex to -1.
|
||||
if (findex < 0) {
|
||||
if (orig_save == NULL) {
|
||||
if (xp->xp_orig == NULL) {
|
||||
findex = xp->xp_numfiles - 1;
|
||||
} else {
|
||||
findex = -1;
|
||||
}
|
||||
}
|
||||
if (findex >= xp->xp_numfiles) {
|
||||
if (orig_save == NULL) {
|
||||
if (xp->xp_orig == NULL) {
|
||||
findex = 0;
|
||||
} else {
|
||||
findex = -1;
|
||||
@ -698,7 +698,7 @@ static char *get_next_or_prev_match(int mode, expand_T *xp, char *orig_save)
|
||||
}
|
||||
xp->xp_selected = findex;
|
||||
|
||||
return xstrdup(findex == -1 ? orig_save : xp->xp_files[findex]);
|
||||
return xstrdup(findex == -1 ? xp->xp_orig : xp->xp_files[findex]);
|
||||
}
|
||||
|
||||
/// Start the command-line expansion and get the matches.
|
||||
@ -805,8 +805,8 @@ static char *find_longest_match(expand_T *xp, int options)
|
||||
/// Return NULL for failure.
|
||||
///
|
||||
/// "orig" is the originally expanded string, copied to allocated memory. It
|
||||
/// should either be kept in orig_save or freed. When "mode" is WILD_NEXT or
|
||||
/// WILD_PREV "orig" should be NULL.
|
||||
/// should either be kept in "xp->xp_orig" or freed. When "mode" is WILD_NEXT
|
||||
/// or WILD_PREV "orig" should be NULL.
|
||||
///
|
||||
/// Results are cached in xp->xp_files and xp->xp_numfiles, except when "mode"
|
||||
/// is WILD_EXPAND_FREE or WILD_ALL.
|
||||
@ -841,21 +841,20 @@ static char *find_longest_match(expand_T *xp, int options)
|
||||
char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
|
||||
{
|
||||
char *ss = NULL;
|
||||
static char *orig_save = NULL; // kept value of orig
|
||||
int orig_saved = false;
|
||||
|
||||
// first handle the case of using an old match
|
||||
if (mode == WILD_NEXT || mode == WILD_PREV
|
||||
|| mode == WILD_PAGEUP || mode == WILD_PAGEDOWN
|
||||
|| mode == WILD_PUM_WANT) {
|
||||
return get_next_or_prev_match(mode, xp, orig_save);
|
||||
return get_next_or_prev_match(mode, xp);
|
||||
}
|
||||
|
||||
if (mode == WILD_CANCEL) {
|
||||
ss = xstrdup(orig_save ? orig_save : "");
|
||||
ss = xstrdup(xp->xp_orig ? xp->xp_orig : "");
|
||||
} else if (mode == WILD_APPLY) {
|
||||
ss = xstrdup(xp->xp_selected == -1
|
||||
? (orig_save ? orig_save : "")
|
||||
? (xp->xp_orig ? xp->xp_orig : "")
|
||||
: xp->xp_files[xp->xp_selected]);
|
||||
}
|
||||
|
||||
@ -863,7 +862,7 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
|
||||
if (xp->xp_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST) {
|
||||
FreeWild(xp->xp_numfiles, xp->xp_files);
|
||||
xp->xp_numfiles = -1;
|
||||
XFREE_CLEAR(orig_save);
|
||||
XFREE_CLEAR(xp->xp_orig);
|
||||
|
||||
// The entries from xp_files may be used in the PUM, remove it.
|
||||
if (compl_match_array != NULL) {
|
||||
@ -877,8 +876,8 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
|
||||
}
|
||||
|
||||
if (xp->xp_numfiles == -1 && mode != WILD_APPLY && mode != WILD_CANCEL) {
|
||||
xfree(orig_save);
|
||||
orig_save = orig;
|
||||
xfree(xp->xp_orig);
|
||||
xp->xp_orig = orig;
|
||||
orig_saved = true;
|
||||
|
||||
ss = ExpandOne_start(mode, xp, str, options);
|
||||
@ -912,7 +911,7 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
|
||||
ExpandCleanup(xp);
|
||||
}
|
||||
|
||||
// Free "orig" if it wasn't stored in "orig_save".
|
||||
// Free "orig" if it wasn't stored in "xp->xp_orig".
|
||||
if (!orig_saved) {
|
||||
xfree(orig);
|
||||
}
|
||||
@ -936,6 +935,7 @@ void ExpandCleanup(expand_T *xp)
|
||||
FreeWild(xp->xp_numfiles, xp->xp_files);
|
||||
xp->xp_numfiles = -1;
|
||||
}
|
||||
XFREE_CLEAR(xp->xp_orig);
|
||||
}
|
||||
|
||||
/// Display one line of completion matches. Multiple matches are displayed in
|
||||
|
@ -237,6 +237,7 @@ struct expand {
|
||||
int xp_numfiles; // number of files found by file name completion
|
||||
int xp_col; // cursor position in line
|
||||
int xp_selected; // selected index in completion
|
||||
char *xp_orig; // originally expanded string
|
||||
char **xp_files; // list of files
|
||||
char *xp_line; // text being completed
|
||||
#define EXPAND_BUF_LEN 256
|
||||
|
@ -3650,4 +3650,22 @@ func Test_getcompletion_usercmd()
|
||||
delcom TestCompletion
|
||||
endfunc
|
||||
|
||||
func Test_custom_completion_with_glob()
|
||||
func TestGlobComplete(A, L, P)
|
||||
return split(glob('Xglob*'), "\n")
|
||||
endfunc
|
||||
|
||||
command -nargs=* -complete=customlist,TestGlobComplete TestGlobComplete :
|
||||
call writefile([], 'Xglob1')
|
||||
call writefile([], 'Xglob2')
|
||||
|
||||
call feedkeys(":TestGlobComplete \<Tab> \<Tab>\<C-N> \<Tab>\<C-P>;\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"TestGlobComplete Xglob1 Xglob2 ;', @:)
|
||||
|
||||
call delete('Xglob1')
|
||||
call delete('Xglob2')
|
||||
delcommand TestGlobComplete
|
||||
delfunc TestGlobComplete
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
Loading…
Reference in New Issue
Block a user