diff options
author | Christian Brabandt <cb@256bit.org> | 2024-07-26 19:13:55 +0200 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2024-07-26 19:13:55 +0200 |
commit | 70a11a6bf69f477844470ce59958b686024d2a41 (patch) | |
tree | 3ad5acb1a26ac84bc8745a852590bd970573e927 | |
parent | 325420ebe459e7f67b959ce189269b0e8ca9dc12 (diff) |
patch 9.1.0624: ex command modifiers not foundv9.1.0624
Problem: ex command modifiers are not found
(Ingo Karkat, after v9.1.0352)
Solution: partly revert patch v9.1.0352, ignore :{ and :}
when expanding ex commands
The issue is, that the :keepmarks command can be abbreviated to :kee or
:keep or :keepm but not to e.g. :ke (because that would be the :exe
command :k with register e).
This basically means, we need `:kee` sorted before `:keepalt` but at the
same time `:keepmarks` sorted after the `:keepalt` command in the
cmdmod_info_tab table. Due to this, the binary search may not work
correctly, so let's revert that part of patch v9.1.0352.
fixes: #15305
closes: #15336
Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r-- | src/ex_docmd.c | 81 | ||||
-rw-r--r-- | src/testdir/test_cmdline.vim | 21 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 43 insertions, 61 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c index e6200ed706..2a59301548 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -19,10 +19,6 @@ static int ex_pressedreturn = FALSE; # define ex_hardcopy ex_ni #endif -#if defined(FEAT_EVAL) || defined(PROTO) -static int cmp_cmdmod_info(const void *a, const void *b); -#endif - #ifdef FEAT_EVAL static char_u *do_one_cmd(char_u **, int, cstack_T *, char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie); #else @@ -4050,16 +4046,6 @@ static cmdmod_info_T cmdmod_info_tab[] = { {"vim9cmd", 4, FALSE} }; // cmdmod_info_tab -// compare two cmdmod_info_T structs by case sensitive name with length - static int -cmp_cmdmod_info(const void *a, const void *b) -{ - cmdmod_info_T *cm1 = (cmdmod_info_T *)a; - cmdmod_info_T *cm2 = (cmdmod_info_T *)b; - - return STRNCMP(cm1->name, cm2->name, cm2->minlen); -} - /* * Return length of a command modifier (including optional count). * Return zero when it's not a modifier. @@ -4067,36 +4053,20 @@ cmp_cmdmod_info(const void *a, const void *b) int modifier_len(char_u *cmd) { + int i, j; char_u *p = cmd; - cmdmod_info_T target; - cmdmod_info_T *entry; if (VIM_ISDIGIT(*cmd)) p = skipwhite(skipdigits(cmd + 1)); - - // only lowercase characters can match - if (!ASCII_ISLOWER(*p)) - return 0; - - target.name = (char *)p; - target.minlen = 0; // not used, see cmp_cmdmod_info() - target.has_count = FALSE; - - entry = (cmdmod_info_T *)bsearch(&target, &cmdmod_info_tab, ARRAY_LENGTH(cmdmod_info_tab), sizeof(cmdmod_info_tab[0]), cmp_cmdmod_info); - if (entry != NULL) + for (i = 0; i < (int)ARRAY_LENGTH(cmdmod_info_tab); ++i) { - int i; - - for (i = entry->minlen; p[i] != NUL; ++i) - { - if (p[i] != entry->name[i]) + for (j = 0; p[j] != NUL; ++j) + if (p[j] != cmdmod_info_tab[i].name[j]) break; - } - - if (!ASCII_ISALPHA(p[i]) && i >= entry->minlen && (p == cmd || entry->has_count)) - return i + (int)(p - cmd); + if (!ASCII_ISALPHA(p[j]) && j >= cmdmod_info_tab[i].minlen + && (p == cmd || cmdmod_info_tab[i].has_count)) + return j + (int)(p - cmd); } - return 0; } @@ -4110,33 +4080,18 @@ cmd_exists(char_u *name) { exarg_T ea; int full = FALSE; + int i; + int j; char_u *p; - // only lowercase characters can match - if (ASCII_ISLOWER(*name)) + // Check command modifiers. + for (i = 0; i < (int)ARRAY_LENGTH(cmdmod_info_tab); ++i) { - cmdmod_info_T target; - cmdmod_info_T *entry; - - target.name = (char *)name; - target.minlen = 0; // not used, see cmp_cmdmod_info() - target.has_count = FALSE; - - // Check command modifiers. - entry = (cmdmod_info_T *)bsearch(&target, &cmdmod_info_tab, ARRAY_LENGTH(cmdmod_info_tab), sizeof(cmdmod_info_tab[0]), cmp_cmdmod_info); - if (entry != NULL) - { - int i; - - for (i = entry->minlen; name[i] != NUL; ++i) - { - if (name[i] != entry->name[i]) - break; - } - - if (name[i] == NUL && i >= entry->minlen) - return (entry->name[i] == NUL ? 2 : 1); - } + for (j = 0; name[j] != NUL; ++j) + if (name[j] != cmdmod_info_tab[i].name[j]) + break; + if (name[j] == NUL && j >= cmdmod_info_tab[i].minlen) + return (cmdmod_info_tab[i].name[j] == NUL ? 2 : 1); } // Check built-in commands and user defined commands. @@ -5993,6 +5948,10 @@ get_command_name(expand_T *xp UNUSED, int idx) { if (idx >= (int)CMD_SIZE) return expand_user_command_name(idx); + // the following are no real commands + if (STRNCMP(cmdnames[idx].cmd_name, "{", 1) == 0 || + STRNCMP(cmdnames[idx].cmd_name, "}", 1) == 0) + return (char_u *)""; return cmdnames[idx].cmd_name; } diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index f83d673346..3f6918a8cd 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -3870,4 +3870,25 @@ func Test_term_option() let &cpo = _cpo endfunc +func Test_ex_command_completion() + " required for :* + set cpo+=* + let list = filter(getcompletion('', 'command'), 'exists(":" . v:val) == 0') + " :++ and :-- are only valid in Vim9 Script context, so they can be ignored + call assert_equal(['++', '--'], sort(list)) + call assert_equal(1, exists(':k')) + call assert_equal(0, exists(':ke')) + call assert_equal(1, exists(':kee')) + call assert_equal(1, exists(':keep')) + call assert_equal(1, exists(':keepm')) + call assert_equal(1, exists(':keepma')) + call assert_equal(1, exists(':keepmar')) + call assert_equal(1, exists(':keepmark')) + call assert_equal(2, exists(':keepmarks')) + call assert_equal(2, exists(':keepalt')) + call assert_equal(2, exists(':keepjumps')) + call assert_equal(2, exists(':keeppatterns')) + set cpo-=* +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index e16ad291a4..0dadd19b10 100644 --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 624, +/**/ 623, /**/ 622, |