Skip to content

Commit

Permalink
Problem: exists(':keepalt') return 0
Browse files Browse the repository at this point in the history
Problem:  exists(':keepalt') returns 0
Solution: partly revert patch v9.1.0352,
          also ignore :{ and :} when expanding
          command line items

fixes: vim#15305

Signed-off-by: Christian Brabandt <[email protected]>
  • Loading branch information
chrisbra committed Jul 26, 2024
1 parent dc373d4 commit 29e51f2
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 61 deletions.
81 changes: 20 additions & 61 deletions src/ex_docmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -4050,53 +4046,27 @@ 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.
*/
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;
}

Expand All @@ -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.
Expand Down Expand Up @@ -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;
}

Expand Down
21 changes: 21 additions & 0 deletions src/testdir/test_cmdline.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 29e51f2

Please sign in to comment.