# HG changeset patch # User Bram Moolenaar # Date 1647286203 -3600 # Node ID b737bfa876c5a8f7874f82b484da251d2f8e8971 # Parent 8f6aea2b806909243e2c34a5972af532f0f84b4b patch 8.2.4565: no command line completion for :breakadd and :breakdel Commit: https://github.com/vim/vim/commit/6e2e2cc95b913e33145047e0fade5193da6e4379 Author: Bram Moolenaar Date: Mon Mar 14 19:24:46 2022 +0000 patch 8.2.4565: no command line completion for :breakadd and :breakdel Problem: No command line completion for :breakadd and :breakdel. Solution: Add completion for :breakadd and :breakdel. (Yegappan Lakshmanan, closes #9950) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -3230,7 +3230,8 @@ getcompletion({pat}, {type} [, {filtered arglist file names in argument list augroup autocmd groups buffer buffer names - behave :behave suboptions + behave |:behave| suboptions + breakpoint |:breakadd| and |:breakdel| suboptions color color schemes command Ex command cmdline |cmdline-completion| result @@ -3247,7 +3248,7 @@ getcompletion({pat}, {type} [, {filtered 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 diff --git a/src/cmdexpand.c b/src/cmdexpand.c --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -1602,6 +1602,71 @@ set_context_in_lang_cmd(expand_T *xp, ch } #endif +#ifdef FEAT_EVAL +static enum +{ + EXP_BREAKPT_ADD, // expand ":breakadd" sub-commands + EXP_BREAKPT_DEL // expand ":breakdel" sub-commands +} breakpt_expand_what; + +/* + * Set the completion context for the :breakadd command. Always returns NULL. + */ + static char_u * +set_context_in_breakadd_cmd(expand_T *xp, char_u *arg, cmdidx_T cmdidx) +{ + char_u *p; + char_u *subcmd_start; + + xp->xp_context = EXPAND_BREAKPOINT; + xp->xp_pattern = arg; + + if (cmdidx == CMD_breakadd) + breakpt_expand_what = EXP_BREAKPT_ADD; + else + breakpt_expand_what = EXP_BREAKPT_DEL; + + p = skipwhite(arg); + if (*p == NUL) + return NULL; + subcmd_start = p; + + if (STRNCMP("file ", p, 5) == 0 || + STRNCMP("func ", p, 5) == 0) + { + // :breakadd file [lnum] + // :breakadd func [lnum] + p += 4; + p = skipwhite(p); + + // skip line number (if specified) + if (VIM_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 = p; + } + else if (STRNCMP("expr ", p, 5) == 0) + { + // :breakadd expr + xp->xp_context = EXPAND_EXPRESSION; + xp->xp_pattern = skipwhite(p + 5); + } + + return NULL; +} +#endif + /* * 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'. @@ -1958,6 +2023,12 @@ set_context_by_cmdname( xp->xp_pattern = arg; break; +#ifdef FEAT_EVAL + case CMD_breakadd: + case CMD_breakdel: + return set_context_in_breakadd_cmd(xp, arg, cmdidx); +#endif + default: break; } @@ -2348,6 +2419,31 @@ get_behave_arg(expand_T *xp UNUSED, int return NULL; } +# ifdef FEAT_EVAL +/* + * Function given to ExpandGeneric() to obtain the possible arguments of the + * ":breakadd {expr, file, func, here}" command. + * ":breakdel {func, file, here}" command. + */ + static char_u * +get_breakadd_arg(expand_T *xp UNUSED, int idx) +{ + char *opts[] = {"expr", "file", "func", "here"}; + + if (idx >=0 && idx <= 3) + { + if (breakpt_expand_what == EXP_BREAKPT_ADD) + return (char_u *)opts[idx]; + else + { + if (idx <= 2) + return (char_u *)opts[idx + 1]; + } + } + return NULL; +} +#endif + /* * Function given to ExpandGeneric() to obtain the possible arguments of the * ":messages {clear}" command. @@ -2397,42 +2493,45 @@ ExpandOther( {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE}, {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE}, {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE}, -# ifdef FEAT_EVAL +#ifdef FEAT_EVAL {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE}, {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE}, {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE}, {EXPAND_DISASSEMBLE, get_disassemble_argument, FALSE, TRUE}, {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE}, -# endif -# ifdef FEAT_MENU +#endif +#ifdef FEAT_MENU {EXPAND_MENUS, get_menu_name, FALSE, TRUE}, {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE}, -# endif -# ifdef FEAT_SYN_HL +#endif +#ifdef FEAT_SYN_HL {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE}, -# endif -# ifdef FEAT_PROFILE +#endif +#ifdef FEAT_PROFILE {EXPAND_SYNTIME, get_syntime_arg, TRUE, TRUE}, -# endif +#endif {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE}, {EXPAND_EVENTS, get_event_name, TRUE, FALSE}, {EXPAND_AUGROUP, get_augroup_name, TRUE, FALSE}, -# ifdef FEAT_CSCOPE +#ifdef FEAT_CSCOPE {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE}, -# endif -# ifdef FEAT_SIGNS +#endif +#ifdef FEAT_SIGNS {EXPAND_SIGN, get_sign_name, TRUE, TRUE}, -# endif -# ifdef FEAT_PROFILE +#endif +#ifdef FEAT_PROFILE {EXPAND_PROFILE, get_profile_name, TRUE, TRUE}, -# endif -# if defined(HAVE_LOCALE_H) || defined(X_LOCALE) +#endif +#if defined(HAVE_LOCALE_H) || defined(X_LOCALE) {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE}, {EXPAND_LOCALES, get_locales, TRUE, FALSE}, -# endif +#endif {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, {EXPAND_USER, get_users, TRUE, FALSE}, {EXPAND_ARGLIST, get_arglist_name, TRUE, FALSE}, +#ifdef FEAT_EVAL + {EXPAND_BREAKPOINT, get_breakadd_arg, TRUE, TRUE}, +#endif }; int i; int ret = FAIL; diff --git a/src/spellsuggest.c b/src/spellsuggest.c --- a/src/spellsuggest.c +++ b/src/spellsuggest.c @@ -508,7 +508,7 @@ spell_suggest(int count) end_visual_mode(); // make sure we don't include the NUL at the end of the line line = ml_get_curline(); - if (badlen > STRLEN(line) - curwin->w_cursor.col) + if (badlen > (int)STRLEN(line) - (int)curwin->w_cursor.col) badlen = STRLEN(line) - curwin->w_cursor.col; } // Find the start of the badly spelled word. diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -3007,4 +3007,158 @@ func Test_fuzzy_completion_custom_func() set wildoptions& endfunc +" Test for :breakadd argument completion +func Test_cmdline_complete_breakadd() + call feedkeys(":breakadd \\\"\", 'tx') + call assert_equal("\"breakadd expr file func here", @:) + call feedkeys(":breakadd \\\"\", 'tx') + call assert_equal("\"breakadd expr", @:) + call feedkeys(":breakadd \\\"\", 'tx') + call assert_equal("\"breakadd expr", @:) + call feedkeys(":breakadd he\\\"\", 'tx') + call assert_equal("\"breakadd here", @:) + call feedkeys(":breakadd he\\\"\", 'tx') + call assert_equal("\"breakadd here", @:) + call feedkeys(":breakadd abc\\\"\", '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] + call writefile([], 'Xscript') + call feedkeys(":breakadd file Xsc\\\"\", 'tx') + call assert_equal("\"breakadd file Xscript", @:) + call feedkeys(":breakadd file Xsc\\\"\", 'tx') + call assert_equal("\"breakadd file Xscript", @:) + call feedkeys(":breakadd file 20 Xsc\\\"\", 'tx') + call assert_equal("\"breakadd file 20 Xscript", @:) + call feedkeys(":breakadd file 20 Xsc\\\"\", 'tx') + call assert_equal("\"breakadd file 20 Xscript", @:) + call feedkeys(":breakadd file 20x Xsc\\\"\", 'tx') + call assert_equal("\"breakadd file 20x Xsc\t", @:) + call feedkeys(":breakadd file 20\\\"\", 'tx') + call assert_equal("\"breakadd file 20\t", @:) + call feedkeys(":breakadd file 20x\\\"\", 'tx') + call assert_equal("\"breakadd file 20x\t", @:) + call feedkeys(":breakadd file Xscript \\\"\", 'tx') + call assert_equal("\"breakadd file Xscript ", @:) + call feedkeys(":breakadd file X1B2C3\\\"\", 'tx') + call assert_equal("\"breakadd file X1B2C3", @:) + call delete('Xscript') + + " Test for :breakadd func [lnum] + func Xbreak_func() + endfunc + call feedkeys(":breakadd func Xbr\\\"\", 'tx') + call assert_equal("\"breakadd func Xbreak_func", @:) + call feedkeys(":breakadd func Xbr\\\"\", 'tx') + call assert_equal("\"breakadd func Xbreak_func", @:) + call feedkeys(":breakadd func 20 Xbr\\\"\", 'tx') + call assert_equal("\"breakadd func 20 Xbreak_func", @:) + call feedkeys(":breakadd func 20 Xbr\\\"\", 'tx') + call assert_equal("\"breakadd func 20 Xbreak_func", @:) + call feedkeys(":breakadd func 20x Xbr\\\"\", 'tx') + call assert_equal("\"breakadd func 20x Xbr\t", @:) + call feedkeys(":breakadd func 20\\\"\", 'tx') + call assert_equal("\"breakadd func 20\t", @:) + call feedkeys(":breakadd func 20x\\\"\", 'tx') + call assert_equal("\"breakadd func 20x\t", @:) + call feedkeys(":breakadd func Xbreak_func \\\"\", 'tx') + call assert_equal("\"breakadd func Xbreak_func ", @:) + call feedkeys(":breakadd func X1B2C3\\\"\", 'tx') + call assert_equal("\"breakadd func X1B2C3", @:) + delfunc Xbreak_func + + " Test for :breakadd expr + let g:Xtest_var = 10 + call feedkeys(":breakadd expr Xtest\\\"\", 'tx') + call assert_equal("\"breakadd expr Xtest_var", @:) + call feedkeys(":breakadd expr Xtest\\\"\", 'tx') + call assert_equal("\"breakadd expr Xtest_var", @:) + call feedkeys(":breakadd expr Xtest_var \\\"\", 'tx') + call assert_equal("\"breakadd expr Xtest_var ", @:) + call feedkeys(":breakadd expr X1B2C3\\\"\", 'tx') + call assert_equal("\"breakadd expr X1B2C3", @:) + unlet g:Xtest_var + + " Test for :breakadd here + call feedkeys(":breakadd here Xtest\\\"\", 'tx') + call assert_equal("\"breakadd here Xtest", @:) + call feedkeys(":breakadd here Xtest\\\"\", 'tx') + call assert_equal("\"breakadd here Xtest", @:) + call feedkeys(":breakadd here \\\"\", 'tx') + call assert_equal("\"breakadd here ", @:) +endfunc + +" Test for :breakdel argument completion +func Test_cmdline_complete_breakdel() + call feedkeys(":breakdel \\\"\", 'tx') + call assert_equal("\"breakdel file func here", @:) + call feedkeys(":breakdel \\\"\", 'tx') + call assert_equal("\"breakdel file", @:) + call feedkeys(":breakdel \\\"\", 'tx') + call assert_equal("\"breakdel file", @:) + call feedkeys(":breakdel he\\\"\", 'tx') + call assert_equal("\"breakdel here", @:) + call feedkeys(":breakdel he\\\"\", 'tx') + call assert_equal("\"breakdel here", @:) + call feedkeys(":breakdel abc\\\"\", 'tx') + call assert_equal("\"breakdel abc", @:) + + " Test for :breakdel file [lnum] + call writefile([], 'Xscript') + call feedkeys(":breakdel file Xsc\\\"\", 'tx') + call assert_equal("\"breakdel file Xscript", @:) + call feedkeys(":breakdel file Xsc\\\"\", 'tx') + call assert_equal("\"breakdel file Xscript", @:) + call feedkeys(":breakdel file 20 Xsc\\\"\", 'tx') + call assert_equal("\"breakdel file 20 Xscript", @:) + call feedkeys(":breakdel file 20 Xsc\\\"\", 'tx') + call assert_equal("\"breakdel file 20 Xscript", @:) + call feedkeys(":breakdel file 20x Xsc\\\"\", 'tx') + call assert_equal("\"breakdel file 20x Xsc\t", @:) + call feedkeys(":breakdel file 20\\\"\", 'tx') + call assert_equal("\"breakdel file 20\t", @:) + call feedkeys(":breakdel file 20x\\\"\", 'tx') + call assert_equal("\"breakdel file 20x\t", @:) + call feedkeys(":breakdel file Xscript \\\"\", 'tx') + call assert_equal("\"breakdel file Xscript ", @:) + call feedkeys(":breakdel file X1B2C3\\\"\", 'tx') + call assert_equal("\"breakdel file X1B2C3", @:) + call delete('Xscript') + + " Test for :breakdel func [lnum] + func Xbreak_func() + endfunc + call feedkeys(":breakdel func Xbr\\\"\", 'tx') + call assert_equal("\"breakdel func Xbreak_func", @:) + call feedkeys(":breakdel func Xbr\\\"\", 'tx') + call assert_equal("\"breakdel func Xbreak_func", @:) + call feedkeys(":breakdel func 20 Xbr\\\"\", 'tx') + call assert_equal("\"breakdel func 20 Xbreak_func", @:) + call feedkeys(":breakdel func 20 Xbr\\\"\", 'tx') + call assert_equal("\"breakdel func 20 Xbreak_func", @:) + call feedkeys(":breakdel func 20x Xbr\\\"\", 'tx') + call assert_equal("\"breakdel func 20x Xbr\t", @:) + call feedkeys(":breakdel func 20\\\"\", 'tx') + call assert_equal("\"breakdel func 20\t", @:) + call feedkeys(":breakdel func 20x\\\"\", 'tx') + call assert_equal("\"breakdel func 20x\t", @:) + call feedkeys(":breakdel func Xbreak_func \\\"\", 'tx') + call assert_equal("\"breakdel func Xbreak_func ", @:) + call feedkeys(":breakdel func X1B2C3\\\"\", 'tx') + call assert_equal("\"breakdel func X1B2C3", @:) + delfunc Xbreak_func + + " Test for :breakdel here + call feedkeys(":breakdel here Xtest\\\"\", 'tx') + call assert_equal("\"breakdel here Xtest", @:) + call feedkeys(":breakdel here Xtest\\\"\", 'tx') + call assert_equal("\"breakdel here Xtest", @:) + call feedkeys(":breakdel here \\\"\", 'tx') + call assert_equal("\"breakdel here ", @:) + +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_writefile.vim b/src/testdir/test_writefile.vim --- a/src/testdir/test_writefile.vim +++ b/src/testdir/test_writefile.vim @@ -890,6 +890,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 @@ -898,11 +901,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' diff --git a/src/usercmd.c b/src/usercmd.c --- a/src/usercmd.c +++ b/src/usercmd.c @@ -90,6 +90,9 @@ static struct {EXPAND_TAGS_LISTFILES, "tag_listfiles"}, {EXPAND_USER, "user"}, {EXPAND_USER_VARS, "var"}, +#if defined(FEAT_EVAL) + {EXPAND_BREAKPOINT, "breakpoint"}, +#endif {0, NULL} }; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4565, +/**/ 4564, /**/ 4563, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -801,6 +801,7 @@ extern int (*dyn_libintl_wputenv)(const #define EXPAND_ARGLIST 48 #define EXPAND_DIFF_BUFFERS 49 #define EXPAND_DISASSEMBLE 50 +#define EXPAND_BREAKPOINT 51 // Values for exmode_active (0 is no exmode) #define EXMODE_NORMAL 1