Merge pull request #21806 from zeertzjq/vim-8.2.4565

vim-patch:8.2.{4563,4565,4570}: cmdline completion for :breakadd, :breakdel, :profdel
This commit is contained in:
zeertzjq 2023-01-15 08:38:23 +08:00 committed by GitHub
commit 9dd5903273
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 325 additions and 7 deletions

View File

@ -2958,7 +2958,8 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
arglist file names in argument list
augroup autocmd groups
buffer buffer names
behave :behave suboptions
behave |:behave| suboptions
breakpoint |:breakadd| and |:breakdel| suboptions
cmdline |cmdline-completion| result
color color schemes
command Ex command
@ -2974,7 +2975,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
function function name
help help subjects
highlight highlight groups
history :history suboptions
history |:history| suboptions
locale locale names (as output of locale -a)
mapclear buffer argument
mapping mapping name

View File

@ -1658,6 +1658,62 @@ static const char *set_context_in_lang_cmd(expand_T *xp, const char *arg)
return NULL;
}
static enum {
EXP_BREAKPT_ADD, ///< expand ":breakadd" sub-commands
EXP_BREAKPT_DEL, ///< expand ":breakdel" sub-commands
EXP_PROFDEL, ///< expand ":profdel" sub-commands
} breakpt_expand_what;
/// Set the completion context for the :breakadd command. Always returns NULL.
static const char *set_context_in_breakadd_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
{
xp->xp_context = EXPAND_BREAKPOINT;
xp->xp_pattern = (char *)arg;
if (cmdidx == CMD_breakadd) {
breakpt_expand_what = EXP_BREAKPT_ADD;
} else if (cmdidx == CMD_breakdel) {
breakpt_expand_what = EXP_BREAKPT_DEL;
} else {
breakpt_expand_what = EXP_PROFDEL;
}
const char *p = skipwhite(arg);
if (*p == NUL) {
return NULL;
}
const char *subcmd_start = p;
if (strncmp("file ", p, 5) == 0 || strncmp("func ", p, 5) == 0) {
// :breakadd file [lnum] <filename>
// :breakadd func [lnum] <funcname>
p += 4;
p = skipwhite(p);
// skip line number (if specified)
if (ascii_isdigit(*p)) {
p = skipdigits(p);
if (*p != ' ') {
xp->xp_context = EXPAND_NOTHING;
return NULL;
}
p = skipwhite(p);
}
if (strncmp("file", subcmd_start, 4) == 0) {
xp->xp_context = EXPAND_FILES;
} else {
xp->xp_context = EXPAND_USER_FUNC;
}
xp->xp_pattern = (char *)p;
} else if (strncmp("expr ", p, 5) == 0) {
// :breakadd expr <expression>
xp->xp_context = EXPAND_EXPRESSION;
xp->xp_pattern = skipwhite(p + 5);
}
return NULL;
}
/// Set the completion context in "xp" for command "cmd" with index "cmdidx".
/// The argument to the command is "arg" and the argument flags is "argt".
/// For user-defined commands and for environment variables, "context" has the
@ -2012,6 +2068,11 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa
xp->xp_pattern = (char *)arg;
break;
case CMD_breakadd:
case CMD_profdel:
case CMD_breakdel:
return set_context_in_breakadd_cmd(xp, arg, cmdidx);
case CMD_lua:
xp->xp_context = EXPAND_LUA;
break;
@ -2358,6 +2419,32 @@ static char *get_behave_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
return NULL;
}
/// Function given to ExpandGeneric() to obtain the possible arguments of the
/// ":breakadd {expr, file, func, here}" command.
/// ":breakdel {func, file, here}" command.
static char *get_breakadd_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
{
char *opts[] = { "expr", "file", "func", "here" };
if (idx >= 0 && idx <= 3) {
// breakadd {expr, file, func, here}
if (breakpt_expand_what == EXP_BREAKPT_ADD) {
return opts[idx];
} else if (breakpt_expand_what == EXP_BREAKPT_DEL) {
// breakdel {func, file, here}
if (idx <= 2) {
return opts[idx + 1];
}
} else {
// profdel {func, file}
if (idx <= 1) {
return opts[idx + 1];
}
}
}
return NULL;
}
/// Function given to ExpandGeneric() to obtain the possible arguments of the
/// ":messages {clear}" command.
static char *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
@ -2442,6 +2529,7 @@ static int ExpandOther(expand_T *xp, regmatch_T *rmp, char ***matches, int *numM
{ EXPAND_ENV_VARS, get_env_name, true, true },
{ EXPAND_USER, get_users, true, false },
{ EXPAND_ARGLIST, get_arglist_name, true, false },
{ EXPAND_BREAKPOINT, get_breakadd_arg, true, true },
{ EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
};
int ret = FAIL;

View File

@ -354,7 +354,6 @@ char *get_profile_name(expand_T *xp, int idx)
switch (pexpand_what) {
case PEXP_SUBCMD:
return pexpand_cmds[idx];
// case PEXP_FUNC: TODO
default:
return NULL;
}
@ -373,13 +372,17 @@ void set_context_in_profile_cmd(expand_T *xp, const char *arg)
return;
}
if (end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0) {
if ((end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0)
|| (end_subcmd - arg == 4 && strncmp(arg, "file", 4) == 0)) {
xp->xp_context = EXPAND_FILES;
xp->xp_pattern = skipwhite(end_subcmd);
return;
} else if (end_subcmd - arg == 4 && strncmp(arg, "func", 4) == 0) {
xp->xp_context = EXPAND_USER_FUNC;
xp->xp_pattern = skipwhite(end_subcmd);
return;
}
// TODO(tarruda): expand function names after "func"
xp->xp_context = EXPAND_NOTHING;
}

