forked from aniani/vim
patch 8.1.0939: no completion for sign group names
Problem: No completion for sign group names. Solution: Add completion for sign group names and buffer names. (Yegappan Lakshmanan, closes #3980)
This commit is contained in:
parent
21edde8742
commit
3678f65d43
128
src/sign.c
128
src/sign.c
@ -1767,10 +1767,58 @@ static enum
|
|||||||
EXP_SUBCMD, // expand :sign sub-commands
|
EXP_SUBCMD, // expand :sign sub-commands
|
||||||
EXP_DEFINE, // expand :sign define {name} args
|
EXP_DEFINE, // expand :sign define {name} args
|
||||||
EXP_PLACE, // expand :sign place {id} args
|
EXP_PLACE, // expand :sign place {id} args
|
||||||
|
EXP_LIST, // expand :sign place args
|
||||||
EXP_UNPLACE, // expand :sign unplace"
|
EXP_UNPLACE, // expand :sign unplace"
|
||||||
EXP_SIGN_NAMES // expand with name of placed signs
|
EXP_SIGN_NAMES, // expand with name of placed signs
|
||||||
|
EXP_SIGN_GROUPS // expand with name of placed sign groups
|
||||||
} expand_what;
|
} expand_what;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the n'th sign name (used for command line completion)
|
||||||
|
*/
|
||||||
|
static char_u *
|
||||||
|
get_nth_sign_name(int idx)
|
||||||
|
{
|
||||||
|
int current_idx;
|
||||||
|
sign_T *sp;
|
||||||
|
|
||||||
|
// Complete with name of signs already defined
|
||||||
|
current_idx = 0;
|
||||||
|
for (sp = first_sign; sp != NULL; sp = sp->sn_next)
|
||||||
|
if (current_idx++ == idx)
|
||||||
|
return sp->sn_name;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the n'th sign group name (used for command line completion)
|
||||||
|
*/
|
||||||
|
static char_u *
|
||||||
|
get_nth_sign_group_name(int idx)
|
||||||
|
{
|
||||||
|
int current_idx;
|
||||||
|
int todo;
|
||||||
|
hashitem_T *hi;
|
||||||
|
signgroup_T *group;
|
||||||
|
|
||||||
|
// Complete with name of sign groups already defined
|
||||||
|
current_idx = 0;
|
||||||
|
todo = (int)sg_table.ht_used;
|
||||||
|
for (hi = sg_table.ht_array; todo > 0; ++hi)
|
||||||
|
{
|
||||||
|
if (!HASHITEM_EMPTY(hi))
|
||||||
|
{
|
||||||
|
--todo;
|
||||||
|
if (current_idx++ == idx)
|
||||||
|
{
|
||||||
|
group = HI2SG(hi);
|
||||||
|
return group->sg_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function given to ExpandGeneric() to obtain the sign command
|
* Function given to ExpandGeneric() to obtain the sign command
|
||||||
* expansion.
|
* expansion.
|
||||||
@ -1778,9 +1826,6 @@ static enum
|
|||||||
char_u *
|
char_u *
|
||||||
get_sign_name(expand_T *xp UNUSED, int idx)
|
get_sign_name(expand_T *xp UNUSED, int idx)
|
||||||
{
|
{
|
||||||
sign_T *sp;
|
|
||||||
int current_idx;
|
|
||||||
|
|
||||||
switch (expand_what)
|
switch (expand_what)
|
||||||
{
|
{
|
||||||
case EXP_SUBCMD:
|
case EXP_SUBCMD:
|
||||||
@ -1802,18 +1847,23 @@ get_sign_name(expand_T *xp UNUSED, int idx)
|
|||||||
};
|
};
|
||||||
return (char_u *)place_arg[idx];
|
return (char_u *)place_arg[idx];
|
||||||
}
|
}
|
||||||
|
case EXP_LIST:
|
||||||
|
{
|
||||||
|
char *list_arg[] =
|
||||||
|
{
|
||||||
|
"group=", "file=", "buffer=", NULL
|
||||||
|
};
|
||||||
|
return (char_u *)list_arg[idx];
|
||||||
|
}
|
||||||
case EXP_UNPLACE:
|
case EXP_UNPLACE:
|
||||||
{
|
{
|
||||||
char *unplace_arg[] = { "group=", "file=", "buffer=", NULL };
|
char *unplace_arg[] = { "group=", "file=", "buffer=", NULL };
|
||||||
return (char_u *)unplace_arg[idx];
|
return (char_u *)unplace_arg[idx];
|
||||||
}
|
}
|
||||||
case EXP_SIGN_NAMES:
|
case EXP_SIGN_NAMES:
|
||||||
// Complete with name of signs already defined
|
return get_nth_sign_name(idx);
|
||||||
current_idx = 0;
|
case EXP_SIGN_GROUPS:
|
||||||
for (sp = first_sign; sp != NULL; sp = sp->sn_next)
|
return get_nth_sign_group_name(idx);
|
||||||
if (current_idx++ == idx)
|
|
||||||
return sp->sn_name;
|
|
||||||
return NULL;
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1848,28 +1898,6 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
|
|||||||
// |
|
// |
|
||||||
// begin_subcmd_args
|
// begin_subcmd_args
|
||||||
begin_subcmd_args = skipwhite(end_subcmd);
|
begin_subcmd_args = skipwhite(end_subcmd);
|
||||||
p = skiptowhite(begin_subcmd_args);
|
|
||||||
if (*p == NUL)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Expand first argument of subcmd when possible.
|
|
||||||
// For ":jump {id}" and ":unplace {id}", we could
|
|
||||||
// possibly expand the ids of all signs already placed.
|
|
||||||
//
|
|
||||||
xp->xp_pattern = begin_subcmd_args;
|
|
||||||
switch (cmd_idx)
|
|
||||||
{
|
|
||||||
case SIGNCMD_LIST:
|
|
||||||
case SIGNCMD_UNDEFINE:
|
|
||||||
// :sign list <CTRL-D>
|
|
||||||
// :sign undefine <CTRL-D>
|
|
||||||
expand_what = EXP_SIGN_NAMES;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
xp->xp_context = EXPAND_NOTHING;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// expand last argument of subcmd
|
// expand last argument of subcmd
|
||||||
|
|
||||||
@ -1878,6 +1906,7 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
|
|||||||
// p
|
// p
|
||||||
|
|
||||||
// Loop until reaching last argument.
|
// Loop until reaching last argument.
|
||||||
|
p = begin_subcmd_args;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
p = skipwhite(p);
|
p = skipwhite(p);
|
||||||
@ -1900,7 +1929,19 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
|
|||||||
expand_what = EXP_DEFINE;
|
expand_what = EXP_DEFINE;
|
||||||
break;
|
break;
|
||||||
case SIGNCMD_PLACE:
|
case SIGNCMD_PLACE:
|
||||||
expand_what = EXP_PLACE;
|
// List placed signs
|
||||||
|
if (VIM_ISDIGIT(*begin_subcmd_args))
|
||||||
|
// :sign place {id} {args}...
|
||||||
|
expand_what = EXP_PLACE;
|
||||||
|
else
|
||||||
|
// :sign place {args}...
|
||||||
|
expand_what = EXP_LIST;
|
||||||
|
break;
|
||||||
|
case SIGNCMD_LIST:
|
||||||
|
case SIGNCMD_UNDEFINE:
|
||||||
|
// :sign list <CTRL-D>
|
||||||
|
// :sign undefine <CTRL-D>
|
||||||
|
expand_what = EXP_SIGN_NAMES;
|
||||||
break;
|
break;
|
||||||
case SIGNCMD_JUMP:
|
case SIGNCMD_JUMP:
|
||||||
case SIGNCMD_UNPLACE:
|
case SIGNCMD_UNPLACE:
|
||||||
@ -1917,17 +1958,30 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
|
|||||||
switch (cmd_idx)
|
switch (cmd_idx)
|
||||||
{
|
{
|
||||||
case SIGNCMD_DEFINE:
|
case SIGNCMD_DEFINE:
|
||||||
if (STRNCMP(last, "texthl", p - last) == 0
|
if (STRNCMP(last, "texthl", 6) == 0
|
||||||
|| STRNCMP(last, "linehl", p - last) == 0)
|
|| STRNCMP(last, "linehl", 6) == 0)
|
||||||
xp->xp_context = EXPAND_HIGHLIGHT;
|
xp->xp_context = EXPAND_HIGHLIGHT;
|
||||||
else if (STRNCMP(last, "icon", p - last) == 0)
|
else if (STRNCMP(last, "icon", 4) == 0)
|
||||||
xp->xp_context = EXPAND_FILES;
|
xp->xp_context = EXPAND_FILES;
|
||||||
else
|
else
|
||||||
xp->xp_context = EXPAND_NOTHING;
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
break;
|
break;
|
||||||
case SIGNCMD_PLACE:
|
case SIGNCMD_PLACE:
|
||||||
if (STRNCMP(last, "name", p - last) == 0)
|
if (STRNCMP(last, "name", 4) == 0)
|
||||||
expand_what = EXP_SIGN_NAMES;
|
expand_what = EXP_SIGN_NAMES;
|
||||||
|
else if (STRNCMP(last, "group", 5) == 0)
|
||||||
|
expand_what = EXP_SIGN_GROUPS;
|
||||||
|
else if (STRNCMP(last, "file", 4) == 0)
|
||||||
|
xp->xp_context = EXPAND_BUFFERS;
|
||||||
|
else
|
||||||
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
|
break;
|
||||||
|
case SIGNCMD_UNPLACE:
|
||||||
|
case SIGNCMD_JUMP:
|
||||||
|
if (STRNCMP(last, "group", 5) == 0)
|
||||||
|
expand_what = EXP_SIGN_GROUPS;
|
||||||
|
else if (STRNCMP(last, "file", 4) == 0)
|
||||||
|
xp->xp_context = EXPAND_BUFFERS;
|
||||||
else
|
else
|
||||||
xp->xp_context = EXPAND_NOTHING;
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
break;
|
break;
|
||||||
|
@ -210,13 +210,16 @@ func Test_sign_completion()
|
|||||||
call assert_equal('"sign define Sign linehl=SpellBad SpellCap ' .
|
call assert_equal('"sign define Sign linehl=SpellBad SpellCap ' .
|
||||||
\ 'SpellLocal SpellRare', @:)
|
\ 'SpellLocal SpellRare', @:)
|
||||||
|
|
||||||
call writefile(['foo'], 'XsignOne')
|
call feedkeys(":sign define Sign texthl=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call writefile(['bar'], 'XsignTwo')
|
call assert_equal('"sign define Sign texthl=SpellBad SpellCap ' .
|
||||||
|
\ 'SpellLocal SpellRare', @:)
|
||||||
|
|
||||||
|
call writefile(repeat(["Sun is shining"], 30), "XsignOne")
|
||||||
|
call writefile(repeat(["Sky is blue"], 30), "XsignTwo")
|
||||||
call feedkeys(":sign define Sign icon=Xsig\<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":sign define Sign icon=Xsig\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"sign define Sign icon=XsignOne XsignTwo', @:)
|
call assert_equal('"sign define Sign icon=XsignOne XsignTwo', @:)
|
||||||
call delete('XsignOne')
|
|
||||||
call delete('XsignTwo')
|
|
||||||
|
|
||||||
|
" Test for completion of arguments to ':sign undefine'
|
||||||
call feedkeys(":sign undefine \<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":sign undefine \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"sign undefine Sign1 Sign2', @:)
|
call assert_equal('"sign undefine Sign1 Sign2', @:)
|
||||||
|
|
||||||
@ -227,17 +230,70 @@ func Test_sign_completion()
|
|||||||
call feedkeys(":sign place 1 name=\<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":sign place 1 name=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"sign place 1 name=Sign1 Sign2', @:)
|
call assert_equal('"sign place 1 name=Sign1 Sign2', @:)
|
||||||
|
|
||||||
|
edit XsignOne
|
||||||
|
sign place 1 name=Sign1 line=5
|
||||||
|
sign place 1 name=Sign1 group=g1 line=10
|
||||||
|
edit XsignTwo
|
||||||
|
sign place 1 name=Sign2 group=g2 line=15
|
||||||
|
|
||||||
|
" Test for completion of group= and file= arguments to ':sign place'
|
||||||
|
call feedkeys(":sign place 1 name=Sign1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign place 1 name=Sign1 file=XsignOne XsignTwo', @:)
|
||||||
|
call feedkeys(":sign place 1 name=Sign1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign place 1 name=Sign1 group=g1 g2', @:)
|
||||||
|
|
||||||
|
" Test for completion of arguments to 'sign place' without sign identifier
|
||||||
|
call feedkeys(":sign place \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign place buffer= file= group=', @:)
|
||||||
|
call feedkeys(":sign place file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign place file=XsignOne XsignTwo', @:)
|
||||||
|
call feedkeys(":sign place group=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign place group=g1 g2', @:)
|
||||||
|
call feedkeys(":sign place group=g1 file=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign place group=g1 file=XsignOne XsignTwo', @:)
|
||||||
|
|
||||||
|
" Test for completion of arguments to ':sign unplace'
|
||||||
call feedkeys(":sign unplace 1 \<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":sign unplace 1 \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"sign unplace 1 buffer= file= group=', @:)
|
call assert_equal('"sign unplace 1 buffer= file= group=', @:)
|
||||||
|
call feedkeys(":sign unplace 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign unplace 1 file=XsignOne XsignTwo', @:)
|
||||||
|
call feedkeys(":sign unplace 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign unplace 1 group=g1 g2', @:)
|
||||||
|
call feedkeys(":sign unplace 1 group=g2 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign unplace 1 group=g2 file=XsignOne XsignTwo', @:)
|
||||||
|
|
||||||
|
" Test for completion of arguments to ':sign list'
|
||||||
call feedkeys(":sign list \<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":sign list \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"sign list Sign1 Sign2', @:)
|
call assert_equal('"sign list Sign1 Sign2', @:)
|
||||||
|
|
||||||
|
" Test for completion of arguments to ':sign jump'
|
||||||
call feedkeys(":sign jump 1 \<C-A>\<C-B>\"\<CR>", 'tx')
|
call feedkeys(":sign jump 1 \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"sign jump 1 buffer= file= group=', @:)
|
call assert_equal('"sign jump 1 buffer= file= group=', @:)
|
||||||
|
call feedkeys(":sign jump 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign jump 1 file=XsignOne XsignTwo', @:)
|
||||||
|
call feedkeys(":sign jump 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign jump 1 group=g1 g2', @:)
|
||||||
|
|
||||||
|
" Error cases
|
||||||
|
call feedkeys(":sign here\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"sign here', @:)
|
||||||
|
call feedkeys(":sign define Sign here=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal("\"sign define Sign here=\<C-A>", @:)
|
||||||
|
call feedkeys(":sign place 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal("\"sign place 1 here=\<C-A>", @:)
|
||||||
|
call feedkeys(":sign jump 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal("\"sign jump 1 here=\<C-A>", @:)
|
||||||
|
call feedkeys(":sign here there\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal("\"sign here there\<C-A>", @:)
|
||||||
|
call feedkeys(":sign here there=\<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal("\"sign here there=\<C-A>", @:)
|
||||||
|
|
||||||
|
sign unplace * group=*
|
||||||
sign undefine Sign1
|
sign undefine Sign1
|
||||||
sign undefine Sign2
|
sign undefine Sign2
|
||||||
|
enew
|
||||||
|
call delete('XsignOne')
|
||||||
|
call delete('XsignTwo')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_sign_invalid_commands()
|
func Test_sign_invalid_commands()
|
||||||
|
@ -779,6 +779,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
939,
|
||||||
/**/
|
/**/
|
||||||
938,
|
938,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user