Skip to content

Commit 3678f65

Browse files
committed
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)
1 parent 21edde8 commit 3678f65

3 files changed

Lines changed: 154 additions & 42 deletions

File tree

src/sign.c

Lines changed: 91 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,20 +1767,65 @@ static enum
17671767
EXP_SUBCMD, // expand :sign sub-commands
17681768
EXP_DEFINE, // expand :sign define {name} args
17691769
EXP_PLACE, // expand :sign place {id} args
1770+
EXP_LIST, // expand :sign place args
17701771
EXP_UNPLACE, // expand :sign unplace"
1771-
EXP_SIGN_NAMES // expand with name of placed signs
1772+
EXP_SIGN_NAMES, // expand with name of placed signs
1773+
EXP_SIGN_GROUPS // expand with name of placed sign groups
17721774
} expand_what;
17731775

1776+
/*
1777+
* Return the n'th sign name (used for command line completion)
1778+
*/
1779+
static char_u *
1780+
get_nth_sign_name(int idx)
1781+
{
1782+
int current_idx;
1783+
sign_T *sp;
1784+
1785+
// Complete with name of signs already defined
1786+
current_idx = 0;
1787+
for (sp = first_sign; sp != NULL; sp = sp->sn_next)
1788+
if (current_idx++ == idx)
1789+
return sp->sn_name;
1790+
return NULL;
1791+
}
1792+
1793+
/*
1794+
* Return the n'th sign group name (used for command line completion)
1795+
*/
1796+
static char_u *
1797+
get_nth_sign_group_name(int idx)
1798+
{
1799+
int current_idx;
1800+
int todo;
1801+
hashitem_T *hi;
1802+
signgroup_T *group;
1803+
1804+
// Complete with name of sign groups already defined
1805+
current_idx = 0;
1806+
todo = (int)sg_table.ht_used;
1807+
for (hi = sg_table.ht_array; todo > 0; ++hi)
1808+
{
1809+
if (!HASHITEM_EMPTY(hi))
1810+
{
1811+
--todo;
1812+
if (current_idx++ == idx)
1813+
{
1814+
group = HI2SG(hi);
1815+
return group->sg_name;
1816+
}
1817+
}
1818+
}
1819+
return NULL;
1820+
}
1821+
17741822
/*
17751823
* Function given to ExpandGeneric() to obtain the sign command
17761824
* expansion.
17771825
*/
17781826
char_u *
17791827
get_sign_name(expand_T *xp UNUSED, int idx)
17801828
{
1781-
sign_T *sp;
1782-
int current_idx;
1783-
17841829
switch (expand_what)
17851830
{
17861831
case EXP_SUBCMD:
@@ -1802,18 +1847,23 @@ get_sign_name(expand_T *xp UNUSED, int idx)
18021847
};
18031848
return (char_u *)place_arg[idx];
18041849
}
1850+
case EXP_LIST:
1851+
{
1852+
char *list_arg[] =
1853+
{
1854+
"group=", "file=", "buffer=", NULL
1855+
};
1856+
return (char_u *)list_arg[idx];
1857+
}
18051858
case EXP_UNPLACE:
18061859
{
18071860
char *unplace_arg[] = { "group=", "file=", "buffer=", NULL };
18081861
return (char_u *)unplace_arg[idx];
18091862
}
18101863
case EXP_SIGN_NAMES:
1811-
// Complete with name of signs already defined
1812-
current_idx = 0;
1813-
for (sp = first_sign; sp != NULL; sp = sp->sn_next)
1814-
if (current_idx++ == idx)
1815-
return sp->sn_name;
1816-
return NULL;
1864+
return get_nth_sign_name(idx);
1865+
case EXP_SIGN_GROUPS:
1866+
return get_nth_sign_group_name(idx);
18171867
default:
18181868
return NULL;
18191869
}
@@ -1848,28 +1898,6 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
18481898
// |
18491899
// begin_subcmd_args
18501900
begin_subcmd_args = skipwhite(end_subcmd);
1851-
p = skiptowhite(begin_subcmd_args);
1852-
if (*p == NUL)
1853-
{
1854-
//
1855-
// Expand first argument of subcmd when possible.
1856-
// For ":jump {id}" and ":unplace {id}", we could
1857-
// possibly expand the ids of all signs already placed.
1858-
//
1859-
xp->xp_pattern = begin_subcmd_args;
1860-
switch (cmd_idx)
1861-
{
1862-
case SIGNCMD_LIST:
1863-
case SIGNCMD_UNDEFINE:
1864-
// :sign list <CTRL-D>
1865-
// :sign undefine <CTRL-D>
1866-
expand_what = EXP_SIGN_NAMES;
1867-
break;
1868-
default:
1869-
xp->xp_context = EXPAND_NOTHING;
1870-
}
1871-
return;
1872-
}
18731901

