From 409122e5aede252fb83aa5cb9a1e88514b3561ed Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 24 Sep 2025 08:28:38 +0800 Subject: [PATCH] vim-patch:11bde1f: runtime(sh): refactored sh.vim syntax script (#35895) - unified bashStatement, kshStatement and shStatement as much as possible - separated builtin commands from external programs - cleaned up kornshell flavor logic - fixed alias syntax highlighting - added test for bash alias syntax highlighting - removed daemon keyword closes: vim/vim#18355 https://github.com/vim/vim/commit/11bde1f16939ef4128d08488ae238c66b46aa056 Co-authored-by: Bjoern Foersterling --- runtime/syntax/sh.vim | 1013 ++++++++++++++++++++--------------------- 1 file changed, 492 insertions(+), 521 deletions(-) diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index 8dd62566cb..5cf4930658 100644 --- a/runtime/syntax/sh.vim +++ b/runtime/syntax/sh.vim @@ -4,20 +4,21 @@ " 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) +" 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 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 " }}} " Version: 208 " Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH @@ -26,7 +27,7 @@ " quit when a syntax file was already loaded {{{1 if exists("b:current_syntax") - finish + finish endif " Ensure this is set unless we find another shell @@ -36,36 +37,36 @@ let b:is_sh = 1 let s:shebang = getline(1) if s:shebang =~ '^#!.\{-2,}\' - " The binary is too ambiguous (i.e. '/bin/ksh' or some such). - let b:is_kornshell = 1 - let b:generic_korn = 1 + " The binary is too ambiguous (i.e. '/bin/ksh' or some such). + let b:is_kornshell = 1 + let b:generic_korn = 1 elseif s:shebang =~ '^#!.\{-2,}\' - " ksh93u+ (or 93u-) release (still much too common to encounter) - let b:is_kornshell = 1 - let b:is_ksh93u = 1 + " ksh93u+ (or 93u-) release (still much too common to encounter) + let b:is_kornshell = 1 + let b:is_ksh93u = 1 elseif s:shebang =~ '^#!.\{-2,}\' - " ksh93v- alpha or beta - let b:is_kornshell = 1 - let b:is_ksh93v = 1 + " ksh93v- alpha or beta + let b:is_kornshell = 1 + let b:is_ksh93v = 1 elseif s:shebang =~ '^#!.\{-2,}\' - " Could be any ksh93 release - let b:is_kornshell = 1 - let b:is_ksh93 = 1 + " Could be any ksh93 release + let b:is_kornshell = 1 + let b:is_ksh93 = 1 elseif s:shebang =~ '^#!.\{-2,}\' - let b:is_kornshell = 1 - let b:is_ksh2020 = 1 + let b:is_kornshell = 1 + let b:is_ksh2020 = 1 elseif s:shebang =~ '^#!.\{-2,}\' - " The actual AT&T ksh88 and its feature set is assumed. - let b:is_kornshell = 1 - let b:is_ksh88 = 1 + " The actual AT&T ksh88 and its feature set is assumed. + let b:is_kornshell = 1 + let b:is_ksh88 = 1 elseif s:shebang =~ '^#!.\{-2,}\' - " MirBSD Korn Shell - let b:is_kornshell = 1 - let b:is_mksh = 1 + " MirBSD Korn Shell + let b:is_kornshell = 1 + let b:is_mksh = 1 elseif s:shebang =~ '^#!.\{-2,}\' - let b:is_bash = 1 + let b:is_bash = 1 elseif s:shebang =~ '^#!.\{-2,}\' - let b:is_dash = 1 + let b:is_dash = 1 " handling /bin/sh with is_kornshell/is_sh {{{1 " b:is_sh will be set when "#! /bin/sh" is found; " However, it often is just a masquerade by bash (typically Linux) @@ -74,132 +75,132 @@ elseif s:shebang =~ '^#!.\{-2,}\' " "g:is_posix" or "g:is_dash", a b:is_sh is converted into " b:is_kornshell/b:is_bash/b:is_posix/b:is_dash, respectively. elseif !exists("b:is_kornshell") && !exists("b:is_bash") && !exists("b:is_posix") && !exists("b:is_dash") - if exists("g:is_kornshell") - let b:is_kornshell= 1 - let b:generic_korn = 1 - elseif exists("g:is_bash") - let b:is_bash= 1 - elseif exists("g:is_dash") - let b:is_dash= 1 - elseif exists("g:is_posix") - let b:is_posix= 1 - elseif exists("g:is_sh") - let b:is_sh= 1 - else - " user did not specify which shell to use, and - " the script itself does not specify which shell to use. FYI: /bin/sh is ambiguous. - " Assuming /bin/sh is executable, and if its a link, find out what it links to. - let s:shell = "" - if executable("/bin/sh") - let s:shell = resolve("/bin/sh") - elseif executable("/usr/bin/sh") - let s:shell = resolve("/usr/bin/sh") - endif - if s:shell =~ '\' - " The binary is too ambiguous (i.e. '/bin/ksh' or some such). - let b:is_kornshell = 1 - let b:generic_korn = 1 - elseif s:shell =~ '\' - " ksh93u+ (or 93u-) release (still much too common to encounter) - let b:is_kornshell = 1 - let b:is_ksh93u = 1 - elseif s:shell =~ '\' - " ksh93v- alpha or beta - let b:is_kornshell = 1 - let b:is_ksh93v = 1 - elseif s:shell =~ '\' - " Could be any ksh93 release - let b:is_kornshell = 1 - let b:is_ksh93 = 1 - elseif s:shebang =~ '\' - let b:is_kornshell = 1 - let b:is_ksh2020 = 1 - elseif s:shell =~ '\' - " The actual AT&T ksh88 and its feature set is assumed. - let b:is_kornshell = 1 - let b:is_ksh88 = 1 - elseif s:shell =~ '\' - " MirBSD Korn Shell - let b:is_kornshell = 1 - let b:is_mksh = 1 - elseif s:shell =~ '\' - let b:is_bash = 1 - elseif s:shell =~ '\' - let b:is_dash = 1 - else - let b:is_posix = 1 - endif - unlet s:shell - endif + if exists("g:is_kornshell") + let b:is_kornshell= 1 + let b:generic_korn = 1 + elseif exists("g:is_bash") + let b:is_bash= 1 + elseif exists("g:is_dash") + let b:is_dash= 1 + elseif exists("g:is_posix") + let b:is_posix= 1 + elseif exists("g:is_sh") + let b:is_sh= 1 + else + " user did not specify which shell to use, and + " the script itself does not specify which shell to use. FYI: /bin/sh is ambiguous. + " Assuming /bin/sh is executable, and if its a link, find out what it links to. + let s:shell = "" + if executable("/bin/sh") + let s:shell = resolve("/bin/sh") + elseif executable("/usr/bin/sh") + let s:shell = resolve("/usr/bin/sh") + endif + if s:shell =~ '\' + " The binary is too ambiguous (i.e. '/bin/ksh' or some such). + let b:is_kornshell = 1 + let b:generic_korn = 1 + elseif s:shell =~ '\' + " ksh93u+ (or 93u-) release (still much too common to encounter) + let b:is_kornshell = 1 + let b:is_ksh93u = 1 + elseif s:shell =~ '\' + " ksh93v- alpha or beta + let b:is_kornshell = 1 + let b:is_ksh93v = 1 + elseif s:shell =~ '\' + " Could be any ksh93 release + let b:is_kornshell = 1 + let b:is_ksh93 = 1 + elseif s:shebang =~ '\' + let b:is_kornshell = 1 + let b:is_ksh2020 = 1 + elseif s:shell =~ '\' + " The actual AT&T ksh88 and its feature set is assumed. + let b:is_kornshell = 1 + let b:is_ksh88 = 1 + elseif s:shell =~ '\' + " MirBSD Korn Shell + let b:is_kornshell = 1 + let b:is_mksh = 1 + elseif s:shell =~ '\' + let b:is_bash = 1 + elseif s:shell =~ '\' + let b:is_dash = 1 + else + let b:is_posix = 1 + endif + unlet s:shell + endif endif unlet s:shebang " if b:is_dash, set b:is_posix too if exists("b:is_dash") - let b:is_posix= 1 + let b:is_posix= 1 endif if exists("b:is_kornshell") || exists("b:is_bash") - if exists("b:is_sh") - unlet b:is_sh - endif + if exists("b:is_sh") + unlet b:is_sh + endif endif " set up default g:sh_fold_enabled {{{1 " ================================ if !exists("g:sh_fold_enabled") - let g:sh_fold_enabled= 0 + let g:sh_fold_enabled= 0 elseif g:sh_fold_enabled != 0 && !has("folding") - echomsg "Ignoring g:sh_fold_enabled=".g:sh_fold_enabled."; need to re-compile vim for +fold support" - let g:sh_fold_enabled= 0 + echomsg "Ignoring g:sh_fold_enabled=".g:sh_fold_enabled."; need to re-compile vim for +fold support" + let g:sh_fold_enabled= 0 endif let s:sh_fold_functions= and(g:sh_fold_enabled,1) let s:sh_fold_heredoc = and(g:sh_fold_enabled,2) let s:sh_fold_ifdofor = and(g:sh_fold_enabled,4) if g:sh_fold_enabled && &fdm == "manual" - " Given that the user provided g:sh_fold_enabled - " AND g:sh_fold_enabled is manual (usual default) - " implies a desire for syntax-based folding - setl fdm=syntax + " Given that the user provided g:sh_fold_enabled + " AND g:sh_fold_enabled is manual (usual default) + " implies a desire for syntax-based folding + setl fdm=syntax endif " set up the syntax-highlighting for iskeyword if (v:version == 704 && has("patch-7.4.1142")) || v:version > 704 - if !exists("g:sh_syntax_isk") || (exists("g:sh_syntax_isk") && g:sh_syntax_isk) - if exists("b:is_bash") - exe "syn iskeyword ".&iskeyword.",-,:" - else - exe "syn iskeyword ".&iskeyword.",-" - endif - endif + if !exists("g:sh_syntax_isk") || (exists("g:sh_syntax_isk") && g:sh_syntax_isk) + if exists("b:is_bash") + exe "syn iskeyword ".&iskeyword.",-,:" + else + exe "syn iskeyword ".&iskeyword.",-" + endif + endif endif " Set up folding commands for shell {{{1 " ================================= if exists(":ShFoldFunctions") == 2 - delc ShFoldFunctions + delc ShFoldFunctions endif if exists(":ShFoldIfHereDoc") == 2 - delc ShFoldHereDoc + delc ShFoldHereDoc endif if exists(":ShFoldIfDoFor") == 2 - delc ShFoldIfDoFor + delc ShFoldIfDoFor endif if s:sh_fold_functions - com! -nargs=* ShFoldFunctions fold + com! -nargs=* ShFoldFunctions fold else - com! -nargs=* ShFoldFunctions + com! -nargs=* ShFoldFunctions endif if s:sh_fold_heredoc - com! -nargs=* ShFoldHereDoc fold + com! -nargs=* ShFoldHereDoc fold else - com! -nargs=* ShFoldHereDoc + com! -nargs=* ShFoldHereDoc endif if s:sh_fold_ifdofor - com! -nargs=* ShFoldIfDoFor fold + com! -nargs=* ShFoldIfDoFor fold else - com! -nargs=* ShFoldIfDoFor + com! -nargs=* ShFoldIfDoFor endif " Generate bracket expression items {{{1 @@ -211,37 +212,37 @@ endif " its value does not have "contained" among other optional arguments (":help " :syn-arguments"). fun! s:GenerateBracketExpressionItems(dict) abort - let itemGroup = a:dict.itemGroup - let bracketGroup = a:dict.bracketGroup - let invGroup = itemGroup . 'Inv' - let skipLeftBracketGroup = itemGroup . 'SkipLeftBracket' - let skipRightBracketGroup = itemGroup . 'SkipRightBracket' - let extraArgs = has_key(a:dict, 'extraArgs') ? a:dict.extraArgs : '' + let itemGroup = a:dict.itemGroup + let bracketGroup = a:dict.bracketGroup + let invGroup = itemGroup . 'Inv' + let skipLeftBracketGroup = itemGroup . 'SkipLeftBracket' + let skipRightBracketGroup = itemGroup . 'SkipRightBracket' + let extraArgs = has_key(a:dict, 'extraArgs') ? a:dict.extraArgs : '' - " Make the leading "[!^]" stand out in a NON-matching expression. - exec 'syn match ' . invGroup . ' contained "\[\@<=[!^]"' + " Make the leading "[!^]" stand out in a NON-matching expression. + exec 'syn match ' . invGroup . ' contained "\[\@<=[!^]"' - " Set up indirections for unbalanced-bracket highlighting. - exec 'syn region ' . skipRightBracketGroup . ' contained matchgroup=' . bracketGroup . ' start="\[\%([!^]\=\\\=\]\)\@=" matchgroup=shCollSymb end="\[\.[^]]\{-}\][^]]\{-}\.\]" matchgroup=' . itemGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . invGroup - exec 'syn region ' . skipLeftBracketGroup . ' contained matchgroup=' . bracketGroup . ' start="\[\%([!^]\=\\\=\]\)\@=" skip="[!^]\=\\\=\]\%(\[[^]]\+\]\|[^]]\)\{-}\%(\[[:.=]\@!\)\@=" matchgroup=' . itemGroup . ' end="\[[:.=]\@!" contains=@shBracketExprList,shDoubleQuote,' . invGroup + " Set up indirections for unbalanced-bracket highlighting. + exec 'syn region ' . skipRightBracketGroup . ' contained matchgroup=' . bracketGroup . ' start="\[\%([!^]\=\\\=\]\)\@=" matchgroup=shCollSymb end="\[\.[^]]\{-}\][^]]\{-}\.\]" matchgroup=' . itemGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . invGroup + exec 'syn region ' . skipLeftBracketGroup . ' contained matchgroup=' . bracketGroup . ' start="\[\%([!^]\=\\\=\]\)\@=" skip="[!^]\=\\\=\]\%(\[[^]]\+\]\|[^]]\)\{-}\%(\[[:.=]\@!\)\@=" matchgroup=' . itemGroup . ' end="\[[:.=]\@!" contains=@shBracketExprList,shDoubleQuote,' . invGroup - " Look for a general matching expression. - exec 'syn region ' . itemGroup . ' matchgroup=' . bracketGroup . ' start="\[\S\@=" end="\]" contains=@shBracketExprList,shDoubleQuote ' . extraArgs - " Look for a general NON-matching expression. - exec 'syn region ' . itemGroup . ' matchgroup=' . bracketGroup . ' start="\[[!^]\@=" end="\]" contains=@shBracketExprList,shDoubleQuote,' . invGroup . ' ' . extraArgs + " Look for a general matching expression. + exec 'syn region ' . itemGroup . ' matchgroup=' . bracketGroup . ' start="\[\S\@=" end="\]" contains=@shBracketExprList,shDoubleQuote ' . extraArgs + " Look for a general NON-matching expression. + exec 'syn region ' . itemGroup . ' matchgroup=' . bracketGroup . ' start="\[[!^]\@=" end="\]" contains=@shBracketExprList,shDoubleQuote,' . invGroup . ' ' . extraArgs - " Accommodate unbalanced brackets in bracket expressions. The supported - " syntax for a plain "]" can be: "[]ws]" and "[^]ws]"; or, "[ws[.xs]ys.]zs]" - " and "[^ws[.xs]ys.]zs]"; see §9.3.5 RE Bracket Expression (in XBD). - exec 'syn region ' . itemGroup . ' matchgroup=NONE start="\[[!^]\=\\\=\]" matchgroup=' . bracketGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . skipRightBracketGroup . ' ' . extraArgs - " Strive to handle "[]...[]" etc. - exec 'syn region ' . itemGroup . ' matchgroup=NONE start="\[[!^]\=\\\=\]\%(\[[^]]\+\]\|[^]]\)\{-}\[[:.=]\@!" matchgroup=' . bracketGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . skipLeftBracketGroup . ' ' . extraArgs + " Accommodate unbalanced brackets in bracket expressions. The supported + " syntax for a plain "]" can be: "[]ws]" and "[^]ws]"; or, "[ws[.xs]ys.]zs]" + " and "[^ws[.xs]ys.]zs]"; see §9.3.5 RE Bracket Expression (in XBD). + exec 'syn region ' . itemGroup . ' matchgroup=NONE start="\[[!^]\=\\\=\]" matchgroup=' . bracketGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . skipRightBracketGroup . ' ' . extraArgs + " Strive to handle "[]...[]" etc. + exec 'syn region ' . itemGroup . ' matchgroup=NONE start="\[[!^]\=\\\=\]\%(\[[^]]\+\]\|[^]]\)\{-}\[[:.=]\@!" matchgroup=' . bracketGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . skipLeftBracketGroup . ' ' . extraArgs - if !exists("g:skip_sh_syntax_inits") - exec 'hi def link ' . skipLeftBracketGroup . ' ' . itemGroup - exec 'hi def link ' . skipRightBracketGroup . ' ' . itemGroup - exec 'hi def link ' . invGroup . ' Underlined' - endif + if !exists("g:skip_sh_syntax_inits") + exec 'hi def link ' . skipLeftBracketGroup . ' ' . itemGroup + exec 'hi def link ' . skipRightBracketGroup . ' ' . itemGroup + exec 'hi def link ' . invGroup . ' Underlined' + endif endfun call s:GenerateBracketExpressionItems({'itemGroup': 'shBracketExpr', 'bracketGroup': 'shBracketExprDelim'}) @@ -253,7 +254,7 @@ syn case match "================================== syn cluster shErrorList contains=shDoError,shIfError,shInError,shCaseError,shEsacError,shCurlyError,shParenError,shTestError,shOK if exists("b:is_kornshell") || exists("b:is_bash") - syn cluster ErrorList add=shDTestError + syn cluster ErrorList add=shDTestError endif syn cluster shArithParenList contains=shArithmetic,shArithParen,shCaseEsac,shComment,shDeref,shDerefVarArray,shDo,shDerefSimple,shEcho,shEscape,shExpr,shNumber,shOperator,shPosnParm,shExSingleQuote,shExDoubleQuote,shHereString,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement,shIf,shFor,shFunctionKey,shFunctionOne,shFunctionTwo syn cluster shArithList contains=@shArithParenList,shParenError @@ -261,7 +262,7 @@ syn cluster shBracketExprList contains=shCharClassOther,shCharClass,shCollSymb,s syn cluster shCaseEsacList contains=shCaseStart,shCaseLabel,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial,shCaseRange syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shComment,shDblBrace,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq if exists("b:is_kornshell") || exists("b:is_bash") - syn cluster shCaseList add=shForPP,shDblParen + syn cluster shCaseList add=shForPP,shDblParen endif syn cluster shCommandSubList contains=shAlias,shArithmetic,shBracketExpr,shCmdParenRegion,shCommandSub,shComment,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial @@ -274,8 +275,8 @@ syn cluster shExprList1 contains=shBracketExpr,shNumber,shOperator,shExSingleQuo syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest syn cluster shFunctionList contains=shBracketExpr,@shCommandSubList,shCaseEsac,shColon,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shOption,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq if exists("b:is_kornshell") || exists("b:is_bash") - syn cluster shFunctionList add=shRepeat,shDblBrace,shDblParen,shForPP - syn cluster shDerefList add=shCommandSubList,shEchoDeref + syn cluster shFunctionList add=shRepeat,shDblBrace,shDblParen,shForPP + syn cluster shDerefList add=shCommandSubList,shEchoDeref endif syn cluster shHereBeginList contains=@shCommandSubList syn cluster shHereList contains=shBeginHere,shHerePayload @@ -284,7 +285,7 @@ syn cluster shIdList contains=shArithmetic,shCommandSub,shCommandSubBQ,shDerefVa syn cluster shIfList contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey,shFunctionOne,shFunctionTwo syn cluster shLoopList contains=@shCaseList,@shErrorList,shCaseEsac,shConditional,shDblBrace,shExpr,shFor,shIf,shOption,shSet,shTest,shTestOpr,shTouch if exists("b:is_kornshell") || exists("b:is_bash") - syn cluster shLoopList add=shForPP,shDblParen + syn cluster shLoopList add=shForPP,shDblParen 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 @@ -297,15 +298,15 @@ syn cluster shForList contains=shTestOpr,shNumber,shDerefSimple,shDeref,shComman " ==== " This one is needed INSIDE a CommandSub, so that `echo bla` be correct if (exists("b:is_kornshell") && !exists("b:is_ksh88")) - syn region shEcho matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 end="\ze[ \t\n;]}" contains=@shEchoList skipwhite nextgroup=shQuickComment - syn region shEcho matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 end="\ze[ \t\n;]}" contains=@shEchoList skipwhite nextgroup=shQuickComment + syn region shEcho matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 end="\ze[ \t\n;]}" contains=@shEchoList skipwhite nextgroup=shQuickComment + syn region shEcho matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 end="\ze[ \t\n;]}" contains=@shEchoList skipwhite nextgroup=shQuickComment else - syn region shEcho matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment - syn region shEcho matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment + syn region shEcho matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment + syn region shEcho matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment endif if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix") - syn region shEchoDeref contained matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment - syn region shEchoDeref contained matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment + syn region shEchoDeref contained matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment + syn region shEchoDeref contained matchgroup=shStatement start="\" skip="\\$" matchgroup=shEchoDelim end="$" end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment endif syn match shEchoQuote contained '\%(\\\\\)*\\["`'()]' @@ -315,33 +316,31 @@ syn region shEmbeddedEcho contained matchgroup=shStatement start="\" ski " Alias: {{{1 " ===== if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix") - syn match shStatement "\" - syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]*\)\@=" skip="\\$" end="\>\|`" - syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]*=\)\@=" skip="\\$" end="=" -" syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]\+\)\@=" skip="\\$" end="\>\|`" -" syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]\+=\)\@=" skip="\\$" end="=" + syn match shStatement "\" + syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]*\)\@=" skip="\\$" end="\>\|`" + syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]*=\)\@=" skip="\\$" end="=" - " Touch: {{{1 - " ===== - syn match shTouch '\[^;#]*' skipwhite nextgroup=shComment contains=shTouchCmd,shDoubleQuote,shSingleQuote,shDeref,shDerefSimple - syn match shTouchCmd '\' contained + " Touch: {{{1 + " ===== + syn match shTouch '\[^;#]*' skipwhite nextgroup=shComment contains=shTouchCmd,shDoubleQuote,shSingleQuote,shDeref,shDerefSimple + syn match shTouchCmd '\' contained endif " Error Codes: {{{1 " ============ if !exists("g:sh_no_error") - syn match shDoError "\" - syn match shIfError "\" - syn match shInError "\" - syn match shCaseError ";;" - syn match shEsacError "\" - syn match shCurlyError "}" - syn match shParenError ")" - syn match shOK '\.\(done\|fi\|in\|esac\)' - if exists("b:is_kornshell") || exists("b:is_bash") - syn match shDTestError "]]" - endif - syn match shTestError "]" + syn match shDoError "\" + syn match shIfError "\" + syn match shInError "\" + syn match shCaseError ";;" + syn match shEsacError "\" + syn match shCurlyError "}" + syn match shParenError ")" + syn match shOK '\.\(done\|fi\|in\|esac\)' + if exists("b:is_kornshell") || exists("b:is_bash") + syn match shDTestError "]]" + endif + syn match shTestError "]" endif " Options: {{{1 @@ -381,8 +380,8 @@ syn region shTestDoubleQuote contained start='\%(\%(\\\\\)*\\\)\@ ShFoldIfDoFor syn region shIf transparent matchgroup=shConditional start="\+ end="\<;\_s*then\>" end="\" contains=@shIfList ShFoldIfDoFor syn region shFor matchgroup=shLoop start="\#\=" syn match shNumber "\<-\=\.\=\d\+\>#\=" syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained if exists("b:is_bash") || exists("b:is_kornshell") - syn match shSpecial "[^\\]\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained - syn match shSpecial "^\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained - syn region shExSingleQuote matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial nextgroup=shSpecialNxt - syn region shExDoubleQuote matchgroup=shQuote start=+\$"+ skip=+\\\\\|\\.\|\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,shSpecial nextgroup=shSpecialNxt + syn match shSpecial "[^\\]\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained + syn match shSpecial "^\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained + syn region shExSingleQuote matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial nextgroup=shSpecialNxt + syn region shExDoubleQuote matchgroup=shQuote start=+\$"+ skip=+\\\\\|\\.\|\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,shSpecial nextgroup=shSpecialNxt elseif !exists("g:sh_no_error") - syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial - syn region shExDoubleQuote matchGroup=Error start=+\$"+ skip=+\\\\\|\\.+ end=+"+ contains=shStringSpecial + syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial + syn region shExDoubleQuote matchGroup=Error start=+\$"+ skip=+\\\\\|\\.+ end=+"+ contains=shStringSpecial endif syn region shSingleQuote matchgroup=shQuote start=+'+ end=+'+ contains=@Spell nextgroup=shSpecialStart,shSpecialSQ syn region shDoubleQuote matchgroup=shQuote start=+\%(\%(\\\\\)*\\\)\@" + syn match shTodo contained "\<\%(COMBAK\|FIXME\|TODO\|XXX\)\ze:\=\>" else - syn keyword shTodo contained COMBAK FIXME TODO XXX + syn keyword shTodo contained COMBAK FIXME TODO XXX endif syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup syn match shComment "\s\zs#.*$" contains=@shCommentGroup @@ -601,7 +593,7 @@ ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc16 start="<<-\s*\\\_$\_s* " ============= " available for: bash and ksh (except ksh88) but not if its a posix if exists("b:is_bash") || ((exists("b:is_kornshell") && !exists("b:is_ksh88")) && !exists("b:is_posix")) - syn match shHereString "<<<" skipwhite nextgroup=shCmdParenRegion + syn match shHereString "<<<" skipwhite nextgroup=shCmdParenRegion endif " Identifiers: {{{1 @@ -609,112 +601,111 @@ endif syn match shSetOption "\s\zs[-+][a-zA-Z0-9]\+\>" contained syn match shVariable "\<\h\w*\ze=" nextgroup=shVarAssign if exists("b:is_bash") - " The subscript form for array values, e.g. "foo=([2]=10 [4]=100)". - syn region shArrayValue contained start="\[\%(..\{-}\]=\)\@=" end="\]=\@=" contains=@shArrayValueList nextgroup=shVarAssign - syn cluster shArrayValueList contains=shArithmetic,shArithParen,shCommandSub,shDeref,shDerefSimple,shExpr,shNumber,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shSpecial,shParen,bashSpecialVariables,shParenError - syn region shArrayRegion contained matchgroup=shShellVariables start="(" skip='\\\\\|\\.' end=")" contains=@shArrayValueList,shArrayValue,shComment + " The subscript form for array values, e.g. "foo=([2]=10 [4]=100)". + syn region shArrayValue contained start="\[\%(..\{-}\]=\)\@=" end="\]=\@=" contains=@shArrayValueList nextgroup=shVarAssign + syn cluster shArrayValueList contains=shArithmetic,shArithParen,shCommandSub,shDeref,shDerefSimple,shExpr,shNumber,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shSpecial,shParen,bashSpecialVariables,shParenError + syn region shArrayRegion contained matchgroup=shShellVariables start="(" skip='\\\\\|\\.' end=")" contains=@shArrayValueList,shArrayValue,shComment elseif (exists("b:is_kornshell") && !exists("b:is_ksh88")) - " The subscript form for array values, e.g. "foo=([2]=10 [4]=100)". - syn region shArrayValue contained start="\[\%(..\{-}\]=\)\@=" end="\]=\@=" contains=@shArrayValueList nextgroup=shVarAssign - syn cluster shArrayValueList contains=shArithmetic,shArithParen,shCommandSub,shDeref,shDerefSimple,shExpr,shNumber,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shSpecial,shParen,kshSpecialVariables,shParenError - syn region shArrayRegion contained matchgroup=shShellVariables start="(" skip='\\\\\|\\.' end=")" contains=@shArrayValueList,shArrayValue,shComment,shArrayRegion + " The subscript form for array values, e.g. "foo=([2]=10 [4]=100)". + syn region shArrayValue contained start="\[\%(..\{-}\]=\)\@=" end="\]=\@=" contains=@shArrayValueList nextgroup=shVarAssign + syn cluster shArrayValueList contains=shArithmetic,shArithParen,shCommandSub,shDeref,shDerefSimple,shExpr,shNumber,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shSpecial,shParen,kshSpecialVariables,shParenError + syn region shArrayRegion contained matchgroup=shShellVariables start="(" skip='\\\\\|\\.' end=")" contains=@shArrayValueList,shArrayValue,shComment,shArrayRegion endif if exists("b:is_bash") || exists("b:is_kornshell") - syn match shVariable "\<\h\w*\%(\[..\{-}\]\)\=\ze\%([|^&*/%+-]\|[<^]<\|[>^]>\)\==" contains=shDerefVarArray nextgroup=shVarAssign - syn match shVarAssign contained "\%([|^&*/%+-]\|[<^]<\|[>^]>\)\==" nextgroup=shArrayRegion,shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote,shVar + syn match shVariable "\<\h\w*\%(\[..\{-}\]\)\=\ze\%([|^&*/%+-]\|[<^]<\|[>^]>\)\==" contains=shDerefVarArray nextgroup=shVarAssign + syn match shVarAssign contained "\%([|^&*/%+-]\|[<^]<\|[>^]>\)\==" nextgroup=shArrayRegion,shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote,shVar else - syn match shVarAssign contained "=" nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote,shVar + syn match shVarAssign contained "=" nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote,shVar endif syn match shVar contained "\h\w*" syn region shAtExpr contained start="@(" end=")" contains=@shIdList if exists("b:is_bash") - syn match shSet "^\s*set\ze\s\+$" - syn region shSetList oneline matchgroup=shSet start="\<\%(declare\|local\|export\)\>\ze[/a-zA-Z_]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+#\|=" contains=@shIdList - syn region shSetList oneline matchgroup=shSet start="\<\%(set\|unset\)\>[/a-zA-Z_]\@!" end="\ze[;|#)]\|$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+=" contains=@shIdList nextgroup=shComment + syn match shSet "^\s*set\ze\s\+$" + syn region shSetList oneline matchgroup=shSet start="\<\%(declare\|local\|export\)\>\ze[/a-zA-Z_]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+#\|=" contains=@shIdList + syn region shSetList oneline matchgroup=shSet start="\<\%(set\|unset\)\>[/a-zA-Z_]\@!" end="\ze[;|#)]\|$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+=" contains=@shIdList nextgroup=shComment elseif exists("b:is_kornshell") || exists("b:is_posix") - syn match shSet "^\s*set\ze\s\+$" - if exists("b:is_dash") - syn region shSetList oneline matchgroup=shSet start="\<\%(local\)\>\ze[/]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList - endif - syn region shSetList oneline matchgroup=shSet start="\<\(export\)\>\ze[/]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList - syn region shSetList oneline matchgroup=shSet start="\<\%(set\|unset\>\)\ze[/a-zA-Z_]\@!" end="\ze[;|#)]\|$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList nextgroup=shComment + syn match shSet "^\s*set\ze\s\+$" + if exists("b:is_dash") + syn region shSetList oneline matchgroup=shSet start="\<\%(local\)\>\ze[/]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList + syn keyword shStatement chdir + endif + syn region shSetList oneline matchgroup=shSet start="\<\(export\)\>\ze[/]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList + syn region shSetList oneline matchgroup=shSet start="\<\%(set\|unset\>\)\ze[/a-zA-Z_]\@!" end="\ze[;|#)]\|$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList nextgroup=shComment else - syn region shSetList oneline matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[/a-zA-Z_]\@!" end="\ze[;|#)]\|$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList + syn region shSetList oneline matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[/a-zA-Z_]\@!" end="\ze[;|#)]\|$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList endif " KornShell namespace: {{{1 if exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh") - syn keyword shFunctionKey namespace skipwhite skipnl nextgroup=shFunctionTwo + syn keyword shFunctionKey namespace skipwhite skipnl nextgroup=shFunctionTwo endif " Functions: {{{1 if !exists("b:is_posix") - syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo + syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo endif if exists("b:is_bash") - syn keyword shFunctionKey coproc - ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*[A-Za-z_0-9:][-a-zA-Z_0-9:]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_0-9:][-a-zA-Z_0-9:]*\>\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*[A-Za-z_0-9:][-a-zA-Z_0-9:]*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_0-9:][-a-zA-Z_0-9:]*\>\s*\%(()\)\=\_s*)" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + syn keyword shFunctionKey coproc + ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*[A-Za-z_0-9:][-a-zA-Z_0-9:]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_0-9:][-a-zA-Z_0-9:]*\>\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*[A-Za-z_0-9:][-a-zA-Z_0-9:]*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_0-9:][-a-zA-Z_0-9:]*\>\s*\%(()\)\=\_s*)" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment else - ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*\h\w*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment - ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*\h\w*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment + ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment endif " Parameter Dereferencing: {{{1 " ======================== -" Note: sh04 failure with following line -"if !exists("g:sh_no_error") && !(exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix")) if !exists("g:sh_no_error") - syn match shDerefWordError "[^}$[~]" contained + syn match shDerefWordError "[^}$[~]" contained endif syn match shDerefSimple "\$\%(\h\w*\|\d\)" nextgroup=@shNoZSList if exists("b:is_kornshell") && !exists("b:is_ksh88") - if exists("b:is_mksh") - syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart - elseif exists("b:generic_korn") - syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n<|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart - else - syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n<]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart - endif + if exists("b:is_mksh") + syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart + elseif exists("b:generic_korn") + syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n<|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart + 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 + 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 + syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart endif syn match shDerefSimple "\$[-#*@!?]" nextgroup=@shNoZSList syn match shDerefSimple "\$\$" nextgroup=@shNoZSList syn match shDerefSimple "\${\d}" nextgroup=@shNoZSList nextgroup=shSpecialStart if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix") - syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList nextgroup=@shSpecialNoZS,shSpecialStart - syn region shDeref matchgroup=PreProc start="\${\$\$" end="}" contains=@shDerefList nextgroup=@shSpecialNoZS,shSpecialStart + syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList nextgroup=@shSpecialNoZS,shSpecialStart + syn region shDeref matchgroup=PreProc start="\${\$\$" end="}" contains=@shDerefList nextgroup=@shSpecialNoZS,shSpecialStart endif " ksh: ${.sh.*} variables: {{{1 " ======================================== if exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh") - syn match shDerefVar contained "\.\+" nextgroup=@shDerefVarList - syn region shDeref matchgroup=PreProc start="\${\ze[\.]" end="}" contains=@shDerefVarList,shDerefPSR,shDerefPPS + syn match shDerefVar contained "\.\+" nextgroup=@shDerefVarList + syn region shDeref matchgroup=PreProc start="\${\ze[\.]" end="}" contains=@shDerefVarList,shDerefPSR,shDerefPPS endif " ksh: ${!var[*]} array index list syntax: {{{1 " ======================================== if (exists("b:is_kornshell") && !exists("b:is_ksh88")) || exists("b:is_posix") - syn region shDeref matchgroup=PreProc start="\${!" end="}" contains=@shDerefVarArray + syn region shDeref matchgroup=PreProc start="\${!" end="}" contains=@shDerefVarArray endif " bash: ${!prefix*} and ${#parameter}: {{{1 " ==================================== if exists("b:is_bash") - syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOffset - syn match shDerefVar contained "{\@<=!\h\w*" nextgroup=@shDerefVarList + syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOffset + syn match shDerefVar contained "{\@<=!\h\w*" nextgroup=@shDerefVarList endif if (exists("b:is_kornshell") && !exists("b:is_ksh88")) - syn match shDerefVar contained "{\@<=!\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList + syn match shDerefVar contained "{\@<=!\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList endif syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOffset,shDerefOpError @@ -722,7 +713,7 @@ syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@s syn match shDerefVar contained "{\@<=\h\w*" nextgroup=@shDerefVarList syn match shDerefVar contained '\d' nextgroup=@shDerefVarList if exists("b:is_kornshell") || exists("b:is_posix") - syn match shDerefVar contained "{\@<=\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList + syn match shDerefVar contained "{\@<=\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList endif " sh ksh bash : ${var[... ]...} array reference: {{{1 @@ -745,50 +736,50 @@ syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" co " bash : ${parameter@operator} transforms parameter (operator∈[uULqEPARa]) syn cluster shDerefPatternList contains=shDerefPattern,shDerefString if !exists("g:sh_no_error") - syn match shDerefOpError contained ":[[:punct:]]" + syn match shDerefOpError contained ":[[:punct:]]" endif syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix") - syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList - syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList - syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern skipnl - syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern - " Match parametric bracket expressions with a leading whitespace character. - syn region shDerefPattern contained matchgroup=shBracketExprDelim start="\[" end="\]" contains=@shBracketExprList,shDoubleQuote nextgroup=shDerefPattern - call s:GenerateBracketExpressionItems({'itemGroup': 'shDerefPattern', 'bracketGroup': 'shBracketExprDelim', 'extraArgs': 'contained nextgroup=shDerefPattern'}) - syn match shDerefEscape contained '\%(\\\\\)*\\.' + syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList + syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList + syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern skipnl + syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern + " Match parametric bracket expressions with a leading whitespace character. + syn region shDerefPattern contained matchgroup=shBracketExprDelim start="\[" end="\]" contains=@shBracketExprList,shDoubleQuote nextgroup=shDerefPattern + call s:GenerateBracketExpressionItems({'itemGroup': 'shDerefPattern', 'bracketGroup': 'shBracketExprDelim', 'extraArgs': 'contained nextgroup=shDerefPattern'}) + syn match shDerefEscape contained '\%(\\\\\)*\\.' endif if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh") && !exists("b:is_ksh93u") && !exists("b:is_ksh2020")) - syn match shDerefOp contained "[,^]\{1,2}" nextgroup=@shDerefPatternList + syn match shDerefOp contained "[,^]\{1,2}" nextgroup=@shDerefPatternList endif if exists("b:is_bash") - syn match shDerefOp contained "@[uULQEPAKa]" + syn match shDerefOp contained "@[uULQEPAKa]" endif syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@" @@ -856,147 +827,147 @@ syn sync match shWhileSync grouphere shRepeat "\" " Default Highlighting: {{{1 " ===================== if !exists("skip_sh_syntax_inits") - hi def link shArithRegion shShellVariables - hi def link shArrayValue shDeref - hi def link shAstQuote shDoubleQuote - hi def link shAtExpr shSetList - hi def link shBkslshSnglQuote shSingleQuote - hi def link shBkslshDblQuote shDOubleQuote - hi def link shBeginHere shRedir - hi def link shCaseBar shConditional - hi def link shCaseCommandSub shCommandSub - hi def link shCaseDoubleQuote shDoubleQuote - hi def link shCaseIn shConditional - hi def link shQuote shOperator - hi def link shCaseSingleQuote shSingleQuote - hi def link shCaseStart shConditional - hi def link shCmdSubRegion shShellVariables - hi def link shColon shComment - hi def link shDerefOp shOperator - hi def link shDerefPOL shDerefOp - hi def link shDerefPPS shDerefOp - hi def link shDerefPSR shDerefOp - hi def link shDeref shShellVariables - hi def link shDerefDelim shOperator - hi def link shDerefSimple shDeref - hi def link shDerefSpecial shDeref - hi def link shDerefString shDoubleQuote - hi def link shDerefVar shDeref - hi def link shDoubleQuote shString - hi def link shEcho shString - hi def link shEchoDelim shOperator - hi def link shEchoQuote shString - hi def link shForPP shLoop - hi def link shFunction Function - hi def link shEmbeddedEcho shString - hi def link shEscape shCommandSub - hi def link shExDoubleQuote shDoubleQuote - hi def link shExSingleQuote shSingleQuote - hi def link shHereDoc shString - hi def link shHereString shRedir - hi def link shHerePayload shHereDoc - hi def link shLoop shStatement - hi def link shSpecialNxt shSpecial - hi def link shNoQuote shDoubleQuote - hi def link shOption shCommandSub - hi def link shPattern shString - hi def link shParen shArithmetic - hi def link shPosnParm shShellVariables - hi def link shQuickComment shComment - hi def link shBQComment shComment - hi def link shRange shOperator - hi def link shRedir shOperator - hi def link shSetListDelim shOperator - hi def link shSetOption shOption - hi def link shSingleQuote shString - hi def link shSource shOperator - hi def link shStringSpecial shSpecial - hi def link shSpecialStart shSpecial - hi def link shSubShRegion shOperator - hi def link shTestOpr shConditional - hi def link shTestPattern shString - hi def link shTestDoubleQuote shString - hi def link shTestSingleQuote shString - hi def link shTouchCmd shStatement - hi def link shVariable shSetList - hi def link shWrapLineOperator shOperator + hi def link shArithRegion shShellVariables + hi def link shArrayValue shDeref + hi def link shAstQuote shDoubleQuote + hi def link shAtExpr shSetList + hi def link shBkslshSnglQuote shSingleQuote + hi def link shBkslshDblQuote shDOubleQuote + hi def link shBeginHere shRedir + hi def link shCaseBar shConditional + hi def link shCaseCommandSub shCommandSub + hi def link shCaseDoubleQuote shDoubleQuote + hi def link shCaseIn shConditional + hi def link shQuote shOperator + hi def link shCaseSingleQuote shSingleQuote + hi def link shCaseStart shConditional + hi def link shCmdSubRegion shShellVariables + hi def link shColon shComment + hi def link shDerefOp shOperator + hi def link shDerefPOL shDerefOp + hi def link shDerefPPS shDerefOp + hi def link shDerefPSR shDerefOp + hi def link shDeref shShellVariables + hi def link shDerefDelim shOperator + hi def link shDerefSimple shDeref + hi def link shDerefSpecial shDeref + hi def link shDerefString shDoubleQuote + hi def link shDerefVar shDeref + hi def link shDoubleQuote shString + hi def link shEcho shString + hi def link shEchoDelim shOperator + hi def link shEchoQuote shString + hi def link shForPP shLoop + hi def link shFunction Function + hi def link shEmbeddedEcho shString + hi def link shEscape shCommandSub + hi def link shExDoubleQuote shDoubleQuote + hi def link shExSingleQuote shSingleQuote + hi def link shHereDoc shString + hi def link shHereString shRedir + hi def link shHerePayload shHereDoc + hi def link shLoop shStatement + hi def link shSpecialNxt shSpecial + hi def link shNoQuote shDoubleQuote + hi def link shOption shCommandSub + hi def link shPattern shString + hi def link shParen shArithmetic + hi def link shPosnParm shShellVariables + hi def link shQuickComment shComment + hi def link shBQComment shComment + hi def link shRange shOperator + hi def link shRedir shOperator + hi def link shSetListDelim shOperator + hi def link shSetOption shOption + hi def link shSingleQuote shString + hi def link shSource shOperator + hi def link shStringSpecial shSpecial + hi def link shSpecialStart shSpecial + hi def link shSubShRegion shOperator + hi def link shTestOpr shConditional + hi def link shTestPattern shString + hi def link shTestDoubleQuote shString + hi def link shTestSingleQuote shString + hi def link shTouchCmd shStatement + hi def link shVariable shSetList + hi def link shWrapLineOperator shOperator - if exists("b:is_bash") - hi def link bashAdminStatement shStatement - hi def link bashSpecialVariables shShellVariables - hi def link bashStatement shStatement - hi def link shCharClass shSpecial - hi def link shDerefOffset shDerefOp - hi def link shDerefLen shDerefOffset - endif - if exists("b:is_kornshell") || exists("b:is_posix") - hi def link kshSpecialVariables shShellVariables - hi def link kshStatement shStatement - endif + if exists("b:is_bash") + hi def link bashAdminStatement shStatement + hi def link bashSpecialVariables shShellVariables + hi def link bashStatement shStatement + hi def link shCharClass shSpecial + hi def link shDerefOffset shDerefOp + hi def link shDerefLen shDerefOffset + endif + if exists("b:is_kornshell") || exists("b:is_posix") + hi def link kshSpecialVariables shShellVariables + hi def link kshStatement shStatement + endif - if !exists("g:sh_no_error") - hi def link shCaseError Error - hi def link shCondError Error - hi def link shCurlyError Error - hi def link shDerefOpError Error - hi def link shDerefWordError Error - hi def link shDoError Error - hi def link shEsacError Error - hi def link shIfError Error - hi def link shInError Error - hi def link shParenError Error - hi def link shTestError Error - if exists("b:is_kornshell") || exists("b:is_posix") - hi def link shDTestError Error - endif - endif + if !exists("g:sh_no_error") + hi def link shCaseError Error + hi def link shCondError Error + hi def link shCurlyError Error + hi def link shDerefOpError Error + hi def link shDerefWordError Error + hi def link shDoError Error + hi def link shEsacError Error + hi def link shIfError Error + hi def link shInError Error + hi def link shParenError Error + hi def link shTestError Error + if exists("b:is_kornshell") || exists("b:is_posix") + hi def link shDTestError Error + endif + endif - hi def link shArithmetic Special - hi def link shBracketExprDelim Delimiter - hi def link shCharClass Identifier - hi def link shCollSymb shCharClass - hi def link shEqClass shCharClass - hi def link shSnglCase Statement - hi def link shCommandSub Special - hi def link shCommandSubBQ shCommandSub - hi def link shSubshare shCommandSub - hi def link shValsub shCommandSub - hi def link shComment Comment - hi def link shConditional Conditional - hi def link shCtrlSeq Special - hi def link shExprRegion Delimiter - hi def link shFunctionKey Function - hi def link shFunctionName Function - hi def link shNumber Number - hi def link shOperator Operator - hi def link shRepeat Repeat - hi def link shSet Statement - hi def link shSetList Identifier - hi def link shShellVariables PreProc - hi def link shSpecial Special - hi def link shSpecialDQ Special - hi def link shSpecialSQ Special - hi def link shSpecialNoZS shSpecial - hi def link shStatement Statement - hi def link shString String - hi def link shTodo Todo - hi def link shAlias Identifier - hi def link shHereDoc01 shRedir - hi def link shHereDoc02 shRedir - hi def link shHereDoc03 shRedir - hi def link shHereDoc04 shRedir - hi def link shHereDoc05 shRedir - hi def link shHereDoc06 shRedir - hi def link shHereDoc07 shRedir - hi def link shHereDoc08 shRedir - hi def link shHereDoc09 shRedir - hi def link shHereDoc10 shRedir - hi def link shHereDoc11 shRedir - hi def link shHereDoc12 shRedir - hi def link shHereDoc13 shRedir - hi def link shHereDoc14 shRedir - hi def link shHereDoc15 shRedir - hi def link shHereDoc16 shRedir + hi def link shArithmetic Special + hi def link shBracketExprDelim Delimiter + hi def link shCharClass Identifier + hi def link shCollSymb shCharClass + hi def link shEqClass shCharClass + hi def link shSnglCase Statement + hi def link shCommandSub Special + hi def link shCommandSubBQ shCommandSub + hi def link shSubshare shCommandSub + hi def link shValsub shCommandSub + hi def link shComment Comment + hi def link shConditional Conditional + hi def link shCtrlSeq Special + hi def link shExprRegion Delimiter + hi def link shFunctionKey Function + hi def link shFunctionName Function + hi def link shNumber Number + hi def link shOperator Operator + hi def link shRepeat Repeat + hi def link shSet Statement + hi def link shSetList Identifier + hi def link shShellVariables PreProc + hi def link shSpecial Special + hi def link shSpecialDQ Special + hi def link shSpecialSQ Special + hi def link shSpecialNoZS shSpecial + hi def link shStatement Statement + hi def link shString String + hi def link shTodo Todo + hi def link shAlias Identifier + hi def link shHereDoc01 shRedir + hi def link shHereDoc02 shRedir + hi def link shHereDoc03 shRedir + hi def link shHereDoc04 shRedir + hi def link shHereDoc05 shRedir + hi def link shHereDoc06 shRedir + hi def link shHereDoc07 shRedir + hi def link shHereDoc08 shRedir + hi def link shHereDoc09 shRedir + hi def link shHereDoc10 shRedir + hi def link shHereDoc11 shRedir + hi def link shHereDoc12 shRedir + hi def link shHereDoc13 shRedir + hi def link shHereDoc14 shRedir + hi def link shHereDoc15 shRedir + hi def link shHereDoc16 shRedir endif " Delete shell folding commands {{{1 @@ -1012,13 +983,13 @@ delfun s:GenerateBracketExpressionItems " Set Current Syntax: {{{1 " =================== if exists("b:is_bash") - let b:current_syntax = "bash" + let b:current_syntax = "bash" elseif exists("b:is_kornshell") - let b:current_syntax = "ksh" + let b:current_syntax = "ksh" elseif exists("b:is_posix") - let b:current_syntax = "posix" + let b:current_syntax = "posix" else - let b:current_syntax = "sh" + let b:current_syntax = "sh" endif " vim: ts=16 fdm=marker