diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index 41570cce4f..044f2a9e3e 100644 --- a/runtime/syntax/sh.vim +++ b/runtime/syntax/sh.vim @@ -3,30 +3,7 @@ " Maintainer: This runtime file is looking for a new maintainer. " Previous Maintainers: Charles E. Campbell " Lennart Schultz -" Last Change: 2024 Mar 04 by Vim Project {{{1 -" 2024 Nov 03 by Aliaksei Budavei <0x000c70 AT gmail DOT com> improved bracket expressions, #15941 -" 2025 Jan 06 add $PS0 to bashSpecialVariables #16394 -" 2025 Jan 18 add bash coproc, remove duplicate syn keywords #16467 -" 2025 Mar 21 update shell capability detection #16939 -" 2025 Apr 03 command substitution opening paren at EOL #17026 -" 2025 Apr 10 improve shell detection #17084 -" 2025 Apr 29 match escaped chars in test operands #17221 -" 2025 May 06 improve single-quote string matching in parameter expansions -" 2025 May 06 match KornShell compound arrays -" 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 Aug 23 bash: add support for ${ cmd;} and ${|cmd;} #18084 -" 2025 Sep 23 simplify ksh logic, update sh statements #18355 -" 2026 Jan 15 highlight command switches that contain a digit -" 2026 Feb 11 improve support for KornShell function names and variables -" 2026 Feb 15 improve comment handling #19414 -" 2026 Mar 23 improve matching of function definitions #19638 -" 2026 Apr 02 improve matching of function definitions #19849 -" 2026 Apr 19 improve detection of special variables #20016 -" 2026 May 14 don't highlight parens as part of the function name #20219 -" }}} +" Last Change: 2026 May 17 by Vim Project " Version: 208 " Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH " For options and settings, please use: :help ft-sh-syntax @@ -281,7 +258,7 @@ syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial syn cluster shDerefVarList contains=shDerefOffset,shDerefOp,shDerefVarArray,shDerefOpError syn cluster shEchoList contains=shArithmetic,shBracketExpr,shCommandSub,shCommandSubBQ,shDerefVarArray,shSubshare,shValsub,shDeref,shDerefSimple,shEscape,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote syn cluster shExprList1 contains=shBracketExpr,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq -syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest +syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest,shFunctionNameError syn cluster shFunctionCmds contains=shFor,shCaseEsac,shIf,shRepeat,shDblBrace,shDblParen if exists("b:is_ksh88") || exists("b:is_mksh") " Offer "shFunctionCmds" as is. @@ -307,7 +284,7 @@ if exists("b:is_kornshell") || exists("b:is_bash") endif syn cluster shPPSLeftList contains=shAlias,shArithmetic,shBracketExpr,shCmdParenRegion,shCommandSub,shSubshare,shValsub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable syn cluster shPPSRightList contains=shDeref,shDerefSimple,shEscape,shPosnParm -syn cluster shSubShList contains=shBracketExpr,@shCommandSubList,shCommandSubBQ,shSubshare,shValsub,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator +syn cluster shSubShList contains=shBracketExpr,@shCommandSubList,shCommandSubBQ,shSubshare,shValsub,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator,shFunctionNameError syn cluster shTestList contains=shArithmetic,shBracketExpr,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shSpecialDQ,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr syn cluster shNoZSList contains=shSpecialNoZS syn cluster shForList contains=shTestOpr,shNumber,shDerefSimple,shDeref,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shArithmetic @@ -676,6 +653,12 @@ if exists("b:is_bash") 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 + " Claim empty array assignments. + syn match shArrayEmptyDecl "\%#=1\ze\%(\<\h\w*=\)\@>()" transparent nextgroup=shVariable + + if !exists("g:sh_no_error") + syn match shFunctionNameError "\%#=1\%(\%(\<\h\w*\)\@>=\)\%(\%(\w\+\)\@>=\=\)\+()" skipwhite skipnl nextgroup=shExpr,shSubSh + endif elseif exists("b:is_ksh88") " AT&T ksh88 syn match shFunctionCmdOne "^\s*\zs\h\w*\s*()\ze\_s*\%(\%(for\|case\|select\|if\|while\|until\)\>\|\[\[\s\|((\)" skipwhite skipnl nextgroup=@shFunctionCmds contains=shFunctionParens @@ -970,6 +953,9 @@ if !exists("skip_sh_syntax_inits") hi def link shInError Error hi def link shParenError Error hi def link shTestError Error + if exists("b:is_bash") + hi def link shFunctionNameError Error + endif if exists("b:is_kornshell") || exists("b:is_posix") hi def link shDTestError Error endif diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_01.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_01.dump index de0d7d6f12..aba361e65e 100644 --- a/runtime/syntax/testdir/dumps/sh_functions_bash_01.dump +++ b/runtime/syntax/testdir/dumps/sh_functions_bash_01.dump @@ -17,4 +17,4 @@ | +0#0000e05#a8a8a8255@1|f+0#af5f00255#ffffff0|o|r| +0#0000000&|x| |i+0#af5f00255&|n| +0#0000000&|1+0#e000002&| +0#0000000&|2+0#e000002&| +0#0000000&@60 |-+0#0000e05#a8a8a8255| |d+0#af5f00255#ffffff0|o| +0#0000000&@70 ||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|:| @67 -@57|1|9|,|1| @9|3|6|%| +@57|1|9|,|1| @9|1|6|%| diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_02.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_02.dump index 8016beea4f..8901e58ac3 100644 --- a/runtime/syntax/testdir/dumps/sh_functions_bash_02.dump +++ b/runtime/syntax/testdir/dumps/sh_functions_bash_02.dump @@ -16,5 +16,5 @@ |3+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|}+0#e000e06&| +0#0000000&@63 |2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|@|α|!+0#af5f00255&| +0#0000000&|"+0#af5f00255&|$+0#e000e06&|1|"+0#af5f00255&| +0#0000000&@56 |2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|)+0#af5f00255&| +0#0000000&@67 -||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|e+0#af5f00255&|v|a|l| +0#0000000&|!+0#af5f00255&|?+0#0000000&|\+0#e000e06&|#| +0#0000000&|"+0#af5f00255&|$+0#e000e06&|1|"+0#af5f00255&| +0#0000000&@54 -@57|3|7|,|1| @9|8|6|%| +||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|e+0#af5f00255&|v|a|l| +0#0000000&|!+0#af5f00255&|?+0#0000000&|\+0#e000e06&|#| +0#0000000&|"+0#af5f00255&|\+0#e000e06&|"|$|1|\|"|"+0#af5f00255&| +0#0000000&@50 +@57|3|7|,|1| @9|4|0|%| diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_03.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_03.dump index a90642e1dc..98fcc942e8 100644 --- a/runtime/syntax/testdir/dumps/sh_functions_bash_03.dump +++ b/runtime/syntax/testdir/dumps/sh_functions_bash_03.dump @@ -1,20 +1,20 @@ -||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|e+0#af5f00255&|v|a|l| +0#0000000&|!+0#af5f00255&|?+0#0000000&|\+0#e000e06&|#| +0#0000000&|"+0#af5f00255&|$+0#e000e06&|1|"+0#af5f00255&| +0#0000000&@54 +||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|e+0#af5f00255&|v|a|l| +0#0000000&|!+0#af5f00255&|?+0#0000000&|\+0#e000e06&|#| +0#0000000&|"+0#af5f00255&|\+0#e000e06&|"|$|1|\|"|"+0#af5f00255&| +0#0000000&@50 ||+0#0000e05#a8a8a8255| |f+0#af5f00255#ffffff0|i| +0#0000000&@70 | +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@72 | +0#0000e05#a8a8a8255@1|n+0#00e0e07#ffffff0|a|m|e|s|p|a|c|e| |(+0#e000e06&|)| +0#0000000&@60 |-+0#0000e05#a8a8a8255| |{+0#e000e06#ffffff0| +0#0000000&|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|#|;+0#af5f00255&| +0#0000000&@62 ||+0#0000e05#a8a8a8255| >}+0#e000e06#ffffff0|;+0#0000000&| |n|a|m|e|s|p|a|c|e| |$+0#e000e06&|@| +0#0000000&@57 -|~+0#4040ff13&| @73 -|~| @73 -|~| @73 -|~| @73 -|~| @73 -|~| @73 -|~| @73 -|~| @73 -|~| @73 -|~| @73 -|~| @73 -|~| @73 -|~| @73 -| +0#0000000&@56|5@1|,|1| @9|B|o|t| +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@72 +| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |W|h|e|t|h|e|r| |"|=|"| |b|e|l|o|n|g|s| |t|o| |a| |n|a|m|e| |o|r| |d|e|l|i|m|i|t|s| |a| |n|a|m|e| |d|e|p|e|n|d|s| |o|n| |w|h|e|t|h|e|r| +0#0000000&@3 +| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |t|h|e| |r|e|s|e|r|v|e|d| |w|o|r|d| |"|f|u|n|c|t|i|o|n|"| |i|s| |p|r|e|s|e|n|t|,| |i|f| |s|o|,| |t|h|e|n| |"|=|"| |i|s| |p|a|r|t| |o|f| +0#0000000&@3 +| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |t|h|e| |f|u|n|c|t|i|o|n| |n|a|m|e|;| |e|l|s|e|,| |"|=|"| |d|e|l|i|m|i|t|s| |t|h|e| |n|a|m|e| |o|f| |a| |v|a|r|i|a|b|l|e| |w|h|e|n| |t|h|i|s| +0#0000000& +| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |n|a|m|e| |i|s| |g|i|v|e|n| |i|n| |a|l|p|h|a|n|u|m|e|r|i|c| |c|h|a|r|a|c|t|e|r|s| |a|n|d| |"|_|"|s| |b|e|f|o|r|e| |t|h|e| |l|e|f|t|m|o|s|t| +0#0000000&@1 +| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |"|=|"|;| |o|t|h|e|r|w|i|s|e|,| |"|=|"| |i|s| |p|a|r|t| |o|f| |t|h|e| |f|u|n|c|t|i|o|n| |n|a|m|e| |w|h|e|n| |t|h|i|s| |n|a|m|e| |h|a|s| +0#0000000&@3 +| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |o|n|e| |o|r| |m|o|r|e| |s|u|p@1|o|r|t|e|d| |N|O|N|-|a|l|p|h|a|n|u|m|e|r|i|c| |(|o|r| |"|_|"|)| |c|h|a|r|a|c|t|e|r|s| |b|e|f|o|r|e| |"|=|"|.| +0#0000000& +| +0#0000e05#a8a8a8255@1|x+0#00e0e07#ffffff0|s|=+0#0000000&|(+0#e000e06&|)| +0#0000000&@67 +| +0#0000e05#a8a8a8255@1|(+0#e000e06#ffffff0| +0#0000000&@71 +| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@3|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|(@1| |1+0#e000002&| +0#e000e06&|+| |$|{|#|x|s|[|*+0#0000000&|]+0#e000e06&|}| |)@1| +0#0000000&@43 +| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@3|x+0#00e0e07&|s|=+0#0000000&|(+0#e000e06&|)| +0#0000000&@63 +| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@3|{| +0#0000000&@67 +| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@7|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|(@1| |2+0#e000002&| +0#e000e06&|+| |$|{|#|x|s|[|*+0#0000000&|]+0#e000e06&|}| |)@1| +0#0000000&@39 +@57|5@1|,|1| @9|6|3|%| diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_04.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_04.dump new file mode 100644 index 0000000000..d1be88c7d3 --- /dev/null +++ b/runtime/syntax/testdir/dumps/sh_functions_bash_04.dump @@ -0,0 +1,20 @@ +| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@7|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|(@1| |2+0#e000002&| +0#e000e06&|+| |$|{|#|x|s|[|*+0#0000000&|]+0#e000e06&|}| |)@1| +0#0000000&@39 +| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@7|x+0#00e0e07&|s|=+0#0000000&|(+0#e000e06&|)| +0#0000000&@59 +| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@7|i+0#af5f00255&|f| |:+0#e000e06&|;+0#af5f00255&| +0#e000e06&|t+0#af5f00255&|h|e|n| +0#e000e06&|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|(@1| |3+0#e000002&| +0#e000e06&|+| |$|{|#|x|s|[|*+0#0000000&|]+0#e000e06&|}| |)@1|;+0#af5f00255&| +0#e000e06&|f+0#af5f00255&|i| +0#0000000&@24 +| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@3|}| +0#0000000&@67 +| +0#0000e05#a8a8a8255@1|)+0#e000e06#ffffff0| +0#0000000&@71 +| +0#0000e05#a8a8a8255@1> +0#0000000#ffffff0@72 +|-+0#0000e05#a8a8a8255| |i+0#00e0e07#ffffff0|δ|=|(+0#e000e06&|)| +0#0000000&|(+0#af5f00255&| +0#0000000&@65 +|-+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|=+0#00e0e07&|i|d|=|(+0#e000e06&|)| +0#0000000&|{+0#e000e06&| +0#0000000&@60 +|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|=+0#00e0e07&@2|(+0#e000e06&|)| +0#0000000&@59 +|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|i+0#af5f00255&|f| |:+0#0000000&|;+0#af5f00255&| +0#0000000&|t+0#af5f00255&|h|e|n| +0#0000000&|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|*|;+0#af5f00255&| +0#0000000&|f+0#af5f00255&|i|;| +0#0000000&|=+0#af5f00255&@2| +0#0000000&|$+0#e000e06&|*| +0#0000000&@34 +|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|}+0#e000e06&|;+0#af5f00255&| +0#0000000&|=+0#af5f00255&|i|d|=| +0#0000000&|$+0#e000e06&|*| +0#0000000&@58 +||+0#0000e05#a8a8a8255| |)+0#af5f00255#ffffff0|;+0#0000000&| |i+0#af5f00255&|d|=| +0#0000000&|i|δ|=+0#af5f00255&| +0#0000000&|i|δ|=+0#af5f00255&| +0#0000000&|i|δ|=+0#af5f00255&| +0#0000000&@54 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@72 +|-+0#0000e05#a8a8a8255| |f+0#af5f00255#ffffff0|u|n|c|t|i|o|n| +0#0000000&|f+0#00e0e07&|=|(+0#e000e06&|)| +0#0000000&|(+0#af5f00255&| +0#0000000&@57 +|-+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|f+0#af5f00255&|u|n|c|t|i|o|n| +0#0000000&|f+0#00e0e07&|=|f| +0#0000000&|{+0#e000e06&| +0#0000000&@54 +|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|f+0#af5f00255&|u|n|c|t|i|o|n| +0#0000000&|f+0#00e0e07&|=|f|=| +0#0000000&@51 +|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|i+0#af5f00255&|f| |:+0#0000000&|;+0#af5f00255&| +0#0000000&|t+0#af5f00255&|h|e|n| +0#0000000&|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|*|;+0#af5f00255&| +0#0000000&|f+0#af5f00255&|i|;| +0#0000000&|f|\+0#e000e06&|=|f+0#0000000&|\+0#e000e06&|=| +0#0000000&|$+0#e000e06&|*| +0#0000000&@31 +|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|}+0#e000e06&|;+0#af5f00255&| +0#0000000&|f|\+0#e000e06&|=|f+0#0000000&| |$+0#e000e06&|*| +0#0000000&@58 +||+0#0000e05#a8a8a8255| |)+0#af5f00255#ffffff0|;+0#0000000&| |f+0#00e0e07&|=+0#0000000&| |f|\|=+0#af5f00255&| +0#0000000&|f+0#00e0e07&|=+0#0000000&| |f+0#00e0e07&|=+0#0000000&| @57 +@57|7|3|,|0|-|1| @7|8|7|%| diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_05.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_05.dump new file mode 100644 index 0000000000..9b805c1891 --- /dev/null +++ b/runtime/syntax/testdir/dumps/sh_functions_bash_05.dump @@ -0,0 +1,20 @@ +||+0#0000e05#a8a8a8255| |)+0#af5f00255#ffffff0|;+0#0000000&| |f+0#00e0e07&|=+0#0000000&| |f|\|=+0#af5f00255&| +0#0000000&|f+0#00e0e07&|=+0#0000000&| |f+0#00e0e07&|=+0#0000000&| @57 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@72 +| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |P|a|r|e|n|s| |a|r|e| |n|o|t| |e|s|c|a|p|e|d|,| |h|e|n|c|e| |t|h|i|s| |i|s| |i|n|v|a|l|i|d| |v|a|r|i|a|b|l|e| |a|s@1|i|g|n|m|e|n|t|.| +0#0000000&@4 +| +0#0000e05#a8a8a8255@1|f+0#ffffff16#ff404010|=|f|(|)| +0#0000000#ffffff0@67 +| +0#0000e05#a8a8a8255@1|{+0#e000e06#ffffff0| +0#0000000&@71 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3>f+0#ffffff16#ff404010|=|f|=|(|)| +0#0000000#ffffff0@62 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|(+0#af5f00255&| +0#0000000&@67 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@7|f+0#ffffff16#ff404010|=|f|=|f|(|)| +0#0000000#ffffff0@57 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@7|i+0#af5f00255&|f| |:+0#0000000&|;+0#af5f00255&| +0#0000000&|t+0#af5f00255&|h|e|n| +0#0000000&|:|;+0#af5f00255&| +0#0000000&|f+0#af5f00255&|i| +0#0000000&@48 +| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|)+0#af5f00255&| +0#0000000&@67 +| +0#0000e05#a8a8a8255@1|}+0#e000e06#ffffff0| +0#0000000&@71 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|9|1|,|5| @9|B|o|t| diff --git a/runtime/syntax/testdir/input/sh_functions_bash.sh b/runtime/syntax/testdir/input/sh_functions_bash.sh index 161f14f978..714d2a74b3 100644 --- a/runtime/syntax/testdir/input/sh_functions_bash.sh +++ b/runtime/syntax/testdir/input/sh_functions_bash.sh @@ -47,9 +47,50 @@ if :; then } @α! "$1" ) - eval !?\# "$1" + eval !?\# "\"$1\"" fi namespace () { echo $#; }; namespace $@ + +# Whether "=" belongs to a name or delimits a name depends on whether +# the reserved word "function" is present, if so, then "=" is part of +# the function name; else, "=" delimits the name of a variable when this +# name is given in alphanumeric characters and "_"s before the leftmost +# "="; otherwise, "=" is part of the function name when this name has +# one or more supported NON-alphanumeric (or "_") characters before "=". +xs=() +( + echo $(( 1 + ${#xs[*]} )) + xs=() + { + echo $(( 2 + ${#xs[*]} )) + xs=() + if :; then echo $(( 3 + ${#xs[*]} )); fi + } +) + +iδ=() ( + =id=() { + ===() + if :; then echo $*; fi; === $* + }; =id= $* +); id= iδ= iδ= iδ= + +function f=() ( + function f=f { + function f=f= + if :; then echo $*; fi; f\=f\= $* + }; f\=f $* +); f= f\= f= f= + +# Parens are not escaped, hence this is invalid variable assignment. +f=f() +{ + f=f=() + ( + f=f=f() + if :; then :; fi + ) +}