Commit: runtime(sh): add syntax highlighting support for ${ cmd;} and ${|cmd;}

2 views
Skip to first unread message

Christian Brabandt

unread,
Aug 23, 2025, 11:15:15 AMAug 23
to vim...@googlegroups.com
runtime(sh): add syntax highlighting support for ${ cmd;} and ${|cmd;}

Commit: https://github.com/vim/vim/commit/e06d81fe675794d6e849cfa78e31a78c8001bbe5
Author: Kevin Pulo <kevin...@mongodb.com>
Date: Sat Aug 23 17:07:44 2025 +0200

runtime(sh): add syntax highlighting support for ${ cmd;} and ${|cmd;}

bash 5.3 (released July 2025) added support for ${ cmd;} and
${|cmd;} style command substitution, which is similar (but not
identical) to ksh/mksh.

closes: #18084

Signed-off-by: Kevin Pulo <kevin...@mongodb.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim
index 9cee161ac..8dd62566c 100644
--- a/runtime/syntax/sh.vim
+++ b/runtime/syntax/sh.vim
@@ -16,7 +16,8 @@
" 2025 May 10 improve wildcard character class lists
" 2025 May 21 improve supported KornShell features
" 2025 Jun 16 change how sh_fold_enabled is reset (#17557)
-" 2025 Jul 18 properly delete :commands #17785
+" 2025 Jul 18 properly delete :commands (#17785)
+" 2025 Aug 23 bash: add support for ${ cmd;} and ${|cmd;} (#18084)
" }}}
" Version: 208
" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
@@ -474,6 +475,9 @@ if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")
if exists("b:is_mksh") || exists("b:generic_korn")
syn region shValsub matchgroup=shCmdSubRegion start="\${|" skip='\\\|\.' end="}" contains=@shCommandSubList
endif
+ elseif exists("b:is_bash")
+ syn region shSubshare matchgroup=shCmdSubRegion start="\${\ze[
]" skip='\\\|\.' end="\zs[;
][
]*}" contains=@shCommandSubList
+ syn region shValsub matchgroup=shCmdSubRegion start="\${|" skip='\\\|\.' end="[;
][
]*}" contains=@shCommandSubList
endif
syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\|\.' end="))" contains=@shArithList
syn region shArithmetic matchgroup=shArithRegion start="\$\[" skip='\\\|\.' end="\]" contains=@shArithList
@@ -677,6 +681,8 @@ if exists("b:is_kornshell") && !exists("b:is_ksh88")
else
syn region shDeref matchgroup=PreProc start="\${\ze[^
<]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart
endif
+elseif exists("b:is_bash")
+ syn region shDeref matchgroup=PreProc start="\${\ze[^
|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart
else
syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart
endif
diff --git a/runtime/syntax/testdir/dumps/sh_bash_00.dump b/runtime/syntax/testdir/dumps/sh_bash_00.dump
new file mode 100644
index 000000000..85966ebd7
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/sh_bash_00.dump
@@ -0,0 +1,20 @@
+>#+0#0000e05#ffffff0|!|/|b|i|n|/|b|a|s|h| +0#0000000&@63
+@75
+|#+0#0000e05&| |b|a|s|h| |5|.|3|+| |s|u|p@1|o|r|t|s| |c|o|m@1|a|n|d| |s|u|b|s|t|i|t|u|t|i|o|n| |t|h|a|t| |i|s| |v|e|r|y| |s|i|m|i|l|a|r| +0#0000000&@12
+|#+0#0000e05&| |(|b|u|t| |n|o|t| |i|d|e|n|t|i|c|a|l|)| |t|o| |k|s|h|/|m|k|s|h|.| +0#0000000&@40
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|o|n|e|;+0#e000e06&|}| +0#0000000&@56
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|t|w|o| +0#0000000&@58
+|}+0#e000e06&| +0#0000000&@73
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| +0#0000000&@67
+|e+0#af5f00255&|c|h|o| +0#e000002&|t|h|r|e@1| @5|;+0#e000e06&|}| +0#0000000&@56
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|f+0#e000002&|o|u|r|'+0#af5f00255&|;+0#e000e06&| |}| +0#0000000&@52
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|f+0#e000002&|i|v|e|'+0#af5f00255&| +0#e000002&|;+0#e000e06&|}| +0#0000000&@52
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|s+0#e000002&|i|x|'+0#af5f00255&| +0#0000000&@56
+|}+0#e000e06&| +0#0000000&@73
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|s+0#e000002&|e|v|e|n|'+0#af5f00255&| +0#e000002&@3|;+0#e000e06&|}| +0#0000000&@48
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|e+0#e000002&|i|g|h|t|'+0#af5f00255&|;+0#e000e06&| @2|}| +0#0000000&@49
+|t+0#af5f00255&|y|p|e|s|e|t| +0#e000e06&|n+0#00e0e07&|i|n|e|=+0#0000000&|$+0#e000e06&|{| |p+0#af5f00255&|w|d|;| +0#e000e06&|}| +0#0000000&@52
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|n+0#e000002&|i|n|e|'+0#af5f00255&| +0#e000002&|;+0#e000e06&| | +0#0000000&@52
+| +0#e000e06&|}| +0#0000000&@72
+@75
+|i|s|_|b|a|s|h|:| |1|,| @45|1|,|1| @10|T|o|p|
diff --git a/runtime/syntax/testdir/dumps/sh_bash_01.dump b/runtime/syntax/testdir/dumps/sh_bash_01.dump
new file mode 100644
index 000000000..18961a798
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/sh_bash_01.dump
@@ -0,0 +1,20 @@
+|e+0#af5f00255#ffffff0|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|s+0#e000002&|e|v|e|n|'+0#af5f00255&| +0#e000002&@3|;+0#e000e06&|}| +0#0000000&@48
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|e+0#e000002&|i|g|h|t|'+0#af5f00255&|;+0#e000e06&| @2|}| +0#0000000&@49
+|t+0#af5f00255&|y|p|e|s|e|t| +0#e000e06&|n+0#00e0e07&|i|n|e|=+0#0000000&|$+0#e000e06&|{| |p+0#af5f00255&|w|d|;| +0#e000e06&|}| +0#0000000&@52
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{| |e+0#af5f00255&|c|h|o| +0#e000002&|'+0#af5f00255&|n+0#e000002&|i|n|e|'+0#af5f00255&| +0#e000002&|;+0#e000e06&| | +0#0000000&@52
+| +0#e000e06&|}| +0#0000000&@72
+> @74
+|v+0#e000e06&|a|l|s|u|b|f|u|n|c|(|)| |{| +0#0000000&@60
+| +0#e000e06&@7|R|E|P|L|Y|=+0#af5f00255&|$+0#e000e06&|1| +0#0000000&@58
+|}+0#e000e06&| +0#0000000&@73
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|{|||v|a|l|s|u|b|f|u|n|c| |t|e|n|;|}| +0#0000000&@50
+|e+0#af5f00255&|c|h|o| +0#e000002&|"+0#af5f00255&|$+0#e000e06&|{|||v|a|l|s|u|b|f|u|n|c| |e|l|e|v|e|n|;| |}|"+0#af5f00255&| +0#0000000&@44
+|p+0#af5f00255&|r|i|n|t|f| +0#e000e06&|'+0#af5f00255&|%+0#e000002&|s|\|n|'+0#af5f00255&| +0#e000e06&|"+0#af5f00255&|$+0#e000e06&|{|||v|a|l|s|u|b|f|u|n|c| |t|w|e|l|v|e| @4|;|}|"+0#af5f00255&| +0#0000000&@31
+|u+0#00e0e07&|n|l|u|c|k|y|=+0#0000000&|$+0#e000e06&|{||+0#af5f00255&|v+0#e000e06&|a|l|s|u|b|f|u|n|c| |t|h|i|r|t|e@1|n| +0#0000000&@44
+|}+0#e000e06&| +0#0000000&@73
+|t+0#af5f00255&|y|p|e|s|e|t| +0#e000e06&|n+0#00e0e07&|o|t|a|f|l|o|a|t|=+0#0000000&|$+0#e000e06&|{||+0#af5f00255&|v+0#e000e06&|a|l|s|u|b|f|u|n|c| |n|o|t|a|n|u|m|b|e|r| @5|;+0#af5f00255&| +0#e000e06&| +0#0000000&@24
+| +0#e000e06&|}| +0#0000000&@72
+|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|u|n|l|u|c|k|y| +0#e000002&|$+0#e000e06&|n|o|t|a|n|u|m|b|e|r| +0#0000000&@49
+|$+0#e000e06&|{||+0#af5f00255&|e|c|h|o| +0#e000002&|f|o|u|r|t|e@1|n|;+0#af5f00255&|}+0#e000e06&| +0#0000000&@56
+|$+0#e000e06&|{||+0#af5f00255&|e|c|h|o| +0#e000002&|f|i|f|t|e@1|n| +0#0000000&@59
+@57|1|9|,|0|-|1| @7|9|2|%|
diff --git a/runtime/syntax/testdir/dumps/sh_bash_02.dump b/runtime/syntax/testdir/dumps/sh_bash_02.dump
new file mode 100644
index 000000000..677a1ab12
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/sh_bash_02.dump
@@ -0,0 +1,20 @@
+|$+0#e000e06#ffffff0|{||+0#af5f00255&|e|c|h|o| +0#e000002&|f|i|f|t|e@1|n| +0#0000000&@59
+>}+0#e000e06&| +0#0000000&@73
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|3@1|,|1| @9|B|o|t|
diff --git a/runtime/syntax/testdir/input/sh_bash.bash b/runtime/syntax/testdir/input/sh_bash.bash
new file mode 100644
index 000000000..35b536c4e
--- /dev/null
+++ b/runtime/syntax/testdir/input/sh_bash.bash
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+# bash 5.3+ supports command substitution that is very similar
+# (but not identical) to ksh/mksh.
+echo ${ echo one;}
+echo ${ echo two
+}
+echo ${
+echo three ;}
+echo ${ echo 'four'; }
+echo ${ echo 'five' ;}
+echo ${ echo 'six'
+}
+echo ${ echo 'seven' ;}
+echo ${ echo 'eight'; }
+typeset nine=${ pwd; }
+echo ${ echo 'nine' ;
+ }
+
+valsubfunc() {
+ REPLY=$1
+}
+echo ${|valsubfunc ten;}
+echo "${|valsubfunc eleven; }"
+printf '%s
' "${|valsubfunc twelve ;}"
+unlucky=${|valsubfunc thirteen
+}
+typeset notafloat=${|valsubfunc notanumber ;
+ }
+echo $unlucky $notanumber
+${|echo fourteen;}
+${|echo fifteen
+}
Reply all
Reply to author
Forward
0 new messages