]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0886: :set completion works for an invalid sub-option name v9.2.0886
authorHirohito Higashi <h.east.727@gmail.com>
Fri, 31 Jul 2026 18:48:43 +0000 (18:48 +0000)
committerChristian Brabandt <cb@256bit.org>
Fri, 31 Jul 2026 18:48:43 +0000 (18:48 +0000)
Problem:  Completing the value after a sub-option name also works when the
          name merely ends in a valid one, e.g. "invalid_close:".
Solution: Require the name to start the option value or to follow a comma.
          Compute the length of the name at compile time.

closes: #20893

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/optionstr.c
src/testdir/test_options.vim
src/version.c

index b656288cb50aa0ae9702242acc107b131991eef6..59a5a7e1d1bd43d359431004dd4ac89b5052eed5 100644 (file)
@@ -1132,14 +1132,28 @@ did_set_ambiwidth(optset_T *args UNUSED)
 }
 
 #if defined(FEAT_TABPANEL) || defined(FEAT_DIFF) || defined(FEAT_PROP_POPUP)
+
+// "name" must be a string literal, the length is computed at compile time.
+# define completing_value_for_subopt(args, name) \
+         completing_value_for_subopt_len(args, name, (int)STRLEN_LITERAL(name))
+
+/*
+ * Return true when completing the value of the sub-option "name" with length
+ * "len", e.g. the value after "close:" in 'completepopup'.
+ */
     static bool
-completing_value_for_subopt(optexpand_T *args, char *name_suffix)
+completing_value_for_subopt_len(optexpand_T *args, char *name, int len)
 {
-    char_u *colon = args->oe_xp->xp_pattern - 1;
-    int len = (int)STRLEN(name_suffix);
+    char_u  *colon = args->oe_xp->xp_pattern - 1;
+    int            off = (int)(colon - args->oe_set_arg);
+
+    if (off < len)
+       return false;
+    // The name must follow a comma when it does not start the option value.
+    if (off > len && *(colon - len - 1) != ',')
+       return false;
 
-    return colon - args->oe_set_arg >= len
-          && STRNCMP(colon - len, name_suffix, len) == 0;
+    return STRNCMP(colon - len, name, len) == 0;
 }
 #endif
 
index b1201eb39727571d7ba45e574e65057c234a30d1..93d0e61442f7d05476bbd63391dbf94d0c2a0c5c 100644 (file)
@@ -663,6 +663,12 @@ func Test_set_completion_string_values()
   call feedkeys(":set completepopup=height:10,align:\<Tab>\<C-B>\"\<CR>", 'xt')
   call assert_equal('"set completepopup=height:10,align:item', @:)
   call assert_equal([], getcompletion('set completepopup=bogusname:', 'cmdline'))
+  " a name ending in a known sub-option name is not a sub-option
+  call assert_equal([], getcompletion('set completepopup=invalid_close:', 'cmdline'))
+  call assert_equal([], getcompletion('set completepopup=xborder:', 'cmdline'))
+  call assert_equal([], getcompletion('set completepopup=xhighlight:', 'cmdline'))
+  call assert_equal(['on', 'off'],
+        \ getcompletion('set completepopup=border:on,close:', 'cmdline'))
   call assert_equal(['on', 'off'], getcompletion('set completepopup=close:', 'cmdline'))
   call assert_equal(['on', 'off'], getcompletion('set completepopup=close:o', 'cmdline'))
   call assert_equal(['off'], getcompletion('set previewpopup=close:of', 'cmdline'))
@@ -687,6 +693,8 @@ func Test_set_completion_string_values()
   " diffopt: special handling of algorithm:<alg_list> and inline:<inline_type>
   call assert_equal('filler', getcompletion('set diffopt+=', 'cmdline')[0])
   call assert_equal([], getcompletion('set diffopt+=iblank,foldcolumn:', 'cmdline'))
+  call assert_equal([], getcompletion('set diffopt+=Xalgorithm:', 'cmdline'))
+  call assert_equal([], getcompletion('set diffopt+=iblank,Xinline:', 'cmdline'))
   call assert_equal('patience', getcompletion('set diffopt+=iblank,algorithm:pat*', 'cmdline')[0])
   call assert_equal('char', getcompletion('set diffopt+=iwhite,inline:ch*', 'cmdline')[0])
 
index 55f755f23f656171cad1183ec57f8fa3b01d8211..59e9c7bb4bd7bd3ed1cf099e77093e415aa8748c 100644 (file)
@@ -758,6 +758,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    886,
 /**/
     885,
 /**/