diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index 9cee161ac2..8dd62566cb 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[ \t\n]" skip='\\\\\|\\.' end="\zs[;\n][ \t\n]*}" contains=@shCommandSubList + syn region shValsub matchgroup=shCmdSubRegion start="\${|" skip='\\\\\|\\.' end="[;\n][ \t\n]*}" 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[^ \t\n<]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart endif +elseif exists("b:is_bash") + syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n|]" 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 0000000000..85966ebd75 --- /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 0000000000..18961a7983 --- /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 0000000000..677a1ab127 --- /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 0000000000..35b536c4e3 --- /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\n' "${|valsubfunc twelve ;}" +unlucky=${|valsubfunc thirteen +} +typeset notafloat=${|valsubfunc notanumber ; + } +echo $unlucky $notanumber +${|echo fourteen;} +${|echo fifteen +}