From 925ddb190f6f45bc0095473d0555d0b3cfe04672 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 7 Aug 2026 12:34:59 +0800 Subject: [PATCH] vim-patch:90e8cb0: runtime(sh): Fix shFunctionTwo and shFunctionFour definitions for Bash Claim e.g. "function f () { :; }" as shFunctionTwo while observing that parentheses after the function name are optional when the "function" word is used and do not delimit its body if the latter follows them in "{}" (which should not be taken for granted with limited backtracking). closes: vim/vim#20878 https://github.com/vim/vim/commit/90e8cb0094508e9e6932adcf42f5003251c47c26 Co-authored-by: Aliaksei Budavei <0x000c70@gmail.com> --- runtime/syntax/sh.vim | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index 90a712a00a..901923b0d3 100644 --- a/runtime/syntax/sh.vim +++ b/runtime/syntax/sh.vim @@ -651,9 +651,13 @@ if exists("b:is_bash") syn match shFunctionCmdOne "\%#=1^\s*\zs\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\s*()\ze\_s*\%(\%(for\|case\|select\|if\|while\|until\)\>\|\[\[\s\|((\)" skipwhite skipnl nextgroup=@shFunctionCmds contains=shFunctionParens syn match shFunctionCmdTwo "\%#=1\%(\%(\<\k\+\>\|[^()<>|&$;\t ]\+\)\+\)\@>\ze\s*\%(()\ze\)\=\_s*\%(\<\%(for\|case\|select\|if\|while\|until\)\>\|\[\[\s\|((\)" contained skipwhite skipnl nextgroup=@shFunctionCmds contains=shFunctionParens syn match shFunctionOne "\%#=1^\s*\zs\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\s*()\ze\_s*{" skipwhite skipnl nextgroup=shFunctionExpr contains=shFunctionParens - syn match shFunctionTwo "\%#=1\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\ze\s*\%(()\ze\)\=\_s*{" contained skipwhite skipnl nextgroup=shFunctionExpr contains=shFunctionParens syn match shFunctionThree "\%#=1^\s*\zs\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\s*()\ze\_s*((\@!" skipwhite skipnl nextgroup=shFunctionSubSh contains=shFunctionParens - syn match shFunctionFour "\%#=1\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\ze\s*\%(\%(()\ze\)\=\)\@>\_s*((\@!" contained skipwhite skipnl nextgroup=shFunctionSubSh contains=shFunctionParens + " Proof against future changes by inducing priority-driven "backtracking" + " between shFunctionFour (goes before) and shFunctionTwo (goes after) so + " that e.g. "function f () {}" is still claimed by shFunctionTwo (observe + " "f[[:blank:]]()"). + syn match shFunctionFour "\%#=1\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\ze\%(\%(\s*()\ze\)\=\)\@>\_s*((\@!" contained skipwhite skipnl nextgroup=shFunctionSubSh contains=shFunctionParens + syn match shFunctionTwo "\%#=1\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\ze\%(\%(\s*()\ze\)\=\)\@>\_s*{" contained skipwhite skipnl nextgroup=shFunctionExpr contains=shFunctionParens " Claim empty array assignments. syn match shArrayEmptyDecl "\%#=1\ze\%(\<\h\w*=\)\@>()" transparent nextgroup=shVariable " Claim commented out function declaration headers.