View File

@ -483,6 +483,11 @@ void spell_suggest(int count)
}
badlen++;
end_visual_mode();
// make sure we don't include the NUL at the end of the line
line = get_cursor_line_ptr();
if (badlen > (int)strlen(line) - (int)curwin->w_cursor.col) {
badlen = (int)strlen(line) - (int)curwin->w_cursor.col;
}
// Find the start of the badly spelled word.
} else if (spell_move_to(curwin, FORWARD, true, true, NULL) == 0
|| curwin->w_cursor.col > prev_cursor.col) {

View File

@ -2654,6 +2654,159 @@ func Test_cmdline_complete_dlist()
call assert_equal("\"dlist 10 /pat/ | chistory", @:)
endfunc
" Test for :breakadd argument completion
func Test_cmdline_complete_breakadd()
call feedkeys(":breakadd \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd expr file func here", @:)
call feedkeys(":breakadd \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd expr", @:)
call feedkeys(":breakadd \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd expr", @:)
call feedkeys(":breakadd he\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd here", @:)
call feedkeys(":breakadd he\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd here", @:)
call feedkeys(":breakadd abc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd abc", @:)
call assert_equal(['expr', 'file', 'func', 'here'], getcompletion('', 'breakpoint'))
let l = getcompletion('not', 'breakpoint')
call assert_equal([], l)
" Test for :breakadd file [lnum] <file>
call writefile([], 'Xscript')
call feedkeys(":breakadd file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd file Xscript", @:)
call feedkeys(":breakadd file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd file Xscript", @:)
call feedkeys(":breakadd file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd file 20 Xscript", @:)
call feedkeys(":breakadd file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd file 20 Xscript", @:)
call feedkeys(":breakadd file 20x Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd file 20x Xsc\t", @:)
call feedkeys(":breakadd file 20\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd file 20\t", @:)
call feedkeys(":breakadd file 20x\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd file 20x\t", @:)
call feedkeys(":breakadd file Xscript \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd file Xscript ", @:)
call feedkeys(":breakadd file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd file X1B2C3", @:)
call delete('Xscript')
" Test for :breakadd func [lnum] <function>
func Xbreak_func()
endfunc
call feedkeys(":breakadd func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd func Xbreak_func", @:)
call feedkeys(":breakadd func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd func Xbreak_func", @:)
call feedkeys(":breakadd func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd func 20 Xbreak_func", @:)
call feedkeys(":breakadd func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd func 20 Xbreak_func", @:)
call feedkeys(":breakadd func 20x Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd func 20x Xbr\t", @:)
call feedkeys(":breakadd func 20\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd func 20\t", @:)
call feedkeys(":breakadd func 20x\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd func 20x\t", @:)
call feedkeys(":breakadd func Xbreak_func \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd func Xbreak_func ", @:)
call feedkeys(":breakadd func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd func X1B2C3", @:)
delfunc Xbreak_func
" Test for :breakadd expr <expression>
let g:Xtest_var = 10
call feedkeys(":breakadd expr Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd expr Xtest_var", @:)
call feedkeys(":breakadd expr Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd expr Xtest_var", @:)
call feedkeys(":breakadd expr Xtest_var \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd expr Xtest_var ", @:)
call feedkeys(":breakadd expr X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd expr X1B2C3", @:)
unlet g:Xtest_var
" Test for :breakadd here
call feedkeys(":breakadd here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd here Xtest", @:)
call feedkeys(":breakadd here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd here Xtest", @:)
call feedkeys(":breakadd here \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakadd here ", @:)
endfunc
" Test for :breakdel argument completion
func Test_cmdline_complete_breakdel()
call feedkeys(":breakdel \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file func here", @:)
call feedkeys(":breakdel \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file", @:)
call feedkeys(":breakdel \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file", @:)
call feedkeys(":breakdel he\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel here", @:)
call feedkeys(":breakdel he\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel here", @:)
call feedkeys(":breakdel abc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel abc", @:)
" Test for :breakdel file [lnum] <file>
call writefile([], 'Xscript')
call feedkeys(":breakdel file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file Xscript", @:)
call feedkeys(":breakdel file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file Xscript", @:)
call feedkeys(":breakdel file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file 20 Xscript", @:)
call feedkeys(":breakdel file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file 20 Xscript", @:)
call feedkeys(":breakdel file 20x Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file 20x Xsc\t", @:)
call feedkeys(":breakdel file 20\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file 20\t", @:)
call feedkeys(":breakdel file 20x\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file 20x\t", @:)
call feedkeys(":breakdel file Xscript \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file Xscript ", @:)
call feedkeys(":breakdel file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel file X1B2C3", @:)
call delete('Xscript')
" Test for :breakdel func [lnum] <function>
func Xbreak_func()
endfunc
call feedkeys(":breakdel func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel func Xbreak_func", @:)
call feedkeys(":breakdel func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel func Xbreak_func", @:)
call feedkeys(":breakdel func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel func 20 Xbreak_func", @:)
call feedkeys(":breakdel func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel func 20 Xbreak_func", @:)
call feedkeys(":breakdel func 20x Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel func 20x Xbr\t", @:)
call feedkeys(":breakdel func 20\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel func 20\t", @:)
call feedkeys(":breakdel func 20x\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel func 20x\t", @:)
call feedkeys(":breakdel func Xbreak_func \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel func Xbreak_func ", @:)
call feedkeys(":breakdel func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel func X1B2C3", @:)
delfunc Xbreak_func
" Test for :breakdel here
call feedkeys(":breakdel here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel here Xtest", @:)
call feedkeys(":breakdel here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel here Xtest", @:)
call feedkeys(":breakdel here \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"breakdel here ", @:)
endfunc
" this was going over the end of IObuff
func Test_report_error_with_composing()
let caught = 'no'

View File

@ -403,6 +403,47 @@ func Test_profile_completion()
call feedkeys(":profile start test_prof\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_match('^"profile start.* test_profile\.vim', @:)
call feedkeys(":profile file test_prof\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_match('"profile file test_profile\.vim', @:)
call feedkeys(":profile file test_prof\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_match('"profile file test_profile\.vim', @:)
call feedkeys(":profile file test_prof \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_match('"profile file test_prof ', @:)
call feedkeys(":profile file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_match('"profile file X1B2C3', @:)
func Xprof_test()
endfunc
call feedkeys(":profile func Xprof\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profile func Xprof_test', @:)
call feedkeys(":profile func Xprof\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profile func Xprof_test', @:)
call feedkeys(":profile func Xprof \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profile func Xprof ', @:)
call feedkeys(":profile func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profile func X1B2C3', @:)
call feedkeys(":profdel \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profdel file func', @:)
call feedkeys(":profdel fu\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profdel func', @:)
call feedkeys(":profdel he\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profdel he', @:)
call feedkeys(":profdel here \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profdel here ', @:)
call feedkeys(":profdel file test_prof\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profdel file test_profile.vim', @:)
call feedkeys(":profdel file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profdel file X1B2C3', @:)
call feedkeys(":profdel func Xprof\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profdel func Xprof_test', @:)
call feedkeys(":profdel func Xprof_test \<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profdel func Xprof_test ', @:)
call feedkeys(":profdel func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profdel func X1B2C3', @:)
delfunc Xprof_test
endfunc
func Test_profile_errors()

View File

@ -531,8 +531,23 @@ func Test_spellsuggest_timeout()
call assert_fails('set spellsuggest=timeout:--9', 'E474:')
endfunc
func Test_spellsuggest_visual_end_of_line()
let enc_save = &encoding
" set encoding=iso8859
" This was reading beyond the end of the line.
norm R00000000000
sil norm 0
sil! norm i00000)
sil! norm i00000)
call feedkeys("\<CR>")
norm z=
let &encoding = enc_save
endfunc
func Test_spellinfo()
throw 'skipped: Nvim does not support enc=latin1'
throw 'Skipped: Nvim does not support enc=latin1'
new
let runtime = substitute($VIMRUNTIME, '\\', '/', 'g')

View File

@ -896,6 +896,9 @@ endfunc
" link to the original file. The backup file should not be modified.
func Test_write_backup_symlink()
CheckUnix
call mkdir('Xbackup')
let save_backupdir = &backupdir
set backupdir=.,./Xbackup
call writefile(['1111'], 'Xfile')
silent !ln -s Xfile Xfile.bak
@ -904,11 +907,18 @@ func Test_write_backup_symlink()
write
call assert_equal('link', getftype('Xfile.bak'))
call assert_equal('Xfile', resolve('Xfile.bak'))
" backup file should be created in the 'backup' directory
if !has('bsd')
" This check fails on FreeBSD
call assert_true(filereadable('./Xbackup/Xfile.bak'))
endif
set backup& backupcopy& backupext&
close
%bw
call delete('Xfile')
call delete('Xfile.bak')
call delete('Xbackup', 'rf')
let &backupdir = save_backupdir
endfunc
" Test for ':write ++bin' and ':write ++nobin'

View File

@ -95,6 +95,7 @@ static const char *command_complete[] = {
[EXPAND_TAGS_LISTFILES] = "tag_listfiles",
[EXPAND_USER] = "user",
[EXPAND_USER_VARS] = "var",
[EXPAND_BREAKPOINT] = "breakpoint",
};
/// List of names of address types. Must be alphabetical for completion.

View File

@ -154,6 +154,7 @@ enum {
EXPAND_MAPCLEAR,
EXPAND_ARGLIST,
EXPAND_DIFF_BUFFERS,
EXPAND_BREAKPOINT,
EXPAND_CHECKHEALTH,
EXPAND_LUA,
};