]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.1.0939: no completion for sign group names v8.1.0939
authorBram Moolenaar <Bram@vim.org>
Sun, 17 Feb 2019 13:50:25 +0000 (14:50 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 17 Feb 2019 13:50:25 +0000 (14:50 +0100)
Problem:    No completion for sign group names.
Solution:   Add completion for sign group names and buffer names. (Yegappan
            Lakshmanan, closes #3980)

src/sign.c
src/testdir/test_signs.vim
src/version.c

index 44b638caff96c9c81f4a07475ef31eea75872814..cc519010726fc488c2f50ddeca2f17e10f1f4164 100644 (file)
@@ -1767,10 +1767,58 @@ 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.
@@ -1778,9 +1826,6 @@ static enum
     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;
index 49bd986c35ac700f2650cdf8fb6d5a8f3a5aa6b2..426998d6d7af378ee2d4e85bd0c4d9d06521f30a 100644 (file)
@@ -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()
index df3aa4813c49ca90d1773c7533cbb682ad474064..06500bd7906b3ae4b31b65de08131f8e02a9a8bb 100644 (file)
@@ -779,6 +779,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    939,
 /**/
     938,
 /**/