codekingpro/portable-devtools
114k
1" Vim syntax file2" Language: shell (sh) Korn shell (ksh) bash (sh)3" Maintainer: This runtime file is looking for a new maintainer.4" Previous Maintainers: Charles E. Campbell5" Lennart Schultz <Lennart.Schultz@ecmwf.int>6" Last Change: 2024 Mar 04 by Vim Project {{{17" 2024 Nov 03 by Aliaksei Budavei <0x000c70 AT gmail DOT com> improved bracket expressions, #159418" 2025 Jan 06 add $PS0 to bashSpecialVariables #163949" 2025 Jan 18 add bash coproc, remove duplicate syn keywords #1646710" 2025 Mar 21 update shell capability detection #1693911" 2025 Apr 03 command substitution opening paren at EOL #1702612" 2025 Apr 10 improve shell detection #1708413" 2025 Apr 29 match escaped chars in test operands #1722114" 2025 May 06 improve single-quote string matching in parameter expansions15" 2025 May 06 match KornShell compound arrays16" 2025 May 10 improve wildcard character class lists17" 2025 May 21 improve supported KornShell features18" 2025 Jun 16 change how sh_fold_enabled is reset #1755719" 2025 Jul 18 properly delete :commands #1778520" 2025 Aug 23 bash: add support for ${ cmd;} and ${|cmd;} #1808421" 2025 Sep 23 simplify ksh logic, update sh statements #1835522" 2026 Jan 15 highlight command switches that contain a digit23" 2026 Feb 11 improve support for KornShell function names and variables24" 2026 Feb 15 improve comment handling #1941425" 2026 Mar 23 improve matching of function definitions #1963826" 2026 Apr 02 improve matching of function definitions #1984927" }}}28" Version: 20829" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH30" For options and settings, please use: :help ft-sh-syntax31" This file includes many ideas from Eric Brunet (eric.brunet@ens.fr) and heredoc fixes from Felipe Contreras32 33" quit when a syntax file was already loaded {{{134if exists("b:current_syntax")35 finish36endif37 38" Ensure this is set unless we find another shell39let b:is_sh = 140 41" If the shell script itself specifies which shell to use, use it42let s:shebang = getline(1)43 44if s:shebang =~ '^#!.\{-2,}\<ksh\>'45 " The binary is too ambiguous (i.e. '/bin/ksh' or some such).46 let b:is_kornshell = 147 let b:generic_korn = 148elseif s:shebang =~ '^#!.\{-2,}\<ksh93u\+\>'49 " ksh93u+ (or 93u-) release (still much too common to encounter)50 let b:is_kornshell = 151 let b:is_ksh93u = 152elseif s:shebang =~ '^#!.\{-2,}\<ksh93v\>'53 " ksh93v- alpha or beta54 let b:is_kornshell = 155 let b:is_ksh93v = 156elseif s:shebang =~ '^#!.\{-2,}\<ksh93\>'57 " Could be any ksh93 release58 let b:is_kornshell = 159 let b:is_ksh93 = 160elseif s:shebang =~ '^#!.\{-2,}\<ksh2020\>'61 let b:is_kornshell = 162 let b:is_ksh2020 = 163elseif s:shebang =~ '^#!.\{-2,}\<ksh88\>'64 " The actual AT&T ksh88 and its feature set is assumed.65 let b:is_kornshell = 166 let b:is_ksh88 = 167elseif s:shebang =~ '^#!.\{-2,}\<mksh\>'68 " MirBSD Korn Shell69 let b:is_kornshell = 170 let b:is_mksh = 171elseif s:shebang =~ '^#!.\{-2,}\<bash\>'72 let b:is_bash = 173elseif s:shebang =~ '^#!.\{-2,}\<dash\>'74 let b:is_dash = 175" handling /bin/sh with is_kornshell/is_sh {{{176" b:is_sh will be set when "#! /bin/sh" is found;77" However, it often is just a masquerade by bash (typically Linux)78" or kornshell (typically workstations with Posix "sh").79" So, when the user sets "g:is_kornshell", "g:is_bash",80" "g:is_posix" or "g:is_dash", a b:is_sh is converted into81" b:is_kornshell/b:is_bash/b:is_posix/b:is_dash, respectively.82elseif !exists("b:is_kornshell") && !exists("b:is_bash") && !exists("b:is_posix") && !exists("b:is_dash")83 if exists("g:is_kornshell")84 let b:is_kornshell= 185 let b:generic_korn = 186 elseif exists("g:is_bash")87 let b:is_bash= 188 elseif exists("g:is_dash")89 let b:is_dash= 190 elseif exists("g:is_posix")91 let b:is_posix= 192 elseif exists("g:is_sh")93 let b:is_sh= 194 else95 " user did not specify which shell to use, and96 " the script itself does not specify which shell to use. FYI: /bin/sh is ambiguous.97 " Assuming /bin/sh is executable, and if its a link, find out what it links to.98 let s:shell = ""99 if executable("/bin/sh")100 let s:shell = resolve("/bin/sh")101 elseif executable("/usr/bin/sh")102 let s:shell = resolve("/usr/bin/sh")103 endif104 if s:shell =~ '\<ksh\>'105 " The binary is too ambiguous (i.e. '/bin/ksh' or some such).106 let b:is_kornshell = 1107 let b:generic_korn = 1108 elseif s:shell =~ '\<ksh93u\+\>'109 " ksh93u+ (or 93u-) release (still much too common to encounter)110 let b:is_kornshell = 1111 let b:is_ksh93u = 1112 elseif s:shell =~ '\<ksh93v\>'113 " ksh93v- alpha or beta114 let b:is_kornshell = 1115 let b:is_ksh93v = 1116 elseif s:shell =~ '\<ksh93\>'117 " Could be any ksh93 release118 let b:is_kornshell = 1119 let b:is_ksh93 = 1120 elseif s:shebang =~ '\<ksh2020\>'121 let b:is_kornshell = 1122 let b:is_ksh2020 = 1123 elseif s:shell =~ '\<ksh88\>'124 " The actual AT&T ksh88 and its feature set is assumed.125 let b:is_kornshell = 1126 let b:is_ksh88 = 1127 elseif s:shell =~ '\<mksh\>'128 " MirBSD Korn Shell129 let b:is_kornshell = 1130 let b:is_mksh = 1131 elseif s:shell =~ '\<bash\>'132 let b:is_bash = 1133 elseif s:shell =~ '\<dash\>'134 let b:is_dash = 1135 else136 let b:is_posix = 1137 endif138 unlet s:shell139 endif140endif141 142unlet s:shebang143 144" if b:is_dash, set b:is_posix too145if exists("b:is_dash")146 let b:is_posix= 1147endif148 149if exists("b:is_kornshell") || exists("b:is_bash")150 if exists("b:is_sh")151 unlet b:is_sh152 endif153endif154 155" set up default g:sh_fold_enabled {{{1156" ================================157if !exists("g:sh_fold_enabled")158 let g:sh_fold_enabled= 0159elseif g:sh_fold_enabled != 0 && !has("folding")160 echomsg "Ignoring g:sh_fold_enabled=".g:sh_fold_enabled."; need to re-compile vim for +fold support"161 let g:sh_fold_enabled= 0162endif163let s:sh_fold_functions= and(g:sh_fold_enabled,1)164let s:sh_fold_heredoc = and(g:sh_fold_enabled,2)165let s:sh_fold_ifdofor = and(g:sh_fold_enabled,4)166if g:sh_fold_enabled && &fdm == "manual"167 " Given that the user provided g:sh_fold_enabled168 " AND g:sh_fold_enabled is manual (usual default)169 " implies a desire for syntax-based folding170 setl fdm=syntax171endif172 173" set up the syntax-highlighting for iskeyword174if (v:version == 704 && has("patch-7.4.1142")) || v:version > 704175 if !exists("g:sh_syntax_isk") || (exists("g:sh_syntax_isk") && g:sh_syntax_isk)176 if exists("b:is_bash")177 exe "syn iskeyword ".&iskeyword.",-,:"178 elseif exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh")179 exe "syn iskeyword ".&iskeyword.",-,."180 else181 exe "syn iskeyword ".&iskeyword.",-"182 endif183 endif184endif185 186" Set up folding commands for shell {{{1187" =================================188if exists(":ShFoldFunctions") == 2189 delc ShFoldFunctions190endif191if exists(":ShFoldIfHereDoc") == 2192 delc ShFoldHereDoc193endif194if exists(":ShFoldIfDoFor") == 2195 delc ShFoldIfDoFor196endif197if s:sh_fold_functions198 com! -nargs=* ShFoldFunctions <args> fold199else200 com! -nargs=* ShFoldFunctions <args>201endif202if s:sh_fold_heredoc203 com! -nargs=* ShFoldHereDoc <args> fold204else205 com! -nargs=* ShFoldHereDoc <args>206endif207if s:sh_fold_ifdofor208 com! -nargs=* ShFoldIfDoFor <args> fold209else210 com! -nargs=* ShFoldIfDoFor <args>211endif212 213" Generate bracket expression items {{{1214" =================================215" Note that the following function can be invoked as many times as necessary216" provided that these constraints hold for the passed dictionary argument:217" - every time a unique group-name value is assigned to the "itemGroup" key;218" - only ONCE either the "extraArgs" key is not entered or it is entered and219" its value does not have "contained" among other optional arguments (":help220" :syn-arguments").221fun! s:GenerateBracketExpressionItems(dict) abort222 let itemGroup = a:dict.itemGroup223 let bracketGroup = a:dict.bracketGroup224 let invGroup = itemGroup . 'Inv'225 let skipLeftBracketGroup = itemGroup . 'SkipLeftBracket'226 let skipRightBracketGroup = itemGroup . 'SkipRightBracket'227 let extraArgs = has_key(a:dict, 'extraArgs') ? a:dict.extraArgs : ''228 229 " Make the leading "[!^]" stand out in a NON-matching expression.230 exec 'syn match ' . invGroup . ' contained "\[\@<=[!^]"'231 232 " Set up indirections for unbalanced-bracket highlighting.233 exec 'syn region ' . skipRightBracketGroup . ' contained matchgroup=' . bracketGroup . ' start="\[\%([!^]\=\\\=\]\)\@=" matchgroup=shCollSymb end="\[\.[^]]\{-}\][^]]\{-}\.\]" matchgroup=' . itemGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . invGroup234 exec 'syn region ' . skipLeftBracketGroup . ' contained matchgroup=' . bracketGroup . ' start="\[\%([!^]\=\\\=\]\)\@=" skip="[!^]\=\\\=\]\%(\[[^]]\+\]\|[^]]\)\{-}\%(\[[:.=]\@!\)\@=" matchgroup=' . itemGroup . ' end="\[[:.=]\@!" contains=@shBracketExprList,shDoubleQuote,' . invGroup235 236 " Look for a general matching expression.237 exec 'syn region ' . itemGroup . ' matchgroup=' . bracketGroup . ' start="\[\S\@=" end="\]" contains=@shBracketExprList,shDoubleQuote ' . extraArgs238 " Look for a general NON-matching expression.239 exec 'syn region ' . itemGroup . ' matchgroup=' . bracketGroup . ' start="\[[!^]\@=" end="\]" contains=@shBracketExprList,shDoubleQuote,' . invGroup . ' ' . extraArgs240 241 " Accommodate unbalanced brackets in bracket expressions. The supported242 " syntax for a plain "]" can be: "[]ws]" and "[^]ws]"; or, "[ws[.xs]ys.]zs]"243 " and "[^ws[.xs]ys.]zs]"; see §9.3.5 RE Bracket Expression (in XBD).244 exec 'syn region ' . itemGroup . ' matchgroup=NONE start="\[[!^]\=\\\=\]" matchgroup=' . bracketGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . skipRightBracketGroup . ' ' . extraArgs245 " Strive to handle "[]...[]" etc.246 exec 'syn region ' . itemGroup . ' matchgroup=NONE start="\[[!^]\=\\\=\]\%(\[[^]]\+\]\|[^]]\)\{-}\[[:.=]\@!" matchgroup=' . bracketGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . skipLeftBracketGroup . ' ' . extraArgs247 248 if !exists("g:skip_sh_syntax_inits")249 exec 'hi def link ' . skipLeftBracketGroup . ' ' . itemGroup250 exec 'hi def link ' . skipRightBracketGroup . ' ' . itemGroup251 exec 'hi def link ' . invGroup . ' Underlined'252 endif253endfun254 255call s:GenerateBracketExpressionItems({'itemGroup': 'shBracketExpr', 'bracketGroup': 'shBracketExprDelim'})256 257" sh syntax is case sensitive {{{1258syn case match259 260" Clusters: contains=@... clusters {{{1261"==================================262syn cluster shErrorList contains=shDoError,shIfError,shInError,shCaseError,shEsacError,shCurlyError,shParenError,shTestError,shOK263if exists("b:is_kornshell") || exists("b:is_bash")264 syn cluster ErrorList add=shDTestError265endif266syn 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,shFor267syn cluster shArithList contains=@shArithParenList,shParenError268syn cluster shBracketExprList contains=shCharClassOther,shCharClass,shCollSymb,shEqClass269syn cluster shCaseEsacList contains=shCaseStart,shCaseLabel,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial,shCaseRange270syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shComment,shDblBrace,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq271if exists("b:is_kornshell") || exists("b:is_bash")272 syn cluster shCaseList add=shForPP,shDblParen273endif274syn 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,shVariable275syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial276" COMBAK: removing shEscape from shDblQuoteList fails ksh04:43 -- Jun 09, 2022: I don't see the problem with ksh04, so am reinstating shEscape277syn cluster shDblQuoteList contains=shArithmetic,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shDeref,shDerefSimple,shEscape,shPosnParm,shCtrlSeq,shSpecial,shSpecialDQ278syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPSR,shDerefPPS279syn cluster shDerefVarList contains=shDerefOffset,shDerefOp,shDerefVarArray,shDerefOpError280syn cluster shEchoList contains=shArithmetic,shBracketExpr,shCommandSub,shCommandSubBQ,shDerefVarArray,shSubshare,shValsub,shDeref,shDerefSimple,shEscape,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote281syn cluster shExprList1 contains=shBracketExpr,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq282syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest283syn cluster shFunctionCmds contains=shFor,shCaseEsac,shIf,shRepeat,shDblBrace,shDblParen284if exists("b:is_ksh88") || exists("b:is_mksh")285 " Offer "shFunctionCmds" as is.286elseif exists("b:is_kornshell") || exists("b:is_bash")287 syn cluster shFunctionCmds add=shForPP288else289 syn cluster shFunctionCmds remove=shDblBrace,shDblParen290endif291syn cluster shFunctionDefList contains=shDoError,shIfError,shFunctionKey,shFunctionOne,shFunctionThree,shFunctionCmdOne292syn cluster shFunctionList contains=shBracketExpr,@shCommandSubList,shCaseEsac,shColon,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shOption,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq,@shFunctionDefList293if exists("b:is_kornshell") || exists("b:is_bash")294 syn cluster shFunctionList add=shRepeat,shDblBrace,shDblParen,shForPP295 syn cluster shDerefList add=shCommandSubList,shEchoDeref296endif297syn cluster shHereBeginList contains=@shCommandSubList298syn cluster shHereList contains=shBeginHere,shHerePayload299syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload300syn cluster shIdList contains=shArithmetic,shCommandSub,shCommandSubBQ,shDerefVarArray,shSubshare,shValsub,shWrapLineOperator,shSetOption,shComment,shDeref,shDerefSimple,shHereString,shNumber,shOperator,shRedir,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial,shAtExpr301syn cluster shIfList contains=@shLoopList,shDblBrace,shDblParen,@shFunctionDefList302syn cluster shLoopList contains=@shCaseList,@shErrorList,shCaseEsac,shConditional,shDblBrace,shExpr,shFor,shIf,shOption,shSet,shTest,shTestOpr,shTouch303if exists("b:is_kornshell") || exists("b:is_bash")304 syn cluster shLoopList add=shForPP,shDblParen305endif306syn 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,shVariable307syn cluster shPPSRightList contains=shDeref,shDerefSimple,shEscape,shPosnParm308syn cluster shSubShList contains=shBracketExpr,@shCommandSubList,shCommandSubBQ,shSubshare,shValsub,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator309syn cluster shTestList contains=shArithmetic,shBracketExpr,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shSpecialDQ,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr310syn cluster shNoZSList contains=shSpecialNoZS311syn cluster shForList contains=shTestOpr,shNumber,shDerefSimple,shDeref,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shArithmetic312 313" Echo: {{{1314" ====315" This one is needed INSIDE a CommandSub, so that `echo bla` be correct316if (exists("b:is_kornshell") && !exists("b:is_ksh88"))317 syn region shEcho matchgroup=shStatement start="\<echo\>" 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=shQuickComment318 syn region shEcho matchgroup=shStatement start="\<print\>" 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=shQuickComment319else320 syn region shEcho matchgroup=shStatement start="\<echo\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment321 syn region shEcho matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment322endif323if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")324 syn region shEchoDeref contained matchgroup=shStatement start="\<echo\>" skip="\\$" matchgroup=shEchoDelim end="$" end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment325 syn region shEchoDeref contained matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shEchoDelim end="$" end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment326endif327syn match shEchoQuote contained '\%(\\\\\)*\\["`'()]'328 329" This must be after the strings, so that ... \" will be correct330syn region shEmbeddedEcho contained matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|`)]"me=e-1 end="\d[<>]"me=e-2 end="\s#"me=e-2 contains=shBracketExpr,shNumber,shExSingleQuote,shSingleQuote,shDeref,shDerefSimple,shSpecialVar,shOperator,shExDoubleQuote,shDoubleQuote,shCtrlSeq331 332" Alias: {{{1333" =====334if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")335 syn match shStatement "\<alias\>"336 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\h[-._[:alnum:]]*\)\@=" skip="\\$" end="\>\|`"337 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\h[-._[:alnum:]]*=\)\@=" skip="\\$" end="="338 339 " Touch: {{{1340 " =====341 syn match shTouch '\<touch\>[^;#]*' skipwhite nextgroup=shComment contains=shTouchCmd,shDoubleQuote,shSingleQuote,shDeref,shDerefSimple342 syn match shTouchCmd '\<touch\>' contained343endif344 345" Error Codes: {{{1346" ============347if !exists("g:sh_no_error")348 syn match shDoError "\<done\>"349 syn match shIfError "\<fi\>"350 syn match shInError "\<in\>"351 syn match shCaseError ";;"352 syn match shEsacError "\<esac\>"353 syn match shCurlyError "}"354 syn match shParenError ")"355 syn match shOK '\.\(done\|fi\|in\|esac\)'356 if exists("b:is_kornshell") || exists("b:is_bash")357 syn match shDTestError "]]"358 endif359 syn match shTestError "]"360endif361 362" Options: {{{1363" ====================364syn match shOption "\s\zs[-+][-_a-zA-Z#@0-9]\+"365syn match shOption "\s\zs--[^ \t$=`'"|);]\+"366 367" File Redirection Highlighted As Operators: {{{1368"===========================================369syn match shRedir "\d\=>\(&[-0-9]\)\="370syn match shRedir "\d\=>>-\="371syn match shRedir "\d\=<\(&[-0-9]\)\="372syn match shRedir "\d<<-\="373 374" Operators: {{{1375" ==========376syn match shOperator "<<\|>>" contained377syn match shOperator "[!&;|]" contained378syn match shOperator "[-=/*+%]\==" skipwhite nextgroup=shPattern379syn match shPattern "\<\S\+\())\)\@=" contained contains=shExSingleQuote,shSingleQuote,shExDoubleQuote,shDoubleQuote,shDeref380 381" Subshells: {{{1382" ==========383syn region shExpr transparent matchgroup=shExprRegion start="{" end="}" contains=@shExprList2 nextgroup=shSpecialNxt384syn region shSubSh transparent matchgroup=shSubShRegion start="[^(]\zs(" end=")" contains=@shSubShList nextgroup=shSpecialNxt385 386" Tests: {{{1387"=======388syn region shExpr matchgroup=shRange start="\[\s\@=" skip=+\\\\\|\\$\|\[+ end="\]" contains=@shTestList,shSpecial389syn region shTest transparent matchgroup=shStatement start="\<test\s" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1390syn region shNoQuote start='\S' skip='\%(\\\\\)*\\.' end='\ze\s' end="\ze['"]" contained contains=shBracketExpr,shDerefSimple,shDeref,shEscape391syn match shAstQuote contained '\*\ze"' nextgroup=shString392syn match shTestOpr contained '[^-+/%]\zs=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern393syn match shTestOpr contained "<=\|>=\|!=\|==\|=\~\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]"394syn match shTestPattern contained '\w\+'395syn region shTestDoubleQuote contained start='\%(\%(\\\\\)*\\\)\@<!"' skip=+\\\\\|\\"+ end='"' contains=shDeref,shDerefSimple,shDerefSpecial396syn match shTestSingleQuote contained '\\.' nextgroup=shTestSingleQuote397syn match shTestSingleQuote contained "'[^']*'"398if exists("b:is_kornshell") || exists("b:is_bash")399 syn region shDblBrace matchgroup=Delimiter start="\[\[\s\@=" skip=+\%(\\\\\)*\\$+ end="\]\]" contains=@shTestList,shAstQuote,shNoQuote,shComment400 syn region shDblParen matchgroup=Delimiter start="((" skip=+\%(\\\\\)*\\$+ end="))" contains=@shTestList,shComment401endif402 403" Character Class In Range: {{{1404" =========================405syn match shCharClassOther contained "\[:\w\{-}:\]"406syn match shCharClass contained "\[:\%(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\):\]"407syn match shCollSymb contained "\[\..\{-}\.\]"408syn match shEqClass contained "\[=.\{-}=\]"409 410" Loops: do, if, while, until {{{1411" ======412ShFoldIfDoFor syn region shDo transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList413ShFoldIfDoFor syn region shIf transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional skip=+-fi\>+ end="\<;\_s*then\>" end="\<fi\>" contains=@shIfList414ShFoldIfDoFor syn region shFor matchgroup=shLoop start="\<for\ze\_s\s*\%(((\)\@!" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn415if exists("b:is_kornshell") || exists("b:is_bash")416 ShFoldIfDoFor syn region shForPP matchgroup=shLoop start='\<for\>\_s*((' end='))' contains=@shForList417endif418 419if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")420 syn cluster shCaseList add=shRepeat421 syn cluster shFunctionList add=shRepeat422 syn region shRepeat matchgroup=shLoop start="\<while\_s" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace423 syn region shRepeat matchgroup=shLoop start="\<until\_s" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace424 if !exists("b:is_posix")425 syn region shCaseEsac matchgroup=shConditional start="\<select\s" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList426 endif427else428 syn region shRepeat matchgroup=shLoop start="\<while\_s" end="\<do\>"me=e-2 contains=@shLoopList429 syn region shRepeat matchgroup=shLoop start="\<until\_s" end="\<do\>"me=e-2 contains=@shLoopList430endif431syn region shCurlyIn contained matchgroup=Delimiter start="{" end="}" contains=@shCurlyList432syn match shComma contained ","433 434" Case: case...esac {{{1435" ====436syn match shCaseBar contained skipwhite "\(^\|[^\\]\)\(\\\\\)*\zs|" nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote437syn match shCaseStart contained skipwhite skipnl "(" nextgroup=shCase,shCaseBar438syn match shCaseLabel contained skipwhite "\%(\\.\|[-a-zA-Z0-9_*.]\)\+" contains=shBracketExpr439if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_ksh93u") && !exists("b:is_ksh93v") && !exists("b:is_ksh2020"))440 ShFoldIfDoFor syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)" end=";;" end=";&" end=";;&" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment441elseif exists("b:is_kornshell")442 ShFoldIfDoFor syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)" end=";;" end=";&" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment443else444 ShFoldIfDoFor syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)" end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment445endif446ShFoldIfDoFor syn region shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList447 448syn keyword shCaseIn contained skipwhite skipnl in nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote449if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88"))450 syn region shCaseExSingleQuote matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial skipwhite skipnl nextgroup=shCaseBar contained451elseif !exists("g:sh_no_error")452 syn region shCaseExSingleQuote matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained453endif454syn region shCaseSingleQuote matchgroup=shQuote start=+'+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained455syn region shCaseDoubleQuote matchgroup=shQuote start=+"+ skip=+\\\\\|\\.+ end=+"+ contains=@shDblQuoteList,shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained456syn region shCaseCommandSub start=+`+ skip=+\\\\\|\\.+ end=+`+ contains=@shCommandSubList skipwhite skipnl nextgroup=shCaseBar contained457call s:GenerateBracketExpressionItems({'itemGroup': 'shCaseRange', 'bracketGroup': 'shBracketExprDelim', 'extraArgs': 'skip=+\\\\+ contained'})458if exists("b:is_bash")459 syn match shCharClass "\[:\%(alnum\|alpha\|ascii\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|word\|xdigit\):\]" contained460elseif exists("b:is_kornshell")461 syn match shCharClass "\[:\%(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|word\|xdigit\):\]" contained462endif463" Misc: {{{1464"======465syn match shWrapLineOperator "\\$"466syn region shCommandSubBQ start="`" skip="\\\\\|\\." end="`" contains=shBQComment,@shCommandSubList467syn match shEscape contained '\%(^\)\@!\%(\\\\\)*\\.'468 469" $() and $(()): {{{1470" $(..) is not supported by sh (Bourne shell). However, apparently471" some systems (HP?) have as their /bin/sh a (link to) Korn shell472" (ie. Posix compliant shell). /bin/ksh should work for those473" systems too, however, so the following syntax will flag $(..) as474" an Error under /bin/sh. By consensus of vimdev'ers!475if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")476 syn region shCommandSub matchgroup=shCmdSubRegion start="\$((\@!" skip='\\\\\|\\.' end=")" contains=@shCommandSubList477 if exists("b:is_kornshell")478 if !exists("b:is_ksh88")479 if exists("b:is_mksh")480 syn region shSubshare matchgroup=shCmdSubRegion start="\${\ze[ \t\n]" skip='\\\\\|\\.' end="\zs[ \t\n;]}" contains=@shCommandSubList481 else482 syn region shSubshare matchgroup=shCmdSubRegion start="\${\ze[ \t\n<]" skip='\\\\\|\\.' end="\zs[ \t\n;]}" contains=@shCommandSubList483 endif484 endif485 if exists("b:is_mksh") || exists("b:generic_korn")486 syn region shValsub matchgroup=shCmdSubRegion start="\${|" skip='\\\\\|\\.' end="}" contains=@shCommandSubList487 endif488 elseif exists("b:is_bash")489 syn region shSubshare matchgroup=shCmdSubRegion start="\${\ze[ \t\n]" skip='\\\\\|\\.' end="\zs[;\n][ \t\n]*}" contains=@shCommandSubList490 syn region shValsub matchgroup=shCmdSubRegion start="\${|" skip='\\\\\|\\.' end="[;\n][ \t\n]*}" contains=@shCommandSubList491 endif492 syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList493 syn region shArithmetic matchgroup=shArithRegion start="\$\[" skip='\\\\\|\\.' end="\]" contains=@shArithList494 syn match shSkipInitWS contained "^\s\+"495 syn region shArithParen matchgroup=shArithRegion contained start="(" end=")" contains=@shArithParenList496elseif !exists("g:sh_no_error")497 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList498endif499syn region shCmdParenRegion matchgroup=shCmdSubRegion start="((\@!" skip='\\\\\|\\.' end=")" contains=@shCommandSubList500 501if exists("b:is_bash")502 syn cluster shCommandSubList add=bashSpecialVariables,bashStatement503 syn cluster shCaseList add=bashAdminStatement,bashStatement504 syn keyword bashSpecialVariables contained auto_resume BASH BASH_ALIASES BASH_ARGC BASH_ARGV BASH_CMDS BASH_COMMAND BASH_ENV BASH_EXECUTION_STRING BASH_LINENO BASHOPTS BASHPID BASH_REMATCH BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION BASH_XTRACEFD CDPATH COLUMNS COMP_CWORD COMP_KEY COMP_LINE COMP_POINT COMPREPLY COMP_TYPE COMP_WORDBREAKS COMP_WORDS COPROC COPROC_PID DIRSTACK EMACS ENV EUID FCEDIT FIGNORE FUNCNAME FUNCNEST GLOBIGNORE GROUPS histchars HISTCMD HISTCONTROL HISTFILE HISTFILESIZE HISTIGNORE HISTSIZE HISTTIMEFORMAT HOME HOSTFILE HOSTNAME HOSTTYPE IFS IGNOREEOF INPUTRC LANG LC_ALL LC_COLLATE LC_CTYPE LC_MESSAGES LC_NUMERIC LINENO LINES MACHTYPE MAIL MAILCHECK MAILPATH MAPFILE OLDPWD OPTARG OPTERR OPTIND OSTYPE PATH PIPESTATUS POSIXLY_CORRECT PPID PROMPT_COMMAND PS0 PS1 PS2 PS3 PS4 PWD RANDOM READLINE_LINE READLINE_POINT REPLY SECONDS SHELL SHELLOPTS SHLVL TIMEFORMAT TIMEOUT TMPDIR UID505 syn keyword bashStatement bind builtin caller compgen complete compopt declare dirs disown enable fg help history let logout mapfile popd pushd readarray shopt source suspend time506 syn keyword bashStatement typeset nextgroup=shSetOption507 syn keyword bashAdminStatement reload restart start status stop508endif509 510" for all kornshells511if exists("b:is_kornshell")512 syn cluster shCaseList add=kshStatement513 syn cluster shCommandSubList add=kshSpecialVariables,kshStatement514 syn keyword kshSpecialVariables contained CDPATH COLUMNS EDITOR ENV FCEDIT FIGNORE FPATH HISTCMD HISTEDIT HISTFILE HISTSIZE HOME IFS JOBMAX KSH_VERSION LANG LC_ALL LC_COLLATE LC_CTYPE LC_MESSAGES LC_NUMERIC LC_TIME LINENO LINES MAIL MAILCHECK MAILPATH OLDPWD OPTARG OPTIND PATH PPID PS1 PS2 PS3 PS4 PWD RANDOM REPLY SECONDS SHELL SHLVL TMOUT VISUAL515 syn keyword kshStatement autoload builtin compound disown enum fg float functions hist history integer let nameref r redirect source stop suspend time whence516 syn keyword shStatement typeset skipwhite nextgroup=shSetOption517endif518 519" kornshell flavors520if exists("b:generic_korn")521 syn keyword kshSpecialVariables contained BASHPID EPOCHREALTIME ERRNO EXECSHELL KSHEGID KSHGID KSHUID KSH_MATCH PATHSEP PGRP PIPESTATUS TMPDIR USER_ID SH_OPTIONS COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS COMP_KEY COMPREPLY COMP_WORDBREAKS COMP_TYPE VPATH SRANDOM SYSTYPE CSWIDTH .sh .sh.edchar .sh.edcol .sh.edtext .sh.edmode .sh.name .sh.subscript .sh.value .sh.version .sh.match .sh.command .sh.file .sh.fun .sh.subshell .sh.level .sh.lineno .sh.stats .sh.math .sh.pid .sh.ppid .sh.tilde .sh.dollar .sh.pool .sh.pgrp .sh.pwdfd .sh.op_astbin .sh.sig .sh.sig.addr .sh.sig.band .sh.sig.code .sh.sig.errno .sh.sig.name .sh.sig.pid .sh.sig.signo .sh.sig.status .sh.sig.uid .sh.sig.value .sh.sig.value.q .sh.sig.value.Q .sh.stats .sh.stats.arg_cachehits .sh.stats.arg_expands .sh.stats.comsubs .sh.stats.forks .sh.stats.funcalls .sh.stats.globs .sh.stats.linesread .sh.stats.nv_cachehit .sh.stats.nv_opens .sh.stats.pathsearch .sh.stats.posixfuncall .sh.stats.simplecmds .sh.stats.spawns .sh.stats.subshell .sh.install_prefix522 syn keyword kshStatement alarm bind compgen complete eloop fds mkservice pids poll sha2sum vmstate xgrep523elseif exists("b:is_ksh88")524 syn keyword kshSpecialVariables contained ERRNO525elseif exists("b:is_ksh93")526 syn keyword kshSpecialVariables contained COMP_CWORD COMP_KEY COMP_LINE COMP_POINT COMPREPLY COMP_TYPE COMP_WORDBREAKS COMP_WORDS CSWIDTH SH_OPTIONS SRANDOM SYSTYPE VPATH .sh .sh.edchar .sh.edcol .sh.edtext .sh.edmode .sh.name .sh.subscript .sh.value .sh.version .sh.match .sh.command .sh.file .sh.fun .sh.subshell .sh.level .sh.lineno .sh.stats .sh.math .sh.pid .sh.ppid .sh.tilde .sh.dollar .sh.pool .sh.pgrp .sh.pwdfd .sh.op_astbin .sh.sig .sh.sig.addr .sh.sig.band .sh.sig.code .sh.sig.errno .sh.sig.name .sh.sig.pid .sh.sig.signo .sh.sig.status .sh.sig.uid .sh.sig.value .sh.sig.value.q .sh.sig.value.Q .sh.stats .sh.stats.arg_cachehits .sh.stats.arg_expands .sh.stats.comsubs .sh.stats.forks .sh.stats.funcalls .sh.stats.globs .sh.stats.linesread .sh.stats.nv_cachehit .sh.stats.nv_opens .sh.stats.pathsearch .sh.stats.posixfuncall .sh.stats.simplecmds .sh.stats.spawns .sh.stats.subshell527 syn keyword kshStatement alarm compgen complete eloop fds mkservice pids poll sha2sum vmstate xgrep528elseif exists("b:is_ksh93v")529 syn keyword kshSpecialVariables contained COMP_CWORD COMP_KEY COMP_LINE COMP_POINT COMPREPLY COMP_TYPE COMP_WORDBREAKS COMP_WORDS CSWIDTH SH_OPTIONS VPATH .sh .sh.edchar .sh.edcol .sh.edtext .sh.edmode .sh.name .sh.subscript .sh.value .sh.version .sh.match .sh.command .sh.file .sh.fun .sh.subshell .sh.level .sh.lineno .sh.stats .sh.math .sh.dollar .sh.pool .sh.pgrp .sh.pwdfd .sh.op_astbin .sh.sig .sh.sig.addr .sh.sig.band .sh.sig.code .sh.sig.errno .sh.sig.name .sh.sig.pid .sh.sig.signo .sh.sig.status .sh.sig.uid .sh.sig.value .sh.sig.value.q .sh.sig.value.Q .sh.stats .sh.stats.arg_cachehits .sh.stats.arg_expands .sh.stats.comsubs .sh.stats.forks .sh.stats.funcalls .sh.stats.globs .sh.stats.linesread .sh.stats.nv_cachehit .sh.stats.nv_opens .sh.stats.pathsearch .sh.stats.posixfuncall .sh.stats.simplecmds .sh.stats.spawns .sh.stats.subshell530 syn keyword kshStatement alarm compgen complete fds pids poll sha2sum vmstate xgrep531elseif exists("b:is_ksh93u")532 syn keyword kshSpecialVariables contained CSWIDTH SYSTYPE VPATH .sh .sh.edchar .sh.edcol .sh.edtext .sh.edmode .sh.name .sh.subscript .sh.value .sh.version .sh.match .sh.command .sh.file .sh.fun .sh.subshell .sh.level .sh.lineno .sh.stats .sh.math .sh.dollar .sh.pool .sh.stats .sh.stats.arg_cachehits .sh.stats.arg_expands .sh.stats.comsubs .sh.stats.forks .sh.stats.funcalls .sh.stats.globs .sh.stats.linesread .sh.stats.nv_cachehit .sh.stats.nv_opens .sh.stats.pathsearch .sh.stats.posixfuncall .sh.stats.simplecmds .sh.stats.spawns .sh.stats.subshell533 syn keyword kshStatement alarm fds pids vmstate534elseif exists("b:is_ksh2020")535 syn keyword kshSpecialVariables contained COMP_CWORD COMP_KEY COMP_LINE COMP_POINT COMPREPLY COMP_TYPE COMP_WORDBREAKS COMP_WORDS SH_OPTIONS .sh .sh.edchar .sh.edcol .sh.edtext .sh.edmode .sh.name .sh.subscript .sh.value .sh.version .sh.match .sh.command .sh.file .sh.fun .sh.subshell .sh.level .sh.lineno .sh.stats .sh.math .sh.dollar .sh.pool .sh.pgrp .sh.pwdfd .sh.op_astbin .sh.sig .sh.sig.addr .sh.sig.band .sh.sig.code .sh.sig.errno .sh.sig.name .sh.sig.pid .sh.sig.signo .sh.sig.status .sh.sig.uid .sh.sig.value .sh.stats .sh.stats.arg_cachehits .sh.stats.arg_expands .sh.stats.comsubs .sh.stats.forks .sh.stats.funcalls .sh.stats.globs .sh.stats.linesread .sh.stats.nv_cachehit .sh.stats.nv_opens .sh.stats.pathsearch .sh.stats.posixfuncall .sh.stats.simplecmds .sh.stats.spawns .sh.stats.subshell .sh.install_prefix536 syn keyword kshStatement compgen complete537elseif exists("b:is_mksh")538 syn keyword kshSpecialVariables contained BASHPID EPOCHREALTIME EXECSHELL KSHEGID KSHGID KSHUID KSH_MATCH PATHSEP PGRP PIPESTATUS TMPDIR USER_ID539 syn keyword kshStatement bind540endif541 542syn match shSource "^\.\s"543syn match shSource "\s\.\s"544if exists("b:is_kornshell") || exists("b:is_posix")545 syn match shColon '^\s*\zs:'546endif547 548" String And Character Constants: {{{1549"================================550syn match shNumber "\<\d\+\>#\="551syn match shNumber "\<-\=\.\=\d\+\>#\="552syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained553if exists("b:is_bash") || exists("b:is_kornshell")554 syn match shSpecial "[^\\]\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained555 syn match shSpecial "^\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained556 syn region shExSingleQuote matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial nextgroup=shSpecialNxt557 syn region shExDoubleQuote matchgroup=shQuote start=+\$"+ skip=+\\\\\|\\.\|\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,shSpecial nextgroup=shSpecialNxt558elseif !exists("g:sh_no_error")559 syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial560 syn region shExDoubleQuote matchGroup=Error start=+\$"+ skip=+\\\\\|\\.+ end=+"+ contains=shStringSpecial561endif562syn region shSingleQuote matchgroup=shQuote start=+'+ end=+'+ contains=@Spell nextgroup=shSpecialStart,shSpecialSQ563syn region shDoubleQuote matchgroup=shQuote start=+\%(\%(\\\\\)*\\\)\@<!"+ skip=+\\.+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell nextgroup=shSpecialStart564syn match shStringSpecial "[^[:print:] \t]" contained565syn match shStringSpecial "[^\\]\zs\%(\\\\\)*\(\\[\\"'`$()#]\)\+" nextgroup=shComment566syn match shSpecialSQ "[^\\]\zs\%(\\\\\)*\(\\[\\"'`$()#]\)\+" contained nextgroup=shBkslshSnglQuote,@shNoZSList567syn match shSpecialDQ "[^\\]\zs\%(\\\\\)*\(\\[\\"'`$()#]\)\+" contained nextgroup=shBkslshDblQuote,@shNoZSList568syn match shSpecialStart "\%(\\\\\)*\\[\\"'`$()#]" contained nextgroup=shBkslshSnglQuote,shBkslshDblQuote,@shNoZSList569syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]"570syn match shSpecialNoZS contained "\%(\\\\\)*\\[\\"'`$()#]"571syn match shSpecialNxt contained "\\[\\"'`$()#]"572 573" Comments: {{{1574"==========575syn cluster shCommentGroup contains=shTodo,@Spell576if exists("b:is_bash")577 syn match shTodo contained "\<\%(COMBAK\|FIXME\|TODO\|XXX\)\ze:\=\>"578else579 syn keyword shTodo contained COMBAK FIXME TODO XXX580endif581syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup582syn match shComment "\s\zs#.*$" contains=@shCommentGroup583syn match shComment contained "#.*$" contains=@shCommentGroup584syn match shQuickComment contained "#.*$" contains=@shCommentGroup585syn match shBQComment contained "#.\{-}\ze`" contains=@shCommentGroup586 587" Here Documents: {{{1588" (modified by Felipe Contreras)589" =========================================590ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc01 start="<<\s*\z([^ \t|>]\+\)" matchgroup=shHereDoc01 end="^\z1$" contains=@shDblQuoteList591ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc02 start="<<-\s*\z([^ \t|>]\+\)" matchgroup=shHereDoc02 end="^\t*\z1$" contains=@shDblQuoteList592ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc03 start="<<\s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc03 end="^\z1$"593ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc04 start="<<-\s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc04 end="^\t*\z1$"594ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc05 start="<<\s*'\z([^']\+\)'" matchgroup=shHereDoc05 end="^\z1$"595ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc06 start="<<-\s*'\z([^']\+\)'" matchgroup=shHereDoc06 end="^\t*\z1$"596ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc07 start="<<\s*\"\z([^"]\+\)\"" matchgroup=shHereDoc07 end="^\z1$"597ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc08 start="<<-\s*\"\z([^"]\+\)\"" matchgroup=shHereDoc08 end="^\t*\z1$"598ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc09 start="<<\s*\\\_$\_s*\z([^ \t|>]\+\)" matchgroup=shHereDoc09 end="^\z1$" contains=@shDblQuoteList599ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc10 start="<<-\s*\\\_$\_s*\z([^ \t|>]\+\)" matchgroup=shHereDoc10 end="^\t*\z1$" contains=@shDblQuoteList600ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc11 start="<<\s*\\\_$\_s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc11 end="^\z1$"601ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc12 start="<<-\s*\\\_$\_s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc12 end="^\t*\z1$"602ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc13 start="<<\s*\\\_$\_s*'\z([^']\+\)'" matchgroup=shHereDoc13 end="^\z1$"603ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc14 start="<<-\s*\\\_$\_s*'\z([^']\+\)'" matchgroup=shHereDoc14 end="^\t*\z1$"604ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc15 start="<<\s*\\\_$\_s*\"\z([^"]\+\)\"" matchgroup=shHereDoc15 end="^\z1$"605ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc16 start="<<-\s*\\\_$\_s*\"\z([^"]\+\)\"" matchgroup=shHereDoc16 end="^\t*\z1$"606 607 608" Here Strings: {{{1609" =============610" available for: bash and ksh (except ksh88) but not if its a posix611if exists("b:is_bash") || ((exists("b:is_kornshell") && !exists("b:is_ksh88")) && !exists("b:is_posix"))612 syn match shHereString "<<<" skipwhite nextgroup=shCmdParenRegion613endif614 615" Identifiers: {{{1616"=============617syn match shSetOption "\s\zs[-+][a-zA-Z0-9]\+\>" contained618syn match shVariable "\<\h\w*\ze=" nextgroup=shVarAssign619if exists("b:is_bash")620 " The subscript form for array values, e.g. "foo=([2]=10 [4]=100)".621 syn region shArrayValue contained start="\[\%(..\{-}\]=\)\@=" end="\]=\@=" contains=@shArrayValueList nextgroup=shVarAssign622 syn cluster shArrayValueList contains=shArithmetic,shArithParen,shCommandSub,shDeref,shDerefSimple,shExpr,shNumber,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shSpecial,shParen,bashSpecialVariables,shParenError623 syn region shArrayRegion contained matchgroup=shShellVariables start="(" skip='\\\\\|\\.' end=")" contains=@shArrayValueList,shArrayValue,shComment624elseif (exists("b:is_kornshell") && !exists("b:is_ksh88"))625 " The subscript form for array values, e.g. "foo=([2]=10 [4]=100)".626 syn region shArrayValue contained start="\[\%(..\{-}\]=\)\@=" end="\]=\@=" contains=@shArrayValueList nextgroup=shVarAssign627 syn cluster shArrayValueList contains=shArithmetic,shArithParen,shCommandSub,shDeref,shDerefSimple,shExpr,shNumber,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shSpecial,shParen,kshSpecialVariables,shParenError628 syn region shArrayRegion contained matchgroup=shShellVariables start="(" skip='\\\\\|\\.' end=")" contains=@shArrayValueList,shArrayValue,shComment,shArrayRegion629endif630if exists("b:is_bash") || exists("b:is_kornshell")631 syn match shVariable "\<\h\w*\%(\[..\{-}\]\)\=\ze\%([|^&*/%+-]\|[<^]<\|[>^]>\)\==" contains=shDerefVarArray nextgroup=shVarAssign632 syn match shVarAssign contained "\%([|^&*/%+-]\|[<^]<\|[>^]>\)\==" nextgroup=shArrayRegion,shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote,shVar633else634 syn match shVarAssign contained "=" nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote,shVar635endif636syn match shVar contained "\h\w*"637syn region shAtExpr contained start="@(" end=")" contains=@shIdList638if exists("b:is_bash")639 syn match shSet "^\s*set\ze\s\+$"640 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=@shIdList641 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=shComment642elseif exists("b:is_kornshell") || exists("b:is_posix")643 syn match shSet "^\s*set\ze\s\+$"644 if exists("b:is_dash")645 syn region shSetList oneline matchgroup=shSet start="\<\%(local\)\>\ze[/]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList646 syn keyword shStatement chdir647 endif648 syn region shSetList oneline matchgroup=shSet start="\<\(export\)\>\ze[/]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList649 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=shComment650else651 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=@shIdList652endif653 654" KornShell namespace: {{{1655if exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh")656 syn keyword shFunctionKey namespace skipwhite skipnl nextgroup=shNamespaceOne657endif658 659" Functions: {{{1660if !exists("b:is_posix")661 syn keyword shFunctionKey function skipwhite skipnl nextgroup=shDoError,shIfError,shFunctionTwo,shFunctionFour,shFunctionCmdTwo662endif663 664ShFoldFunctions syn region shFunctionExpr matchgroup=shFunctionExprRegion start="{" end="}" contains=@shFunctionList contained skipwhite skipnl nextgroup=shQuickComment665ShFoldFunctions syn region shFunctionSubSh matchgroup=shFunctionSubShRegion start="(" end=")" contains=@shFunctionList contained skipwhite skipnl nextgroup=shQuickComment666 667if exists("b:is_bash")668 syn keyword shFunctionKey coproc669 syn match shFunctionCmdOne "\%#=1^\s*\zs\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\s*()\ze\_s*\%(\%(for\|case\|select\|if\|while\|until\)\>\|\[\[\s\|((\)" skipwhite skipnl nextgroup=@shFunctionCmds670 syn match shFunctionCmdTwo "\%#=1\%(\%(\<\k\+\>\|[^()<>|&$;\t ]\+\)\+\)\@>\ze\s*\%(()\ze\)\=\_s*\%(\<\%(for\|case\|select\|if\|while\|until\)\>\|\[\[\s\|((\)" contained skipwhite skipnl nextgroup=@shFunctionCmds671 syn match shFunctionOne "\%#=1^\s*\zs\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\s*()\ze\_s*{" skipwhite skipnl nextgroup=shFunctionExpr672 syn match shFunctionTwo "\%#=1\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\ze\s*\%(()\ze\)\=\_s*{" contained skipwhite skipnl nextgroup=shFunctionExpr673 syn match shFunctionThree "\%#=1^\s*\zs\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\s*()\ze\_s*((\@!" skipwhite skipnl nextgroup=shFunctionSubSh674 syn match shFunctionFour "\%#=1\%(\%(\<\k\+\|[^()<>|&$;\t ]\+\)\+\)\@>\ze\s*\%(\%(()\ze\)\=\)\@>\_s*((\@!" contained skipwhite skipnl nextgroup=shFunctionSubSh675elseif exists("b:is_ksh88")676 " AT&T ksh88677 syn match shFunctionCmdOne "^\s*\zs\h\w*\s*()\ze\_s*\%(\%(for\|case\|select\|if\|while\|until\)\>\|\[\[\s\|((\)" skipwhite skipnl nextgroup=@shFunctionCmds678 syn match shFunctionOne "^\s*\zs\h\w*\s*()\ze\_s*{" skipwhite skipnl nextgroup=shFunctionExpr679 syn match shFunctionTwo "\<\h\w*\>\ze\_s*{" contained skipwhite skipnl nextgroup=shFunctionExpr680 syn match shFunctionThree "^\s*\zs\h\w*\s*()\ze\_s*((\@!" skipwhite skipnl nextgroup=shFunctionSubSh681elseif exists("b:is_mksh")682 " MirBSD ksh is the wild west of absurd and abstruse function names...683 syn match shFunctionCmdOne "^\s*\zs[-A-Za-z_@!+.%,0-9:]*[-A-Za-z_.%,0-9:]\s*()\ze\_s*\%(\%(for\|case\|select\|if\|while\|until\)\>\|\[\[\s\|((\)" skipwhite skipnl nextgroup=@shFunctionCmds684 syn match shFunctionOne "^\s*\zs[-A-Za-z_@!+.%,0-9:]*[-A-Za-z_.%,0-9:]\s*()\ze\_s*{" skipwhite skipnl nextgroup=shFunctionExpr685 syn match shFunctionTwo "\%#=1\%(\%(\<\w\+\|[@!+.%,:-]\+\)*[-A-Za-z_.%,0-9:]\)\@>\ze\s*\%(()\ze\)\=\_s*{" contained skipwhite skipnl nextgroup=shFunctionExpr686 syn match shFunctionThree "^\s*\zs[-A-Za-z_@!+.%,0-9:]*[-A-Za-z_.%,0-9:]\s*()\ze\_s*((\@!" skipwhite skipnl nextgroup=shFunctionSubSh687elseif exists("b:is_kornshell")688 " ksh93689 syn match shFunctionCmdOne "^\s*\zs[A-Za-z_.][A-Za-z_.0-9]*\s*()\ze\_s*\%(\%(for\|case\|select\|if\|while\|until\)\>\|\[\[\s\|((\)" skipwhite skipnl nextgroup=@shFunctionCmds690 syn match shFunctionOne "^\s*\zs[A-Za-z_.][A-Za-z_.0-9]*\s*()\ze\_s*{" skipwhite skipnl nextgroup=shFunctionExpr691 syn match shFunctionTwo "\%(\<\h\+\|\.\)[A-Za-z_.0-9]*\ze\_s*{" contained skipwhite skipnl nextgroup=shFunctionExpr692 syn match shFunctionThree "^\s*\zs[A-Za-z_.][A-Za-z_.0-9]*\s*()\ze\_s*((\@!" skipwhite skipnl nextgroup=shFunctionSubSh693 syn match shNamespaceOne "\<\h\w*\>\ze\_s*{" contained skipwhite skipnl nextgroup=shFunctionExpr694else695 syn match shFunctionCmdOne "^\s*\zs\h\w*\s*()\ze\_s*\%(for\|case\|if\|while\|until\)\>" skipwhite skipnl nextgroup=@shFunctionCmds696 syn match shFunctionCmdTwo "\<\h\w*\s*()\ze\_s*\%(for\|case\|if\|while\|until\)\>" contained skipwhite skipnl nextgroup=@shFunctionCmds697 syn match shFunctionOne "^\s*\zs\h\w*\s*()\ze\_s*{" skipwhite skipnl nextgroup=shFunctionExpr698 syn match shFunctionTwo "\<\h\w*\>\s*()\ze\_s*{" contained skipwhite skipnl nextgroup=shFunctionExpr699 syn match shFunctionThree "^\s*\zs\h\w*\s*()\ze\_s*(" skipwhite skipnl nextgroup=shFunctionSubSh700 syn match shFunctionFour "\<\h\w*\>\s*()\ze\_s*(" contained skipwhite skipnl nextgroup=shFunctionSubSh701endif702 703if !exists("g:sh_no_error")704 syn match shDoError "\<do\%(ne\)\=\s*()"705 syn match shIfError "\<then\s*()"706 syn match shIfError "\<else\s*()"707endif708 709" Parameter Dereferencing: {{{1710" ========================711if !exists("g:sh_no_error")712 syn match shDerefWordError "[^}$[~]" contained713endif714syn match shDerefSimple "\$\%(\h\w*\|\d\)" nextgroup=@shNoZSList715if exists("b:is_kornshell") && !exists("b:is_ksh88")716 if exists("b:is_mksh")717 syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart718 elseif exists("b:generic_korn")719 syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n<|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart720 else721 syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n<]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart722 endif723elseif exists("b:is_bash")724 syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart725else726 syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart727endif728syn match shDerefSimple "\$[-#*@!?]" nextgroup=@shNoZSList729syn match shDerefSimple "\$\$" nextgroup=@shNoZSList730syn match shDerefSimple "\${\d}" nextgroup=@shNoZSList nextgroup=shSpecialStart731if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix")732 syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList nextgroup=@shSpecialNoZS,shSpecialStart733 syn region shDeref matchgroup=PreProc start="\${\$\$" end="}" contains=@shDerefList nextgroup=@shSpecialNoZS,shSpecialStart734endif735 736" ksh: ${.sh.*} variables: {{{1737" ========================================738if exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh")739 syn match shDerefVar contained "\.\+" nextgroup=@shDerefVarList740 syn region shDeref matchgroup=PreProc start="\${\ze[\.]" end="}" contains=@shDerefVarList,shDerefPSR,shDerefPPS741endif742 743" ksh: ${!var[*]} array index list syntax: {{{1744" ========================================745if (exists("b:is_kornshell") && !exists("b:is_ksh88")) || exists("b:is_posix")746 syn region shDeref matchgroup=PreProc start="\${!" end="}" contains=@shDerefVarArray747endif748 749" bash: ${!prefix*} and ${#parameter}: {{{1750" ====================================751if exists("b:is_bash")752 syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOffset753 syn match shDerefVar contained "{\@<=!\h\w*" nextgroup=@shDerefVarList754endif755if (exists("b:is_kornshell") && !exists("b:is_ksh88"))756 syn match shDerefVar contained "{\@<=!\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList757endif758 759syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOffset,shDerefOpError760syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp761syn match shDerefVar contained "{\@<=\h\w*" nextgroup=@shDerefVarList762syn match shDerefVar contained '\d' nextgroup=@shDerefVarList763if exists("b:is_kornshell") || exists("b:is_posix")764 syn match shDerefVar contained "{\@<=\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList765endif766 767" sh ksh bash : ${var[... ]...} array reference: {{{1768syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError,shDerefOffset769 770" Special ${parameter OPERATOR word} handling: {{{1771" sh ksh bash : ${parameter:-word} word is default value772" sh ksh bash : ${parameter:=word} assign word as default value773" sh ksh bash : ${parameter:?word} display word if parameter is null774" sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing775" ksh bash : ${parameter#pattern} remove small left pattern776" ksh bash : ${parameter##pattern} remove large left pattern777" ksh bash : ${parameter%pattern} remove small right pattern778" ksh bash : ${parameter%%pattern} remove large right pattern779" ksh bash : ${parameter^pattern} Case modification780" ksh bash : ${parameter^^pattern} Case modification781" ksh bash : ${parameter,pattern} Case modification782" ksh bash : ${parameter,,pattern} Case modification783" bash : ${@:start:qty} display command line arguments from start to start+qty-1 (inferred)784" bash : ${parameter@operator} transforms parameter (operator∈[uULqEPARa])785syn cluster shDerefPatternList contains=shDerefPattern,shDerefString786if !exists("g:sh_no_error")787 syn match shDerefOpError contained ":[[:punct:]]"788endif789syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList790syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList791if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix")792 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList793 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList794 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern skipnl795 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern796 " Match parametric bracket expressions with a leading whitespace character.797 syn region shDerefPattern contained matchgroup=shBracketExprDelim start="\[" end="\]" contains=@shBracketExprList,shDoubleQuote nextgroup=shDerefPattern798 call s:GenerateBracketExpressionItems({'itemGroup': 'shDerefPattern', 'bracketGroup': 'shBracketExprDelim', 'extraArgs': 'contained nextgroup=shDerefPattern'})799 syn match shDerefEscape contained '\%(\\\\\)*\\.'800endif801if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh") && !exists("b:is_ksh93u") && !exists("b:is_ksh2020"))802 syn match shDerefOp contained "[,^]\{1,2}" nextgroup=@shDerefPatternList803endif804if exists("b:is_bash")805 syn match shDerefOp contained "@[uULQEPAKa]"806endif807syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!'+ end=+'+808syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial809syn match shDerefString contained "\\["']" nextgroup=shDerefPattern810 811if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88")) || exists("b:is_posix")812 " bash ksh posix : ${parameter:offset}813 " bash ksh posix : ${parameter:offset:length}814 syn region shDerefOffset contained start=':[^-=?+]' end='\ze:' end='\ze}' contains=shDeref,shDerefSimple,shDerefEscape nextgroup=shDerefLen,shDeref,shDerefSimple815 syn region shDerefOffset contained start=':\s-' end='\ze:' end='\ze}' contains=shDeref,shDerefSimple,shDerefEscape nextgroup=shDerefLen,shDeref,shDerefSimple816 syn match shDerefLen contained ":[^}]\+" contains=shDeref,shDerefSimple,shArithmetic817endif818 819if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88"))820 " bash ksh : ${parameter/pattern/string}821 " bash ksh : ${parameter//pattern/string}822 syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft823 syn region shDerefPPSleft contained start='.' skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp end='/' end='\ze}' end='"' nextgroup=shDerefPPSright contains=@shPPSLeftList824 syn region shDerefPPSright contained start='.' skip=@\%(\\\\\)\+@ end='\ze}' contains=@shPPSRightList825 826 " bash ksh : ${parameter/#pattern/string}827 " bash ksh : ${parameter/%pattern/string}828 syn match shDerefPSR contained '/[#%]' nextgroup=shDerefPSRleft,shDoubleQuote,shSingleQuote829 syn region shDerefPSRleft contained start='[^"']' skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPSRright contains=shBracketExpr830 syn region shDerefPSRright contained start='.' skip=@\%(\\\\\)\+@ end='\ze}'831endif832 833" Arithmetic Parenthesized Expressions: {{{1834"syn region shParen matchgroup=shArithRegion start='[^$]\zs(\%(\ze[^(]\|$\)' end=')' contains=@shArithParenList835syn region shParen matchgroup=shArithRegion start='\$\@!(\%(\ze[^(]\|$\)' end=')' contains=@shArithParenList836 837" Additional sh Keywords: {{{1838" ===================839" builtins:840syn keyword shStatement bg break cd continue command eval exec exit export fc getopts hash jobs local printf read readonly return shift times trap type ulimit umask unalias wait841" external programs:842syn keyword shStatement basename cat chgrp chmod chown cksum clear cmp comm cp cut date dirname du egrep expr false fgrep find fmt fold getconf grep head iconv id join kill killall less ln login logname ls md5sum mkdir mkfifo mknod mktemp mv newgrp nice nohup od paste pathchk printenv pwd readlink realpath rename rev rm rmdir sed sha1sum sha224sum sha256sum sha384sum sha512sum sleep sort strip stty sum sync tail tee test tput tr true tty uname uniq wc which xargs843syn keyword shConditional contained elif else then844if !exists("g:sh_no_error")845 syn keyword shCondError elif else then846endif847 848" Synchronization: {{{1849" ================850if !exists("g:sh_minlines")851 let s:sh_minlines = 200852else853 let s:sh_minlines= g:sh_minlines854endif855if !exists("g:sh_maxlines")856 let s:sh_maxlines = 2*s:sh_minlines857 if s:sh_maxlines < 25858 let s:sh_maxlines= 25859 endif860else861 let s:sh_maxlines= g:sh_maxlines862endif863exec "syn sync minlines=" . s:sh_minlines . " maxlines=" . s:sh_maxlines864syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>"865syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>"866syn sync match shDoSync grouphere shDo "\<do\>"867syn sync match shDoSync groupthere shDo "\<done\>"868syn sync match shForSync grouphere shFor "\<for\>"869syn sync match shForSync groupthere shFor "\<in\>"870syn sync match shIfSync grouphere shIf "\<if\>"871syn sync match shIfSync groupthere shIf "\<fi\>"872syn sync match shUntilSync grouphere shRepeat "\<until\>"873syn sync match shWhileSync grouphere shRepeat "\<while\>"874 875" Default Highlighting: {{{1876" =====================877if !exists("skip_sh_syntax_inits")878 hi def link shArithRegion shShellVariables879 hi def link shArrayValue shDeref880 hi def link shAstQuote shDoubleQuote881 hi def link shAtExpr shSetList882 hi def link shBkslshSnglQuote shSingleQuote883 hi def link shBkslshDblQuote shDOubleQuote884 hi def link shBeginHere shRedir885 hi def link shCaseBar shConditional886 hi def link shCaseCommandSub shCommandSub887 hi def link shCaseDoubleQuote shDoubleQuote888 hi def link shCaseIn shConditional889 hi def link shQuote shOperator890 hi def link shCaseSingleQuote shSingleQuote891 hi def link shCaseStart shConditional892 hi def link shCmdSubRegion shShellVariables893 hi def link shColon shComment894 hi def link shDerefOp shOperator895 hi def link shDerefPOL shDerefOp896 hi def link shDerefPPS shDerefOp897 hi def link shDerefPSR shDerefOp898 hi def link shDeref shShellVariables899 hi def link shDerefDelim shOperator900 hi def link shDerefSimple shDeref901 hi def link shDerefSpecial shDeref902 hi def link shDerefString shDoubleQuote903 hi def link shDerefVar shDeref904 hi def link shDoubleQuote shString905 hi def link shEcho shString906 hi def link shEchoDelim shOperator907 hi def link shEchoQuote shString908 hi def link shForPP shLoop909 hi def link shEmbeddedEcho shString910 hi def link shEscape shCommandSub911 hi def link shExDoubleQuote shDoubleQuote912 hi def link shExSingleQuote shSingleQuote913 hi def link shHereDoc shString914 hi def link shHereString shRedir915 hi def link shHerePayload shHereDoc916 hi def link shLoop shStatement917 hi def link shSpecialNxt shSpecial918 hi def link shNoQuote shDoubleQuote919 hi def link shOption shCommandSub920 hi def link shPattern shString921 hi def link shParen shArithmetic922 hi def link shPosnParm shShellVariables923 hi def link shQuickComment shComment924 hi def link shBQComment shComment925 hi def link shRange shOperator926 hi def link shRedir shOperator927 hi def link shSetListDelim shOperator928 hi def link shSetOption shOption929 hi def link shSingleQuote shString930 hi def link shSource shOperator931 hi def link shStringSpecial shSpecial932 hi def link shSpecialStart shSpecial933 hi def link shSubShRegion shOperator934 hi def link shTestOpr shConditional935 hi def link shTestPattern shString936 hi def link shTestDoubleQuote shString937 hi def link shTestSingleQuote shString938 hi def link shTouchCmd shStatement939 hi def link shVariable shSetList940 hi def link shWrapLineOperator shOperator941 942 if exists("b:is_bash")943 hi def link bashAdminStatement shStatement944 hi def link bashSpecialVariables shShellVariables945 hi def link bashStatement shStatement946 hi def link shCharClass shSpecial947 hi def link shDerefOffset shDerefOp948 hi def link shDerefLen shDerefOffset949 endif950 if exists("b:is_kornshell") || exists("b:is_posix")951 hi def link kshSpecialVariables shShellVariables952 hi def link kshStatement shStatement953 endif954 955 if !exists("g:sh_no_error")956 hi def link shCaseError Error957 hi def link shCondError Error958 hi def link shCurlyError Error959 hi def link shDerefOpError Error960 hi def link shDerefWordError Error961 hi def link shDoError Error962 hi def link shEsacError Error963 hi def link shIfError Error964 hi def link shInError Error965 hi def link shParenError Error966 hi def link shTestError Error967 if exists("b:is_kornshell") || exists("b:is_posix")968 hi def link shDTestError Error969 endif970 endif971 972 hi def link shArithmetic Special973 hi def link shBracketExprDelim Delimiter974 hi def link shCharClass Identifier975 hi def link shCollSymb shCharClass976 hi def link shEqClass shCharClass977 hi def link shSnglCase Statement978 hi def link shCommandSub Special979 hi def link shCommandSubBQ shCommandSub980 hi def link shSubshare shCommandSub981 hi def link shValsub shCommandSub982 hi def link shComment Comment983 hi def link shConditional Conditional984 hi def link shCtrlSeq Special985 hi def link shExprRegion Delimiter986 hi def link shFunctionKey Keyword987 hi def link shFunctionOne Function988 hi def link shFunctionTwo shFunctionOne989 hi def link shFunctionThree shFunctionOne990 hi def link shFunctionFour shFunctionOne991 hi def link shFunctionCmdOne shFunctionOne992 hi def link shFunctionCmdTwo shFunctionOne993 hi def link shFunctionExprRegion shExprRegion994 hi def link shFunctionSubShRegion shSubShRegion995 hi def link shNamespaceOne Function996 hi def link shNumber Number997 hi def link shOperator Operator998 hi def link shRepeat Repeat999 hi def link shSet Statement1000 hi def link shSetList Identifier1001 hi def link shShellVariables PreProc1002 hi def link shSpecial Special1003 hi def link shSpecialDQ Special1004 hi def link shSpecialSQ Special1005 hi def link shSpecialNoZS shSpecial1006 hi def link shStatement Statement1007 hi def link shString String1008 hi def link shTodo Todo1009 hi def link shAlias Identifier1010 hi def link shHereDoc01 shRedir1011 hi def link shHereDoc02 shRedir1012 hi def link shHereDoc03 shRedir1013 hi def link shHereDoc04 shRedir1014 hi def link shHereDoc05 shRedir1015 hi def link shHereDoc06 shRedir1016 hi def link shHereDoc07 shRedir1017 hi def link shHereDoc08 shRedir1018 hi def link shHereDoc09 shRedir1019 hi def link shHereDoc10 shRedir1020 hi def link shHereDoc11 shRedir1021 hi def link shHereDoc12 shRedir1022 hi def link shHereDoc13 shRedir1023 hi def link shHereDoc14 shRedir1024 hi def link shHereDoc15 shRedir1025 hi def link shHereDoc16 shRedir1026endif1027 1028" Delete shell folding commands {{{11029" =============================1030delc ShFoldFunctions1031delc ShFoldHereDoc1032delc ShFoldIfDoFor1033 1034" Delete the bracket expression function {{{11035" ======================================1036delfun s:GenerateBracketExpressionItems1037 1038" Set Current Syntax: {{{11039" ===================1040if exists("b:is_bash")1041 let b:current_syntax = "bash"1042elseif exists("b:is_kornshell")1043 let b:current_syntax = "ksh"1044elseif exists("b:is_posix")1045 let b:current_syntax = "posix"1046else1047 let b:current_syntax = "sh"1048endif1049 1050" vim: ts=16 fdm=marker1051 