summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-02-17 14:50:25 +0100
committerBram Moolenaar <Bram@vim.org>2019-02-17 14:50:25 +0100
commit3678f65d43d10b36dc62738aab2f341fa1e18a32 (patch)
tree7a590de683f62b5c0bc289902cf8c7dab11ad1d1
parent21edde87426eeeaf46e118a137a7fa0e86ad167e (diff)
downloadvim-git-3678f65d43d10b36dc62738aab2f341fa1e18a32.tar.gz
patch 8.1.0939: no completion for sign group namesv8.1.0939
Problem: No completion for sign group names. Solution: Add completion for sign group names and buffer names. (Yegappan Lakshmanan, closes #3980)
-rw-r--r--src/sign.c128
-rw-r--r--src/testdir/test_signs.vim66
-rw-r--r--src/version.c2
3 files changed, 154 insertions, 42 deletions
diff --git a/src/sign.c b/src/sign.c
index 44b638caf..cc5190107 100644
--- a/src/sign.c
+++ b/src/sign.c
@@ -1767,20 +1767,65 @@ static enum
EXP_SUBCMD, // expand :sign sub-commands
EXP_DEFINE, // expand :sign define {name} args
EXP_PLACE, // expand :sign place {id} args
+ EXP_LIST, // expand :sign place args
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;
/*
+ * 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
* expansion.
*/
char_u *
get_sign_name(expand_T *xp UNUSED, int idx)
{
- sign_T *sp;
- int current_idx;
-
switch (expand_what)
{
case EXP_SUBCMD:
@@ -1802,18 +1847,23 @@ get_sign_name(expand_T *xp UNUSED, int 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:
{
char *unplace_arg[] = { "group=", "file=", "buffer=", NULL };
return (char_u *)unplace_arg[idx];
}
case EXP_SIGN_NAMES:
- // 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 get_nth_sign_name(idx);
+ case EXP_SIGN_GROUPS:
+ return get_nth_sign_group_name(idx);
default:
return NULL;
}
@@ -1848,28 +1898,6 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
// |
// begin_subcmd_args
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
@@ -1878,6 +1906,7 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
// p
// Loop until reaching last argument.
+ p = begin_subcmd_args;
do
{
p = skipwhite(p);
@@ -1900,7 +1929,19 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
expand_what = EXP_DEFINE;
break;
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;
case SIGNCMD_JUMP:
case SIGNCMD_UNPLACE:
@@ -1917,17 +1958,30 @@ set_context_in_sign_cmd(expand_T *xp, char_u *arg)
switch (cmd_idx)
{
case SIGNCMD_DEFINE:
- if (STRNCMP(last, "texthl", p - last) == 0
- || STRNCMP(last, "linehl", p - last) == 0)
+ if (STRNCMP(last, "texthl", 6) == 0
+ || STRNCMP(last, "linehl", 6) == 0)
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;
else
xp->xp_context = EXPAND_NOTHING;
break;
case SIGNCMD_PLACE:
- if (STRNCMP(last, "name", p - last) == 0)
+ if (STRNCMP(last, "name", 4) == 0)
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
xp->xp_context = EXPAND_NOTHING;
break;
diff --git a/src/testdir/test_signs.vim b/src/testdir/test_signs.vim
index 49bd986c3..426998d6d 100644
--- a/src/testdir/test_signs.vim
+++ b/src/testdir/test_signs.vim
@@ -210,13 +210,16 @@ func Test_sign_completion()
call assert_equal('"sign define Sign linehl=SpellBad SpellCap ' .
\ 'SpellLocal SpellRare', @:)
- call writefile(['foo'], 'XsignOne')
- call writefile(['bar'], 'XsignTwo')
+ call feedkeys(":sign define Sign texthl=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
+ 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 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 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 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 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 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 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 Sign2
+ enew
+ call delete('XsignOne')
+ call delete('XsignTwo')
endfunc
func Test_sign_invalid_commands()
diff --git a/src/version.c b/src/version.c
index df3aa4813..06500bd79 100644
--- a/src/version.c
+++ b/src/version.c
@@ -780,6 +780,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 939,
+/**/
938,
/**/
937,