18741902
// expand last argument of subcmd
18751903

@@ -1878,6 +1906,7 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
18781906
// p
18791907

18801908
// Loop until reaching last argument.
1909+
p = begin_subcmd_args;
18811910
do
18821911
{
18831912
p = skipwhite(p);
@@ -1900,7 +1929,19 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
19001929
expand_what = EXP_DEFINE;
19011930
break;
19021931
case SIGNCMD_PLACE:
1903-
expand_what = EXP_PLACE;
1932+
// List placed signs
1933+
if (VIM_ISDIGIT(*begin_subcmd_args))
1934+
// :sign place {id} {args}...
1935+
expand_what = EXP_PLACE;
1936+
else
1937+
// :sign place {args}...
1938+
expand_what = EXP_LIST;
1939+
break;
1940+
case SIGNCMD_LIST:
1941+
case SIGNCMD_UNDEFINE:
1942+
// :sign list <CTRL-D>
1943+
// :sign undefine <CTRL-D>
1944+
expand_what = EXP_SIGN_NAMES;
19041945
break;
19051946
case SIGNCMD_JUMP:
19061947
case SIGNCMD_UNPLACE:
@@ -1917,17 +1958,30 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
19171958
switch (cmd_idx)
19181959
{
19191960
case SIGNCMD_DEFINE:
1920-
if (STRNCMP(last, "texthl", p - last) == 0
1921-
|| STRNCMP(last, "linehl", p - last) == 0)
1961+
if (STRNCMP(last, "texthl", 6) == 0
1962+
|| STRNCMP(last, "linehl", 6) == 0)
19221963
xp->xp_context = EXPAND_HIGHLIGHT;
1923-
else if (STRNCMP(last, "icon", p - last) == 0)
1964+
else if (STRNCMP(last, "icon", 4) == 0)
19241965
xp->xp_context = EXPAND_FILES;
19251966
else
19261967
xp->xp_context = EXPAND_NOTHING;
19271968
break;
19281969
case SIGNCMD_PLACE:
1929-
if (STRNCMP(last, "name", p - last) == 0)
1970+
if (STRNCMP(last, "name", 4) == 0)
19301971
expand_what = EXP_SIGN_NAMES;
1972+
else if (STRNCMP(last, "group", 5) == 0)
1973+
expand_what = EXP_SIGN_GROUPS;
1974+
else if (STRNCMP(last, "file", 4) == 0)
1975+
xp->xp_context = EXPAND_BUFFERS;
1976+
else
1977+
xp->xp_context = EXPAND_NOTHING;
1978+
break;
1979+
case SIGNCMD_UNPLACE:
1980+
case SIGNCMD_JUMP:
1981+
if (STRNCMP(last, "group", 5) == 0)
1982+
expand_what = EXP_SIGN_GROUPS;
1983+
else if (STRNCMP(last, "file", 4) == 0)
1984+
xp->xp_context = EXPAND_BUFFERS;
19311985
else
19321986
xp->xp_context = EXPAND_NOTHING;
19331987
break;

src/testdir/test_signs.vim

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,16 @@ func Test_sign_completion()
210210
call assert_equal('"sign define Sign linehl=SpellBad SpellCap ' .
211211
\ 'SpellLocal SpellRare', @:)
212212

213-
call writefile(['foo'], 'XsignOne')
214-
call writefile(['bar'], 'XsignTwo')
213+
call feedkeys(":sign define Sign texthl=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
214+
call assert_equal('"sign define Sign texthl=SpellBad SpellCap ' .
215+
\ 'SpellLocal SpellRare', @:)
216+
217+
call writefile(repeat(["Sun is shining"], 30), "XsignOne")
218+
call writefile(repeat(["Sky is blue"], 30), "XsignTwo")
215219
call feedkeys(":sign define Sign icon=Xsig\<C-A>\<C-B>\"\<CR>", 'tx')
216220
call assert_equal('"sign define Sign icon=XsignOne XsignTwo', @:)
217-
call delete('XsignOne')
218-
call delete('XsignTwo')
219221

222+
" Test for completion of arguments to ':sign undefine'
220223
call feedkeys(":sign undefine \<C-A>\<C-B>\"\<CR>", 'tx')
221224
call assert_equal('"sign undefine Sign1 Sign2', @:)
222225

@@ -227,17 +230,70 @@ func Test_sign_completion()
227230
call feedkeys(":sign place 1 name=\<C-A>\<C-B>\"\<CR>", 'tx')
228231
call assert_equal('"sign place 1 name=Sign1 Sign2', @:)
229232

233+
edit XsignOne
234+
sign place 1 name=Sign1 line=5
235+
sign place 1 name=Sign1 group=g1 line=10
236+
edit XsignTwo
237+
sign place 1 name=Sign2 group=g2 line=15
238+
239+
" Test for completion of group= and file= arguments to ':sign place'
240+
call feedkeys(":sign place 1 name=Sign1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
241+
call assert_equal('"sign place 1 name=Sign1 file=XsignOne XsignTwo', @:)
242+
call feedkeys(":sign place 1 name=Sign1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
243+
call assert_equal('"sign place 1 name=Sign1 group=g1 g2', @:)
244+
245+
" Test for completion of arguments to 'sign place' without sign identifier
246+
call feedkeys(":sign place \<C-A>\<C-B>\"\<CR>", 'tx')
247+
call assert_equal('"sign place buffer= file= group=', @:)
248+
call feedkeys(":sign place file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
249+
call assert_equal('"sign place file=XsignOne XsignTwo', @:)
250+
call feedkeys(":sign place group=\<C-A>\<C-B>\"\<CR>", 'tx')
251+
call assert_equal('"sign place group=g1 g2', @:)
252+
call feedkeys(":sign place group=g1 file=\<C-A>\<C-B>\"\<CR>", 'tx')
253+
call assert_equal('"sign place group=g1 file=XsignOne XsignTwo', @:)
254+
255+
" Test for completion of arguments to ':sign unplace'
230256
call feedkeys(":sign unplace 1 \<C-A>\<C-B>\"\<CR>", 'tx')
231257
call assert_equal('"sign unplace 1 buffer= file= group=', @:)
232-
258+
call feedkeys(":sign unplace 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
259+
call assert_equal('"sign unplace 1 file=XsignOne XsignTwo', @:)
260+
call feedkeys(":sign unplace 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
261+
call assert_equal('"sign unplace 1 group=g1 g2', @:)
262+
call feedkeys(":sign unplace 1 group=g2 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
263+
call assert_equal('"sign unplace 1 group=g2 file=XsignOne XsignTwo', @:)
264+
265+
" Test for completion of arguments to ':sign list'
233266
call feedkeys(":sign list \<C-A>\<C-B>\"\<CR>", 'tx')
234267
call assert_equal('"sign list Sign1 Sign2', @:)
235268

269+
" Test for completion of arguments to ':sign jump'
236270
call feedkeys(":sign jump 1 \<C-A>\<C-B>\"\<CR>", 'tx')
237271
call assert_equal('"sign jump 1 buffer= file= group=', @:)
272+
call feedkeys(":sign jump 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
273+
call assert_equal('"sign jump 1 file=XsignOne XsignTwo', @:)
274+
call feedkeys(":sign jump 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
275+
call assert_equal('"sign jump 1 group=g1 g2', @:)
238276

277+
" Error cases
278+
call feedkeys(":sign here\<C-A>\<C-B>\"\<CR>", 'tx')
279+
call assert_equal('"sign here', @:)
280+
call feedkeys(":sign define Sign here=\<C-A>\<C-B>\"\<CR>", 'tx')
281+
call assert_equal("\"sign define Sign here=\<C-A>", @:)
282+
call feedkeys(":sign place 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
283+
call assert_equal("\"sign place 1 here=\<C-A>", @:)
284+
call feedkeys(":sign jump 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
285+
call assert_equal("\"sign jump 1 here=\<C-A>", @:)
286+
call feedkeys(":sign here there\<C-A>\<C-B>\"\<CR>", 'tx')
287+
call assert_equal("\"sign here there\<C-A>", @:)
288+
call feedkeys(":sign here there=\<C-A>\<C-B>\"\<CR>", 'tx')
289+
call assert_equal("\"sign here there=\<C-A>", @:)
290+
291+
sign unplace * group=*
239292
sign undefine Sign1
240293
sign undefine Sign2
294+
enew
295+
call delete('XsignOne')
296+
call delete('XsignTwo')
241297
endfunc
242298

243299
func Test_sign_invalid_commands()

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,8 @@ static char *(features[]) =
779779

780780
static int included_patches[] =
781781
{ /* Add new patch number below this line */
782+
/**/
783+
939,
782784
/**/
783785
938,
784786
/**/

0 commit comments

Comments
 (0)