]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1187: matchparen plugin wrong highlights shell case statement v9.1.1187
authorChristian Brabandt <cb@256bit.org>
Sun, 9 Mar 2025 07:40:33 +0000 (08:40 +0100)
committerChristian Brabandt <cb@256bit.org>
Sun, 9 Mar 2025 07:40:33 +0000 (08:40 +0100)
Problem:  matchparen plugin wrong highlights shell case statement
          (Swudu Susuwu)
Solution: return early, if we are in a shSnglCase syntax element

The shell syntax element "case $var in foobar)" uses closing parenthesis
but there is no corresponding opening parenthesis for that syntax
element. However matchparen is not aware of such things and will happily
try to match just the next opening parenthesis.

So let's just add a way to opt out for such cases. In this case, use the
syntax state to check if the closing parenthesis belongs to the syntax
item "shSnglCase" and if it is, do not try to find a corresponding
opening parenthesis.

Since inspecting the syntax state might be expensive, put the whole
check behind a filetype test, so that matchparen will only perform this
particular check, when it knows the current buffer is a "sh" filetype.

fixes: #16801
closes: #16831

Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/plugin/matchparen.vim
src/testdir/dumps/Test_matchparen_sh_case_1.dump [new file with mode: 0644]
src/testdir/test_plugin_matchparen.vim
src/version.c

index 661a34b578ec5c20c4ab92702ea0fbc187b34d89..2fa30b12ecda5c97466d3ddba805a3bda3f52208 100644 (file)
@@ -1,6 +1,6 @@
 " Vim plugin for showing matching parens
 " Maintainer:  The Vim Project <https://github.com/vim/vim>
-" Last Change: 2024 May 18
+" Last Change: 2025 Mar 08
 " Former Maintainer:   Bram Moolenaar <Bram@vim.org>
 
 " Exit quickly when:
@@ -110,6 +110,17 @@ func s:Highlight_Matching_Pair()
   if !has("syntax") || !exists("g:syntax_on")
     let s_skip = "0"
   else
+    " do not attempt to match when the syntax item where the cursor is
+    " indicates there does not exist a matching parenthesis, e.g. for shells
+    " case statement: "case $var in foobar)"
+    "
+    " add the check behind a filetype check, so it only needs to be
+    " evaluated for certain filetypes
+    if ['sh']->index(&filetype) >= 0 &&
+        \ synstack(".", col("."))->indexof({_, id -> synIDattr(id, "name")
+        \ =~? "shSnglCase"}) >= 0
+      return
+    endif
     " Build an expression that detects whether the current cursor position is
     " in certain syntax types (string, comment, etc.), for use as
     " searchpairpos()'s skip argument.
diff --git a/src/testdir/dumps/Test_matchparen_sh_case_1.dump b/src/testdir/dumps/Test_matchparen_sh_case_1.dump
new file mode 100644 (file)
index 0000000..7e7a2a3
--- /dev/null
@@ -0,0 +1,10 @@
+|#+0#0000e05#ffffff0|!|/|b|i|n|/|s|h| +0#0000000&@65
+|S+0#00e0e07&|U|S|U|W|U|_|P|R|I|N|T|(|)| |(| +0#0000000&@58
+@2|c+0#af5f00255&|a|s|e| +0#0000000&|"+0#af5f00255&|$+0#e000e06&|{|L|E|V|E|L|}|"+0#af5f00255&| +0#0000000&|i+0#af5f00255&|n| +0#0000000&@54
+@4|"+0#af5f00255&|$+0#e000e06&|S|U|S|U|W|U|_|S|H|_|N|O|T|I|C|E|"+0#af5f00255&>)| +0#0000000&@50
+@4|$+0#e000e06&|{|S|U|S|U|W|U|_|S|}| +0#0000000&|&+0#af5f00255&@1| +0#0000000&|r+0#af5f00255&|e|t|u|r|n| +0#0000000&|1+0#e000002&| +0#0000000&@47
+@2|;+0#af5f00255&@1| +0#0000000&@70
+@4|"+0#af5f00255&|$+0#e000e06&|S|U|S|U|W|U|_|S|H|_|D|E|B|U|G|"+0#af5f00255&|)| +0#0000000&@51
+@4|(+0#e000e06&|!+0#af5f00255&| +0#0000000&|$+0#e000e06&|{|S|U|S|U|W|U|_|V|E|R|B|O|S|E|}|)| +0#0000000&|&+0#af5f00255&@1| +0#0000000&|r+0#af5f00255&|e|t|u|r|n| +0#0000000&|1+0#e000002&| +0#0000000&@37
+@2|;+0#af5f00255&@1| +0#0000000&@70
+@57|4|,|2|4| @9|T|o|p| 
index 49d35108a96bac47b15ef922d9db43a5f6967756..23491abf498e382d6bfc96d116dfdef2be53b2d2 100644 (file)
@@ -139,4 +139,36 @@ func Test_matchparen_mbyte()
   call StopVimInTerminal(buf)
 endfunc
 
+" Test for ignoring certain parenthesis
+func Test_matchparen_ignore_sh_case()
+  CheckScreendump
+
+  let lines =<< trim END
+    source $VIMRUNTIME/plugin/matchparen.vim
+    set ft=sh
+    call setline(1, [
+          \ '#!/bin/sh',
+          \ 'SUSUWU_PRINT() (',
+          \ '  case "${LEVEL}" in',
+          \ '    "$SUSUWU_SH_NOTICE")',
+          \ '    ${SUSUWU_S} && return 1',
+          \ '  ;;',
+          \ '    "$SUSUWU_SH_DEBUG")',
+          \ '    (! ${SUSUWU_VERBOSE}) && return 1',
+          \ '  ;;',
+          \ '  esac',
+          \ '  # snip',
+          \ ')'
+          \ ])
+    call cursor(4, 26)
+  END
+
+  let filename = 'Xmatchparen_sh'
+  call writefile(lines, filename, 'D')
+
+  let buf = RunVimInTerminal('-S '.filename, #{rows: 10})
+  call VerifyScreenDump(buf, 'Test_matchparen_sh_case_1', {})
+  call StopVimInTerminal(buf)
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 5536a9b48a63443a80916f96054cb757ff81f08d..7851f79728d6eb55fbad25adc2e635943a01c5a6 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1187,
 /**/
     1186,
 /**/