sh.vim (66221B)
1 " Vim syntax file 2 " Language: shell (sh) Korn shell (ksh) bash (sh) 3 " Maintainer: This runtime file is looking for a new maintainer. 4 " Previous Maintainers: Charles E. Campbell 5 " Lennart Schultz <Lennart.Schultz@ecmwf.int> 6 " Last Change: 2024 Mar 04 by Vim Project {{{1 7 " 2024 Nov 03 by Aliaksei Budavei <0x000c70 AT gmail DOT com> improved bracket expressions, #15941 8 " 2025 Jan 06 add $PS0 to bashSpecialVariables #16394 9 " 2025 Jan 18 add bash coproc, remove duplicate syn keywords #16467 10 " 2025 Mar 21 update shell capability detection #16939 11 " 2025 Apr 03 command substitution opening paren at EOL #17026 12 " 2025 Apr 10 improve shell detection #17084 13 " 2025 Apr 29 match escaped chars in test operands #17221 14 " 2025 May 06 improve single-quote string matching in parameter expansions 15 " 2025 May 06 match KornShell compound arrays 16 " 2025 May 10 improve wildcard character class lists 17 " 2025 May 21 improve supported KornShell features 18 " 2025 Jun 16 change how sh_fold_enabled is reset #17557 19 " 2025 Jul 18 properly delete :commands #17785 20 " 2025 Aug 23 bash: add support for ${ cmd;} and ${|cmd;} #18084 21 " 2025 Sep 23 simplify ksh logic, update sh statements #18355 22 " 2026 Jan 15 highlight command switches that contain a digit 23 " 2026 Feb 11 improve support for KornShell function names and variables 24 " 2026 Feb 15 improve comment handling #19414 25 " }}} 26 " Version: 208 27 " Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH 28 " For options and settings, please use: :help ft-sh-syntax 29 " This file includes many ideas from Eric Brunet (eric.brunet@ens.fr) and heredoc fixes from Felipe Contreras 30 31 " quit when a syntax file was already loaded {{{1 32 if exists("b:current_syntax") 33 finish 34 endif 35 36 " Ensure this is set unless we find another shell 37 let b:is_sh = 1 38 39 " If the shell script itself specifies which shell to use, use it 40 let s:shebang = getline(1) 41 42 if s:shebang =~ '^#!.\{-2,}\<ksh\>' 43 " The binary is too ambiguous (i.e. '/bin/ksh' or some such). 44 let b:is_kornshell = 1 45 let b:generic_korn = 1 46 elseif s:shebang =~ '^#!.\{-2,}\<ksh93u\+\>' 47 " ksh93u+ (or 93u-) release (still much too common to encounter) 48 let b:is_kornshell = 1 49 let b:is_ksh93u = 1 50 elseif s:shebang =~ '^#!.\{-2,}\<ksh93v\>' 51 " ksh93v- alpha or beta 52 let b:is_kornshell = 1 53 let b:is_ksh93v = 1 54 elseif s:shebang =~ '^#!.\{-2,}\<ksh93\>' 55 " Could be any ksh93 release 56 let b:is_kornshell = 1 57 let b:is_ksh93 = 1 58 elseif s:shebang =~ '^#!.\{-2,}\<ksh2020\>' 59 let b:is_kornshell = 1 60 let b:is_ksh2020 = 1 61 elseif s:shebang =~ '^#!.\{-2,}\<ksh88\>' 62 " The actual AT&T ksh88 and its feature set is assumed. 63 let b:is_kornshell = 1 64 let b:is_ksh88 = 1 65 elseif s:shebang =~ '^#!.\{-2,}\<mksh\>' 66 " MirBSD Korn Shell 67 let b:is_kornshell = 1 68 let b:is_mksh = 1 69 elseif s:shebang =~ '^#!.\{-2,}\<bash\>' 70 let b:is_bash = 1 71 elseif s:shebang =~ '^#!.\{-2,}\<dash\>' 72 let b:is_dash = 1 73 " handling /bin/sh with is_kornshell/is_sh {{{1 74 " b:is_sh will be set when "#! /bin/sh" is found; 75 " However, it often is just a masquerade by bash (typically Linux) 76 " or kornshell (typically workstations with Posix "sh"). 77 " So, when the user sets "g:is_kornshell", "g:is_bash", 78 " "g:is_posix" or "g:is_dash", a b:is_sh is converted into 79 " b:is_kornshell/b:is_bash/b:is_posix/b:is_dash, respectively. 80 elseif !exists("b:is_kornshell") && !exists("b:is_bash") && !exists("b:is_posix") && !exists("b:is_dash") 81 if exists("g:is_kornshell") 82 let b:is_kornshell= 1 83 let b:generic_korn = 1 84 elseif exists("g:is_bash") 85 let b:is_bash= 1 86 elseif exists("g:is_dash") 87 let b:is_dash= 1 88 elseif exists("g:is_posix") 89 let b:is_posix= 1 90 elseif exists("g:is_sh") 91 let b:is_sh= 1 92 else 93 " user did not specify which shell to use, and 94 " the script itself does not specify which shell to use. FYI: /bin/sh is ambiguous. 95 " Assuming /bin/sh is executable, and if its a link, find out what it links to. 96 let s:shell = "" 97 if executable("/bin/sh") 98 let s:shell = resolve("/bin/sh") 99 elseif executable("/usr/bin/sh") 100 let s:shell = resolve("/usr/bin/sh") 101 endif 102 if s:shell =~ '\<ksh\>' 103 " The binary is too ambiguous (i.e. '/bin/ksh' or some such). 104 let b:is_kornshell = 1 105 let b:generic_korn = 1 106 elseif s:shell =~ '\<ksh93u\+\>' 107 " ksh93u+ (or 93u-) release (still much too common to encounter) 108 let b:is_kornshell = 1 109 let b:is_ksh93u = 1 110 elseif s:shell =~ '\<ksh93v\>' 111 " ksh93v- alpha or beta 112 let b:is_kornshell = 1 113 let b:is_ksh93v = 1 114 elseif s:shell =~ '\<ksh93\>' 115 " Could be any ksh93 release 116 let b:is_kornshell = 1 117 let b:is_ksh93 = 1 118 elseif s:shebang =~ '\<ksh2020\>' 119 let b:is_kornshell = 1 120 let b:is_ksh2020 = 1 121 elseif s:shell =~ '\<ksh88\>' 122 " The actual AT&T ksh88 and its feature set is assumed. 123 let b:is_kornshell = 1 124 let b:is_ksh88 = 1 125 elseif s:shell =~ '\<mksh\>' 126 " MirBSD Korn Shell 127 let b:is_kornshell = 1 128 let b:is_mksh = 1 129 elseif s:shell =~ '\<bash\>' 130 let b:is_bash = 1 131 elseif s:shell =~ '\<dash\>' 132 let b:is_dash = 1 133 else 134 let b:is_posix = 1 135 endif 136 unlet s:shell 137 endif 138 endif 139 140 unlet s:shebang 141 142 " if b:is_dash, set b:is_posix too 143 if exists("b:is_dash") 144 let b:is_posix= 1 145 endif 146 147 if exists("b:is_kornshell") || exists("b:is_bash") 148 if exists("b:is_sh") 149 unlet b:is_sh 150 endif 151 endif 152 153 " set up default g:sh_fold_enabled {{{1 154 " ================================ 155 if !exists("g:sh_fold_enabled") 156 let g:sh_fold_enabled= 0 157 elseif g:sh_fold_enabled != 0 && !has("folding") 158 echomsg "Ignoring g:sh_fold_enabled=".g:sh_fold_enabled."; need to re-compile vim for +fold support" 159 let g:sh_fold_enabled= 0 160 endif 161 let s:sh_fold_functions= and(g:sh_fold_enabled,1) 162 let s:sh_fold_heredoc = and(g:sh_fold_enabled,2) 163 let s:sh_fold_ifdofor = and(g:sh_fold_enabled,4) 164 if g:sh_fold_enabled && &fdm == "manual" 165 " Given that the user provided g:sh_fold_enabled 166 " AND g:sh_fold_enabled is manual (usual default) 167 " implies a desire for syntax-based folding 168 setl fdm=syntax 169 endif 170 171 " set up the syntax-highlighting for iskeyword 172 if (v:version == 704 && has("patch-7.4.1142")) || v:version > 704 173 if !exists("g:sh_syntax_isk") || (exists("g:sh_syntax_isk") && g:sh_syntax_isk) 174 if exists("b:is_bash") 175 exe "syn iskeyword ".&iskeyword.",-,:" 176 elseif exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh") 177 exe "syn iskeyword ".&iskeyword.",-,." 178 else 179 exe "syn iskeyword ".&iskeyword.",-" 180 endif 181 endif 182 endif 183 184 " Set up folding commands for shell {{{1 185 " ================================= 186 if exists(":ShFoldFunctions") == 2 187 delc ShFoldFunctions 188 endif 189 if exists(":ShFoldIfHereDoc") == 2 190 delc ShFoldHereDoc 191 endif 192 if exists(":ShFoldIfDoFor") == 2 193 delc ShFoldIfDoFor 194 endif 195 if s:sh_fold_functions 196 com! -nargs=* ShFoldFunctions <args> fold 197 else 198 com! -nargs=* ShFoldFunctions <args> 199 endif 200 if s:sh_fold_heredoc 201 com! -nargs=* ShFoldHereDoc <args> fold 202 else 203 com! -nargs=* ShFoldHereDoc <args> 204 endif 205 if s:sh_fold_ifdofor 206 com! -nargs=* ShFoldIfDoFor <args> fold 207 else 208 com! -nargs=* ShFoldIfDoFor <args> 209 endif 210 211 " Generate bracket expression items {{{1 212 " ================================= 213 " Note that the following function can be invoked as many times as necessary 214 " provided that these constraints hold for the passed dictionary argument: 215 " - every time a unique group-name value is assigned to the "itemGroup" key; 216 " - only ONCE either the "extraArgs" key is not entered or it is entered and 217 " its value does not have "contained" among other optional arguments (":help 218 " :syn-arguments"). 219 fun! s:GenerateBracketExpressionItems(dict) abort 220 let itemGroup = a:dict.itemGroup 221 let bracketGroup = a:dict.bracketGroup 222 let invGroup = itemGroup . 'Inv' 223 let skipLeftBracketGroup = itemGroup . 'SkipLeftBracket' 224 let skipRightBracketGroup = itemGroup . 'SkipRightBracket' 225 let extraArgs = has_key(a:dict, 'extraArgs') ? a:dict.extraArgs : '' 226 227 " Make the leading "[!^]" stand out in a NON-matching expression. 228 exec 'syn match ' . invGroup . ' contained "\[\@<=[!^]"' 229 230 " Set up indirections for unbalanced-bracket highlighting. 231 exec 'syn region ' . skipRightBracketGroup . ' contained matchgroup=' . bracketGroup . ' start="\[\%([!^]\=\\\=\]\)\@=" matchgroup=shCollSymb end="\[\.[^]]\{-}\][^]]\{-}\.\]" matchgroup=' . itemGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . invGroup 232 exec 'syn region ' . skipLeftBracketGroup . ' contained matchgroup=' . bracketGroup . ' start="\[\%([!^]\=\\\=\]\)\@=" skip="[!^]\=\\\=\]\%(\[[^]]\+\]\|[^]]\)\{-}\%(\[[:.=]\@!\)\@=" matchgroup=' . itemGroup . ' end="\[[:.=]\@!" contains=@shBracketExprList,shDoubleQuote,' . invGroup 233 234 " Look for a general matching expression. 235 exec 'syn region ' . itemGroup . ' matchgroup=' . bracketGroup . ' start="\[\S\@=" end="\]" contains=@shBracketExprList,shDoubleQuote ' . extraArgs 236 " Look for a general NON-matching expression. 237 exec 'syn region ' . itemGroup . ' matchgroup=' . bracketGroup . ' start="\[[!^]\@=" end="\]" contains=@shBracketExprList,shDoubleQuote,' . invGroup . ' ' . extraArgs 238 239 " Accommodate unbalanced brackets in bracket expressions. The supported 240 " syntax for a plain "]" can be: "[]ws]" and "[^]ws]"; or, "[ws[.xs]ys.]zs]" 241 " and "[^ws[.xs]ys.]zs]"; see §9.3.5 RE Bracket Expression (in XBD). 242 exec 'syn region ' . itemGroup . ' matchgroup=NONE start="\[[!^]\=\\\=\]" matchgroup=' . bracketGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . skipRightBracketGroup . ' ' . extraArgs 243 " Strive to handle "[]...[]" etc. 244 exec 'syn region ' . itemGroup . ' matchgroup=NONE start="\[[!^]\=\\\=\]\%(\[[^]]\+\]\|[^]]\)\{-}\[[:.=]\@!" matchgroup=' . bracketGroup . ' end="\]" contains=@shBracketExprList,shDoubleQuote,' . skipLeftBracketGroup . ' ' . extraArgs 245 246 if !exists("g:skip_sh_syntax_inits") 247 exec 'hi def link ' . skipLeftBracketGroup . ' ' . itemGroup 248 exec 'hi def link ' . skipRightBracketGroup . ' ' . itemGroup 249 exec 'hi def link ' . invGroup . ' Underlined' 250 endif 251 endfun 252 253 call s:GenerateBracketExpressionItems({'itemGroup': 'shBracketExpr', 'bracketGroup': 'shBracketExprDelim'}) 254 255 " sh syntax is case sensitive {{{1 256 syn case match 257 258 " Clusters: contains=@... clusters {{{1 259 "================================== 260 syn cluster shErrorList contains=shDoError,shIfError,shInError,shCaseError,shEsacError,shCurlyError,shParenError,shTestError,shOK 261 if exists("b:is_kornshell") || exists("b:is_bash") 262 syn cluster ErrorList add=shDTestError 263 endif 264 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,shNamespaceOne 265 syn cluster shArithList contains=@shArithParenList,shParenError 266 syn cluster shBracketExprList contains=shCharClassOther,shCharClass,shCollSymb,shEqClass 267 syn cluster shCaseEsacList contains=shCaseStart,shCaseLabel,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial,shCaseRange 268 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 269 if exists("b:is_kornshell") || exists("b:is_bash") 270 syn cluster shCaseList add=shForPP,shDblParen 271 endif 272 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 273 syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial 274 " COMBAK: removing shEscape from shDblQuoteList fails ksh04:43 -- Jun 09, 2022: I don't see the problem with ksh04, so am reinstating shEscape 275 syn cluster shDblQuoteList contains=shArithmetic,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shDeref,shDerefSimple,shEscape,shPosnParm,shCtrlSeq,shSpecial,shSpecialDQ 276 syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPSR,shDerefPPS 277 syn cluster shDerefVarList contains=shDerefOffset,shDerefOp,shDerefVarArray,shDerefOpError 278 syn cluster shEchoList contains=shArithmetic,shBracketExpr,shCommandSub,shCommandSubBQ,shDerefVarArray,shSubshare,shValsub,shDeref,shDerefSimple,shEscape,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote 279 syn cluster shExprList1 contains=shBracketExpr,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq 280 syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest 281 syn cluster shFunctionList contains=shBracketExpr,@shCommandSubList,shCaseEsac,shColon,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shOption,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq 282 if exists("b:is_kornshell") || exists("b:is_bash") 283 syn cluster shFunctionList add=shRepeat,shDblBrace,shDblParen,shForPP 284 syn cluster shDerefList add=shCommandSubList,shEchoDeref 285 endif 286 syn cluster shHereBeginList contains=@shCommandSubList 287 syn cluster shHereList contains=shBeginHere,shHerePayload 288 syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload 289 syn 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,shAtExpr 290 syn cluster shIfList contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey,shFunctionOne,shFunctionTwo,shNamespaceOne 291 syn cluster shLoopList contains=@shCaseList,@shErrorList,shCaseEsac,shConditional,shDblBrace,shExpr,shFor,shIf,shOption,shSet,shTest,shTestOpr,shTouch 292 if exists("b:is_kornshell") || exists("b:is_bash") 293 syn cluster shLoopList add=shForPP,shDblParen 294 endif 295 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 296 syn cluster shPPSRightList contains=shDeref,shDerefSimple,shEscape,shPosnParm 297 syn cluster shSubShList contains=shBracketExpr,@shCommandSubList,shCommandSubBQ,shSubshare,shValsub,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator 298 syn cluster shTestList contains=shArithmetic,shBracketExpr,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shSpecialDQ,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr 299 syn cluster shNoZSList contains=shSpecialNoZS 300 syn cluster shForList contains=shTestOpr,shNumber,shDerefSimple,shDeref,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shArithmetic 301 302 " Echo: {{{1 303 " ==== 304 " This one is needed INSIDE a CommandSub, so that `echo bla` be correct 305 if (exists("b:is_kornshell") && !exists("b:is_ksh88")) 306 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=shQuickComment 307 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=shQuickComment 308 else 309 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=shQuickComment 310 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=shQuickComment 311 endif 312 if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix") 313 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=shQuickComment 314 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=shQuickComment 315 endif 316 syn match shEchoQuote contained '\%(\\\\\)*\\["`'()]' 317 318 " This must be after the strings, so that ... \" will be correct 319 syn 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,shCtrlSeq 320 321 " Alias: {{{1 322 " ===== 323 if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix") 324 syn match shStatement "\<alias\>" 325 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\h[-._[:alnum:]]*\)\@=" skip="\\$" end="\>\|`" 326 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\h[-._[:alnum:]]*=\)\@=" skip="\\$" end="=" 327 328 " Touch: {{{1 329 " ===== 330 syn match shTouch '\<touch\>[^;#]*' skipwhite nextgroup=shComment contains=shTouchCmd,shDoubleQuote,shSingleQuote,shDeref,shDerefSimple 331 syn match shTouchCmd '\<touch\>' contained 332 endif 333 334 " Error Codes: {{{1 335 " ============ 336 if !exists("g:sh_no_error") 337 syn match shDoError "\<done\>" 338 syn match shIfError "\<fi\>" 339 syn match shInError "\<in\>" 340 syn match shCaseError ";;" 341 syn match shEsacError "\<esac\>" 342 syn match shCurlyError "}" 343 syn match shParenError ")" 344 syn match shOK '\.\(done\|fi\|in\|esac\)' 345 if exists("b:is_kornshell") || exists("b:is_bash") 346 syn match shDTestError "]]" 347 endif 348 syn match shTestError "]" 349 endif 350 351 " Options: {{{1 352 " ==================== 353 syn match shOption "\s\zs[-+][-_a-zA-Z#@0-9]\+" 354 syn match shOption "\s\zs--[^ \t$=`'"|);]\+" 355 356 " File Redirection Highlighted As Operators: {{{1 357 "=========================================== 358 syn match shRedir "\d\=>\(&[-0-9]\)\=" 359 syn match shRedir "\d\=>>-\=" 360 syn match shRedir "\d\=<\(&[-0-9]\)\=" 361 syn match shRedir "\d<<-\=" 362 363 " Operators: {{{1 364 " ========== 365 syn match shOperator "<<\|>>" contained 366 syn match shOperator "[!&;|]" contained 367 syn match shOperator "[-=/*+%]\==" skipwhite nextgroup=shPattern 368 syn match shPattern "\<\S\+\())\)\@=" contained contains=shExSingleQuote,shSingleQuote,shExDoubleQuote,shDoubleQuote,shDeref 369 370 " Subshells: {{{1 371 " ========== 372 syn region shExpr transparent matchgroup=shExprRegion start="{" end="}" contains=@shExprList2 nextgroup=shSpecialNxt 373 syn region shSubSh transparent matchgroup=shSubShRegion start="[^(]\zs(" end=")" contains=@shSubShList nextgroup=shSpecialNxt 374 375 " Tests: {{{1 376 "======= 377 syn region shExpr matchgroup=shRange start="\[\s\@=" skip=+\\\\\|\\$\|\[+ end="\]" contains=@shTestList,shSpecial 378 syn region shTest transparent matchgroup=shStatement start="\<test\s" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1 379 syn region shNoQuote start='\S' skip='\%(\\\\\)*\\.' end='\ze\s' end="\ze['"]" contained contains=shBracketExpr,shDerefSimple,shDeref,shEscape 380 syn match shAstQuote contained '\*\ze"' nextgroup=shString 381 syn match shTestOpr contained '[^-+/%]\zs=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern 382 syn match shTestOpr contained "<=\|>=\|!=\|==\|=\~\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]" 383 syn match shTestPattern contained '\w\+' 384 syn region shTestDoubleQuote contained start='\%(\%(\\\\\)*\\\)\@<!"' skip=+\\\\\|\\"+ end='"' contains=shDeref,shDerefSimple,shDerefSpecial 385 syn match shTestSingleQuote contained '\\.' nextgroup=shTestSingleQuote 386 syn match shTestSingleQuote contained "'[^']*'" 387 if exists("b:is_kornshell") || exists("b:is_bash") 388 syn region shDblBrace matchgroup=Delimiter start="\[\[\s\@=" skip=+\%(\\\\\)*\\$+ end="\]\]" contains=@shTestList,shAstQuote,shNoQuote,shComment 389 syn region shDblParen matchgroup=Delimiter start="((" skip=+\%(\\\\\)*\\$+ end="))" contains=@shTestList,shComment 390 endif 391 392 " Character Class In Range: {{{1 393 " ========================= 394 syn match shCharClassOther contained "\[:\w\{-}:\]" 395 syn match shCharClass contained "\[:\%(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\):\]" 396 syn match shCollSymb contained "\[\..\{-}\.\]" 397 syn match shEqClass contained "\[=.\{-}=\]" 398 399 " Loops: do, if, while, until {{{1 400 " ====== 401 ShFoldIfDoFor syn region shDo transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList 402 ShFoldIfDoFor syn region shIf transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional skip=+-fi\>+ end="\<;\_s*then\>" end="\<fi\>" contains=@shIfList 403 ShFoldIfDoFor syn region shFor matchgroup=shLoop start="\<for\ze\_s\s*\%(((\)\@!" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn 404 if exists("b:is_kornshell") || exists("b:is_bash") 405 ShFoldIfDoFor syn region shForPP matchgroup=shLoop start='\<for\>\_s*((' end='))' contains=@shForList 406 endif 407 408 if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix") 409 syn cluster shCaseList add=shRepeat 410 syn cluster shFunctionList add=shRepeat 411 syn region shRepeat matchgroup=shLoop start="\<while\_s" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace 412 syn region shRepeat matchgroup=shLoop start="\<until\_s" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace 413 if !exists("b:is_posix") 414 syn region shCaseEsac matchgroup=shConditional start="\<select\s" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList 415 endif 416 else 417 syn region shRepeat matchgroup=shLoop start="\<while\_s" end="\<do\>"me=e-2 contains=@shLoopList 418 syn region shRepeat matchgroup=shLoop start="\<until\_s" end="\<do\>"me=e-2 contains=@shLoopList 419 endif 420 syn region shCurlyIn contained matchgroup=Delimiter start="{" end="}" contains=@shCurlyList 421 syn match shComma contained "," 422 423 " Case: case...esac {{{1 424 " ==== 425 syn match shCaseBar contained skipwhite "\(^\|[^\\]\)\(\\\\\)*\zs|" nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote 426 syn match shCaseStart contained skipwhite skipnl "(" nextgroup=shCase,shCaseBar 427 syn match shCaseLabel contained skipwhite "\%(\\.\|[-a-zA-Z0-9_*.]\)\+" contains=shBracketExpr 428 if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_ksh93u") && !exists("b:is_ksh93v") && !exists("b:is_ksh2020")) 429 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,shComment 430 elseif exists("b:is_kornshell") 431 ShFoldIfDoFor syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)" end=";;" end=";&" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment 432 else 433 ShFoldIfDoFor syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)" end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment 434 endif 435 ShFoldIfDoFor syn region shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList 436 437 syn keyword shCaseIn contained skipwhite skipnl in nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote 438 if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88")) 439 syn region shCaseExSingleQuote matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial skipwhite skipnl nextgroup=shCaseBar contained 440 elseif !exists("g:sh_no_error") 441 syn region shCaseExSingleQuote matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 442 endif 443 syn region shCaseSingleQuote matchgroup=shQuote start=+'+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 444 syn region shCaseDoubleQuote matchgroup=shQuote start=+"+ skip=+\\\\\|\\.+ end=+"+ contains=@shDblQuoteList,shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 445 syn region shCaseCommandSub start=+`+ skip=+\\\\\|\\.+ end=+`+ contains=@shCommandSubList skipwhite skipnl nextgroup=shCaseBar contained 446 call s:GenerateBracketExpressionItems({'itemGroup': 'shCaseRange', 'bracketGroup': 'shBracketExprDelim', 'extraArgs': 'skip=+\\\\+ contained'}) 447 if exists("b:is_bash") 448 syn match shCharClass "\[:\%(alnum\|alpha\|ascii\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|word\|xdigit\):\]" contained 449 elseif exists("b:is_kornshell") 450 syn match shCharClass "\[:\%(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|word\|xdigit\):\]" contained 451 endif 452 " Misc: {{{1 453 "====== 454 syn match shWrapLineOperator "\\$" 455 syn region shCommandSubBQ start="`" skip="\\\\\|\\." end="`" contains=shBQComment,@shCommandSubList 456 syn match shEscape contained '\%(^\)\@!\%(\\\\\)*\\.' 457 458 " $() and $(()): {{{1 459 " $(..) is not supported by sh (Bourne shell). However, apparently 460 " some systems (HP?) have as their /bin/sh a (link to) Korn shell 461 " (ie. Posix compliant shell). /bin/ksh should work for those 462 " systems too, however, so the following syntax will flag $(..) as 463 " an Error under /bin/sh. By consensus of vimdev'ers! 464 if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix") 465 syn region shCommandSub matchgroup=shCmdSubRegion start="\$((\@!" skip='\\\\\|\\.' end=")" contains=@shCommandSubList 466 if exists("b:is_kornshell") 467 if !exists("b:is_ksh88") 468 if exists("b:is_mksh") 469 syn region shSubshare matchgroup=shCmdSubRegion start="\${\ze[ \t\n]" skip='\\\\\|\\.' end="\zs[ \t\n;]}" contains=@shCommandSubList 470 else 471 syn region shSubshare matchgroup=shCmdSubRegion start="\${\ze[ \t\n<]" skip='\\\\\|\\.' end="\zs[ \t\n;]}" contains=@shCommandSubList 472 endif 473 endif 474 if exists("b:is_mksh") || exists("b:generic_korn") 475 syn region shValsub matchgroup=shCmdSubRegion start="\${|" skip='\\\\\|\\.' end="}" contains=@shCommandSubList 476 endif 477 elseif exists("b:is_bash") 478 syn region shSubshare matchgroup=shCmdSubRegion start="\${\ze[ \t\n]" skip='\\\\\|\\.' end="\zs[;\n][ \t\n]*}" contains=@shCommandSubList 479 syn region shValsub matchgroup=shCmdSubRegion start="\${|" skip='\\\\\|\\.' end="[;\n][ \t\n]*}" contains=@shCommandSubList 480 endif 481 syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList 482 syn region shArithmetic matchgroup=shArithRegion start="\$\[" skip='\\\\\|\\.' end="\]" contains=@shArithList 483 syn match shSkipInitWS contained "^\s\+" 484 syn region shArithParen matchgroup=shArithRegion contained start="(" end=")" contains=@shArithParenList 485 elseif !exists("g:sh_no_error") 486 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList 487 endif 488 syn region shCmdParenRegion matchgroup=shCmdSubRegion start="((\@!" skip='\\\\\|\\.' end=")" contains=@shCommandSubList 489 490 if exists("b:is_bash") 491 syn cluster shCommandSubList add=bashSpecialVariables,bashStatement 492 syn cluster shCaseList add=bashAdminStatement,bashStatement 493 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 UID 494 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 time 495 syn keyword bashStatement typeset nextgroup=shSetOption 496 syn keyword bashAdminStatement reload restart start status stop 497 endif 498 499 " for all kornshells 500 if exists("b:is_kornshell") 501 syn cluster shCaseList add=kshStatement 502 syn cluster shCommandSubList add=kshSpecialVariables,kshStatement 503 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 VISUAL 504 syn keyword kshStatement autoload builtin compound disown enum fg float functions hist history integer let nameref r redirect source stop suspend time whence 505 syn keyword shStatement typeset skipwhite nextgroup=shSetOption 506 endif 507 508 " kornshell flavors 509 if exists("b:generic_korn") 510 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_prefix 511 syn keyword kshStatement alarm bind compgen complete eloop fds mkservice pids poll sha2sum vmstate xgrep 512 elseif exists("b:is_ksh88") 513 syn keyword kshSpecialVariables contained ERRNO 514 elseif exists("b:is_ksh93") 515 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.subshell 516 syn keyword kshStatement alarm compgen complete eloop fds mkservice pids poll sha2sum vmstate xgrep 517 elseif exists("b:is_ksh93v") 518 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.subshell 519 syn keyword kshStatement alarm compgen complete fds pids poll sha2sum vmstate xgrep 520 elseif exists("b:is_ksh93u") 521 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.subshell 522 syn keyword kshStatement alarm fds pids vmstate 523 elseif exists("b:is_ksh2020") 524 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_prefix 525 syn keyword kshStatement compgen complete 526 elseif exists("b:is_mksh") 527 syn keyword kshSpecialVariables contained BASHPID EPOCHREALTIME EXECSHELL KSHEGID KSHGID KSHUID KSH_MATCH PATHSEP PGRP PIPESTATUS TMPDIR USER_ID 528 syn keyword kshStatement bind 529 endif 530 531 syn match shSource "^\.\s" 532 syn match shSource "\s\.\s" 533 if exists("b:is_kornshell") || exists("b:is_posix") 534 syn match shColon '^\s*\zs:' 535 endif 536 537 " String And Character Constants: {{{1 538 "================================ 539 syn match shNumber "\<\d\+\>#\=" 540 syn match shNumber "\<-\=\.\=\d\+\>#\=" 541 syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained 542 if exists("b:is_bash") || exists("b:is_kornshell") 543 syn match shSpecial "[^\\]\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained 544 syn match shSpecial "^\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained 545 syn region shExSingleQuote matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial nextgroup=shSpecialNxt 546 syn region shExDoubleQuote matchgroup=shQuote start=+\$"+ skip=+\\\\\|\\.\|\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,shSpecial nextgroup=shSpecialNxt 547 elseif !exists("g:sh_no_error") 548 syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial 549 syn region shExDoubleQuote matchGroup=Error start=+\$"+ skip=+\\\\\|\\.+ end=+"+ contains=shStringSpecial 550 endif 551 syn region shSingleQuote matchgroup=shQuote start=+'+ end=+'+ contains=@Spell nextgroup=shSpecialStart,shSpecialSQ 552 syn region shDoubleQuote matchgroup=shQuote start=+\%(\%(\\\\\)*\\\)\@<!"+ skip=+\\.+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell nextgroup=shSpecialStart 553 syn match shStringSpecial "[^[:print:] \t]" contained 554 syn match shStringSpecial "[^\\]\zs\%(\\\\\)*\(\\[\\"'`$()#]\)\+" nextgroup=shComment 555 syn match shSpecialSQ "[^\\]\zs\%(\\\\\)*\(\\[\\"'`$()#]\)\+" contained nextgroup=shBkslshSnglQuote,@shNoZSList 556 syn match shSpecialDQ "[^\\]\zs\%(\\\\\)*\(\\[\\"'`$()#]\)\+" contained nextgroup=shBkslshDblQuote,@shNoZSList 557 syn match shSpecialStart "\%(\\\\\)*\\[\\"'`$()#]" contained nextgroup=shBkslshSnglQuote,shBkslshDblQuote,@shNoZSList 558 syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]" 559 syn match shSpecialNoZS contained "\%(\\\\\)*\\[\\"'`$()#]" 560 syn match shSpecialNxt contained "\\[\\"'`$()#]" 561 562 " Comments: {{{1 563 "========== 564 syn cluster shCommentGroup contains=shTodo,@Spell 565 if exists("b:is_bash") 566 syn match shTodo contained "\<\%(COMBAK\|FIXME\|TODO\|XXX\)\ze:\=\>" 567 else 568 syn keyword shTodo contained COMBAK FIXME TODO XXX 569 endif 570 syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup 571 syn match shComment "\s\zs#.*$" contains=@shCommentGroup 572 syn match shComment contained "#.*$" contains=@shCommentGroup 573 syn match shQuickComment contained "#.*$" contains=@shCommentGroup 574 syn match shBQComment contained "#.\{-}\ze`" contains=@shCommentGroup 575 576 " Here Documents: {{{1 577 " (modified by Felipe Contreras) 578 " ========================================= 579 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc01 start="<<\s*\z([^ \t|>]\+\)" matchgroup=shHereDoc01 end="^\z1$" contains=@shDblQuoteList 580 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc02 start="<<-\s*\z([^ \t|>]\+\)" matchgroup=shHereDoc02 end="^\t*\z1$" contains=@shDblQuoteList 581 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc03 start="<<\s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc03 end="^\z1$" 582 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc04 start="<<-\s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc04 end="^\t*\z1$" 583 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc05 start="<<\s*'\z([^']\+\)'" matchgroup=shHereDoc05 end="^\z1$" 584 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc06 start="<<-\s*'\z([^']\+\)'" matchgroup=shHereDoc06 end="^\t*\z1$" 585 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc07 start="<<\s*\"\z([^"]\+\)\"" matchgroup=shHereDoc07 end="^\z1$" 586 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc08 start="<<-\s*\"\z([^"]\+\)\"" matchgroup=shHereDoc08 end="^\t*\z1$" 587 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc09 start="<<\s*\\\_$\_s*\z([^ \t|>]\+\)" matchgroup=shHereDoc09 end="^\z1$" contains=@shDblQuoteList 588 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc10 start="<<-\s*\\\_$\_s*\z([^ \t|>]\+\)" matchgroup=shHereDoc10 end="^\t*\z1$" contains=@shDblQuoteList 589 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc11 start="<<\s*\\\_$\_s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc11 end="^\z1$" 590 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc12 start="<<-\s*\\\_$\_s*\\\z([^ \t|>]\+\)" matchgroup=shHereDoc12 end="^\t*\z1$" 591 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc13 start="<<\s*\\\_$\_s*'\z([^']\+\)'" matchgroup=shHereDoc13 end="^\z1$" 592 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc14 start="<<-\s*\\\_$\_s*'\z([^']\+\)'" matchgroup=shHereDoc14 end="^\t*\z1$" 593 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc15 start="<<\s*\\\_$\_s*\"\z([^"]\+\)\"" matchgroup=shHereDoc15 end="^\z1$" 594 ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc16 start="<<-\s*\\\_$\_s*\"\z([^"]\+\)\"" matchgroup=shHereDoc16 end="^\t*\z1$" 595 596 597 " Here Strings: {{{1 598 " ============= 599 " available for: bash and ksh (except ksh88) but not if its a posix 600 if exists("b:is_bash") || ((exists("b:is_kornshell") && !exists("b:is_ksh88")) && !exists("b:is_posix")) 601 syn match shHereString "<<<" skipwhite nextgroup=shCmdParenRegion 602 endif 603 604 " Identifiers: {{{1 605 "============= 606 syn match shSetOption "\s\zs[-+][a-zA-Z0-9]\+\>" contained 607 syn match shVariable "\<\h\w*\ze=" nextgroup=shVarAssign 608 if exists("b:is_bash") 609 " The subscript form for array values, e.g. "foo=([2]=10 [4]=100)". 610 syn region shArrayValue contained start="\[\%(..\{-}\]=\)\@=" end="\]=\@=" contains=@shArrayValueList nextgroup=shVarAssign 611 syn cluster shArrayValueList contains=shArithmetic,shArithParen,shCommandSub,shDeref,shDerefSimple,shExpr,shNumber,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shSpecial,shParen,bashSpecialVariables,shParenError 612 syn region shArrayRegion contained matchgroup=shShellVariables start="(" skip='\\\\\|\\.' end=")" contains=@shArrayValueList,shArrayValue,shComment 613 elseif (exists("b:is_kornshell") && !exists("b:is_ksh88")) 614 " The subscript form for array values, e.g. "foo=([2]=10 [4]=100)". 615 syn region shArrayValue contained start="\[\%(..\{-}\]=\)\@=" end="\]=\@=" contains=@shArrayValueList nextgroup=shVarAssign 616 syn cluster shArrayValueList contains=shArithmetic,shArithParen,shCommandSub,shDeref,shDerefSimple,shExpr,shNumber,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shSpecial,shParen,kshSpecialVariables,shParenError 617 syn region shArrayRegion contained matchgroup=shShellVariables start="(" skip='\\\\\|\\.' end=")" contains=@shArrayValueList,shArrayValue,shComment,shArrayRegion 618 endif 619 if exists("b:is_bash") || exists("b:is_kornshell") 620 syn match shVariable "\<\h\w*\%(\[..\{-}\]\)\=\ze\%([|^&*/%+-]\|[<^]<\|[>^]>\)\==" contains=shDerefVarArray nextgroup=shVarAssign 621 syn match shVarAssign contained "\%([|^&*/%+-]\|[<^]<\|[>^]>\)\==" nextgroup=shArrayRegion,shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote,shVar 622 else 623 syn match shVarAssign contained "=" nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote,shVar 624 endif 625 syn match shVar contained "\h\w*" 626 syn region shAtExpr contained start="@(" end=")" contains=@shIdList 627 if exists("b:is_bash") 628 syn match shSet "^\s*set\ze\s\+$" 629 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 630 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 631 elseif exists("b:is_kornshell") || exists("b:is_posix") 632 syn match shSet "^\s*set\ze\s\+$" 633 if exists("b:is_dash") 634 syn region shSetList oneline matchgroup=shSet start="\<\%(local\)\>\ze[/]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList 635 syn keyword shStatement chdir 636 endif 637 syn region shSetList oneline matchgroup=shSet start="\<\(export\)\>\ze[/]\@!" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList 638 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 639 else 640 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 641 endif 642 643 " KornShell namespace: {{{1 644 if exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh") 645 syn keyword shFunctionKey namespace skipwhite skipnl nextgroup=shNamespaceOne 646 endif 647 648 " Functions: {{{1 649 if !exists("b:is_posix") 650 syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo 651 endif 652 653 if exists("b:is_bash") 654 syn keyword shFunctionKey coproc 655 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 656 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 657 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 658 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 659 elseif exists("b:is_ksh88") 660 " AT&T ksh88 661 ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*[A-Za-z_][A-Za-z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 662 ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_][A-Za-z_0-9]*\>\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 663 ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*[A-Za-z_][A-Za-z_0-9]*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 664 ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_][A-Za-z_0-9]*\>\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 665 elseif exists("b:is_mksh") 666 " MirBSD ksh is the wild west of absurd and abstruse function names... 667 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 668 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 669 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 670 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 671 elseif exists("b:is_kornshell") 672 " ksh93 673 ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*[A-Za-z_.][A-Za-z_.0-9]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 674 ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_.][A-Za-z_.0-9]*\>\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 675 ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*[A-Za-z_.][A-Za-z_.0-9]*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 676 ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_.][A-Za-z_.0-9]*\>\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 677 ShFoldFunctions syn region shNamespaceOne matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 678 else 679 ShFoldFunctions syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 680 ShFoldFunctions syn region shFunctionTwo matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 681 ShFoldFunctions syn region shFunctionThree matchgroup=shFunction start="^\s*\h\w*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 682 ShFoldFunctions syn region shFunctionFour matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 683 endif 684 685 " Parameter Dereferencing: {{{1 686 " ======================== 687 if !exists("g:sh_no_error") 688 syn match shDerefWordError "[^}$[~]" contained 689 endif 690 syn match shDerefSimple "\$\%(\h\w*\|\d\)" nextgroup=@shNoZSList 691 if exists("b:is_kornshell") && !exists("b:is_ksh88") 692 if exists("b:is_mksh") 693 syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart 694 elseif exists("b:generic_korn") 695 syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n<|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart 696 else 697 syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n<]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart 698 endif 699 elseif exists("b:is_bash") 700 syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart 701 else 702 syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart 703 endif 704 syn match shDerefSimple "\$[-#*@!?]" nextgroup=@shNoZSList 705 syn match shDerefSimple "\$\$" nextgroup=@shNoZSList 706 syn match shDerefSimple "\${\d}" nextgroup=@shNoZSList nextgroup=shSpecialStart 707 if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix") 708 syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList nextgroup=@shSpecialNoZS,shSpecialStart 709 syn region shDeref matchgroup=PreProc start="\${\$\$" end="}" contains=@shDerefList nextgroup=@shSpecialNoZS,shSpecialStart 710 endif 711 712 " ksh: ${.sh.*} variables: {{{1 713 " ======================================== 714 if exists("b:is_kornshell") && !exists("b:is_ksh88") && !exists("b:is_mksh") 715 syn match shDerefVar contained "\.\+" nextgroup=@shDerefVarList 716 syn region shDeref matchgroup=PreProc start="\${\ze[\.]" end="}" contains=@shDerefVarList,shDerefPSR,shDerefPPS 717 endif 718 719 " ksh: ${!var[*]} array index list syntax: {{{1 720 " ======================================== 721 if (exists("b:is_kornshell") && !exists("b:is_ksh88")) || exists("b:is_posix") 722 syn region shDeref matchgroup=PreProc start="\${!" end="}" contains=@shDerefVarArray 723 endif 724 725 " bash: ${!prefix*} and ${#parameter}: {{{1 726 " ==================================== 727 if exists("b:is_bash") 728 syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOffset 729 syn match shDerefVar contained "{\@<=!\h\w*" nextgroup=@shDerefVarList 730 endif 731 if (exists("b:is_kornshell") && !exists("b:is_ksh88")) 732 syn match shDerefVar contained "{\@<=!\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList 733 endif 734 735 syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOffset,shDerefOpError 736 syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp 737 syn match shDerefVar contained "{\@<=\h\w*" nextgroup=@shDerefVarList 738 syn match shDerefVar contained '\d' nextgroup=@shDerefVarList 739 if exists("b:is_kornshell") || exists("b:is_posix") 740 syn match shDerefVar contained "{\@<=\h\w*[[:alnum:]_.]*" nextgroup=@shDerefVarList 741 endif 742 743 " sh ksh bash : ${var[... ]...} array reference: {{{1 744 syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError,shDerefOffset 745 746 " Special ${parameter OPERATOR word} handling: {{{1 747 " sh ksh bash : ${parameter:-word} word is default value 748 " sh ksh bash : ${parameter:=word} assign word as default value 749 " sh ksh bash : ${parameter:?word} display word if parameter is null 750 " sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing 751 " ksh bash : ${parameter#pattern} remove small left pattern 752 " ksh bash : ${parameter##pattern} remove large left pattern 753 " ksh bash : ${parameter%pattern} remove small right pattern 754 " ksh bash : ${parameter%%pattern} remove large right pattern 755 " ksh bash : ${parameter^pattern} Case modification 756 " ksh bash : ${parameter^^pattern} Case modification 757 " ksh bash : ${parameter,pattern} Case modification 758 " ksh bash : ${parameter,,pattern} Case modification 759 " bash : ${@:start:qty} display command line arguments from start to start+qty-1 (inferred) 760 " bash : ${parameter@operator} transforms parameter (operator∈[uULqEPARa]) 761 syn cluster shDerefPatternList contains=shDerefPattern,shDerefString 762 if !exists("g:sh_no_error") 763 syn match shDerefOpError contained ":[[:punct:]]" 764 endif 765 syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList 766 syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList 767 if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix") 768 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList 769 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList 770 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern skipnl 771 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern 772 " Match parametric bracket expressions with a leading whitespace character. 773 syn region shDerefPattern contained matchgroup=shBracketExprDelim start="\[" end="\]" contains=@shBracketExprList,shDoubleQuote nextgroup=shDerefPattern 774 call s:GenerateBracketExpressionItems({'itemGroup': 'shDerefPattern', 'bracketGroup': 'shBracketExprDelim', 'extraArgs': 'contained nextgroup=shDerefPattern'}) 775 syn match shDerefEscape contained '\%(\\\\\)*\\.' 776 endif 777 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")) 778 syn match shDerefOp contained "[,^]\{1,2}" nextgroup=@shDerefPatternList 779 endif 780 if exists("b:is_bash") 781 syn match shDerefOp contained "@[uULQEPAKa]" 782 endif 783 syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!'+ end=+'+ 784 syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial 785 syn match shDerefString contained "\\["']" nextgroup=shDerefPattern 786 787 if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88")) || exists("b:is_posix") 788 " bash ksh posix : ${parameter:offset} 789 " bash ksh posix : ${parameter:offset:length} 790 syn region shDerefOffset contained start=':[^-=?+]' end='\ze:' end='\ze}' contains=shDeref,shDerefSimple,shDerefEscape nextgroup=shDerefLen,shDeref,shDerefSimple 791 syn region shDerefOffset contained start=':\s-' end='\ze:' end='\ze}' contains=shDeref,shDerefSimple,shDerefEscape nextgroup=shDerefLen,shDeref,shDerefSimple 792 syn match shDerefLen contained ":[^}]\+" contains=shDeref,shDerefSimple,shArithmetic 793 endif 794 795 if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_ksh88")) 796 " bash ksh : ${parameter/pattern/string} 797 " bash ksh : ${parameter//pattern/string} 798 syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft 799 syn region shDerefPPSleft contained start='.' skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp end='/' end='\ze}' end='"' nextgroup=shDerefPPSright contains=@shPPSLeftList 800 syn region shDerefPPSright contained start='.' skip=@\%(\\\\\)\+@ end='\ze}' contains=@shPPSRightList 801 802 " bash ksh : ${parameter/#pattern/string} 803 " bash ksh : ${parameter/%pattern/string} 804 syn match shDerefPSR contained '/[#%]' nextgroup=shDerefPSRleft,shDoubleQuote,shSingleQuote 805 syn region shDerefPSRleft contained start='[^"']' skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPSRright contains=shBracketExpr 806 syn region shDerefPSRright contained start='.' skip=@\%(\\\\\)\+@ end='\ze}' 807 endif 808 809 " Arithmetic Parenthesized Expressions: {{{1 810 "syn region shParen matchgroup=shArithRegion start='[^$]\zs(\%(\ze[^(]\|$\)' end=')' contains=@shArithParenList 811 syn region shParen matchgroup=shArithRegion start='\$\@!(\%(\ze[^(]\|$\)' end=')' contains=@shArithParenList 812 813 " Additional sh Keywords: {{{1 814 " =================== 815 " builtins: 816 syn 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 wait 817 " external programs: 818 syn 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 xargs 819 syn keyword shConditional contained elif else then 820 if !exists("g:sh_no_error") 821 syn keyword shCondError elif else then 822 endif 823 824 " Synchronization: {{{1 825 " ================ 826 if !exists("g:sh_minlines") 827 let s:sh_minlines = 200 828 else 829 let s:sh_minlines= g:sh_minlines 830 endif 831 if !exists("g:sh_maxlines") 832 let s:sh_maxlines = 2*s:sh_minlines 833 if s:sh_maxlines < 25 834 let s:sh_maxlines= 25 835 endif 836 else 837 let s:sh_maxlines= g:sh_maxlines 838 endif 839 exec "syn sync minlines=" . s:sh_minlines . " maxlines=" . s:sh_maxlines 840 syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>" 841 syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>" 842 syn sync match shDoSync grouphere shDo "\<do\>" 843 syn sync match shDoSync groupthere shDo "\<done\>" 844 syn sync match shForSync grouphere shFor "\<for\>" 845 syn sync match shForSync groupthere shFor "\<in\>" 846 syn sync match shIfSync grouphere shIf "\<if\>" 847 syn sync match shIfSync groupthere shIf "\<fi\>" 848 syn sync match shUntilSync grouphere shRepeat "\<until\>" 849 syn sync match shWhileSync grouphere shRepeat "\<while\>" 850 851 " Default Highlighting: {{{1 852 " ===================== 853 if !exists("skip_sh_syntax_inits") 854 hi def link shArithRegion shShellVariables 855 hi def link shArrayValue shDeref 856 hi def link shAstQuote shDoubleQuote 857 hi def link shAtExpr shSetList 858 hi def link shBkslshSnglQuote shSingleQuote 859 hi def link shBkslshDblQuote shDOubleQuote 860 hi def link shBeginHere shRedir 861 hi def link shCaseBar shConditional 862 hi def link shCaseCommandSub shCommandSub 863 hi def link shCaseDoubleQuote shDoubleQuote 864 hi def link shCaseIn shConditional 865 hi def link shQuote shOperator 866 hi def link shCaseSingleQuote shSingleQuote 867 hi def link shCaseStart shConditional 868 hi def link shCmdSubRegion shShellVariables 869 hi def link shColon shComment 870 hi def link shDerefOp shOperator 871 hi def link shDerefPOL shDerefOp 872 hi def link shDerefPPS shDerefOp 873 hi def link shDerefPSR shDerefOp 874 hi def link shDeref shShellVariables 875 hi def link shDerefDelim shOperator 876 hi def link shDerefSimple shDeref 877 hi def link shDerefSpecial shDeref 878 hi def link shDerefString shDoubleQuote 879 hi def link shDerefVar shDeref 880 hi def link shDoubleQuote shString 881 hi def link shEcho shString 882 hi def link shEchoDelim shOperator 883 hi def link shEchoQuote shString 884 hi def link shForPP shLoop 885 hi def link shFunction Function 886 hi def link shEmbeddedEcho shString 887 hi def link shEscape shCommandSub 888 hi def link shExDoubleQuote shDoubleQuote 889 hi def link shExSingleQuote shSingleQuote 890 hi def link shHereDoc shString 891 hi def link shHereString shRedir 892 hi def link shHerePayload shHereDoc 893 hi def link shLoop shStatement 894 hi def link shSpecialNxt shSpecial 895 hi def link shNoQuote shDoubleQuote 896 hi def link shOption shCommandSub 897 hi def link shPattern shString 898 hi def link shParen shArithmetic 899 hi def link shPosnParm shShellVariables 900 hi def link shQuickComment shComment 901 hi def link shBQComment shComment 902 hi def link shRange shOperator 903 hi def link shRedir shOperator 904 hi def link shSetListDelim shOperator 905 hi def link shSetOption shOption 906 hi def link shSingleQuote shString 907 hi def link shSource shOperator 908 hi def link shStringSpecial shSpecial 909 hi def link shSpecialStart shSpecial 910 hi def link shSubShRegion shOperator 911 hi def link shTestOpr shConditional 912 hi def link shTestPattern shString 913 hi def link shTestDoubleQuote shString 914 hi def link shTestSingleQuote shString 915 hi def link shTouchCmd shStatement 916 hi def link shVariable shSetList 917 hi def link shWrapLineOperator shOperator 918 919 if exists("b:is_bash") 920 hi def link bashAdminStatement shStatement 921 hi def link bashSpecialVariables shShellVariables 922 hi def link bashStatement shStatement 923 hi def link shCharClass shSpecial 924 hi def link shDerefOffset shDerefOp 925 hi def link shDerefLen shDerefOffset 926 endif 927 if exists("b:is_kornshell") || exists("b:is_posix") 928 hi def link kshSpecialVariables shShellVariables 929 hi def link kshStatement shStatement 930 endif 931 932 if !exists("g:sh_no_error") 933 hi def link shCaseError Error 934 hi def link shCondError Error 935 hi def link shCurlyError Error 936 hi def link shDerefOpError Error 937 hi def link shDerefWordError Error 938 hi def link shDoError Error 939 hi def link shEsacError Error 940 hi def link shIfError Error 941 hi def link shInError Error 942 hi def link shParenError Error 943 hi def link shTestError Error 944 if exists("b:is_kornshell") || exists("b:is_posix") 945 hi def link shDTestError Error 946 endif 947 endif 948 949 hi def link shArithmetic Special 950 hi def link shBracketExprDelim Delimiter 951 hi def link shCharClass Identifier 952 hi def link shCollSymb shCharClass 953 hi def link shEqClass shCharClass 954 hi def link shSnglCase Statement 955 hi def link shCommandSub Special 956 hi def link shCommandSubBQ shCommandSub 957 hi def link shSubshare shCommandSub 958 hi def link shValsub shCommandSub 959 hi def link shComment Comment 960 hi def link shConditional Conditional 961 hi def link shCtrlSeq Special 962 hi def link shExprRegion Delimiter 963 hi def link shFunctionKey Function 964 hi def link shFunctionName Function 965 hi def link shNumber Number 966 hi def link shOperator Operator 967 hi def link shRepeat Repeat 968 hi def link shSet Statement 969 hi def link shSetList Identifier 970 hi def link shShellVariables PreProc 971 hi def link shSpecial Special 972 hi def link shSpecialDQ Special 973 hi def link shSpecialSQ Special 974 hi def link shSpecialNoZS shSpecial 975 hi def link shStatement Statement 976 hi def link shString String 977 hi def link shTodo Todo 978 hi def link shAlias Identifier 979 hi def link shHereDoc01 shRedir 980 hi def link shHereDoc02 shRedir 981 hi def link shHereDoc03 shRedir 982 hi def link shHereDoc04 shRedir 983 hi def link shHereDoc05 shRedir 984 hi def link shHereDoc06 shRedir 985 hi def link shHereDoc07 shRedir 986 hi def link shHereDoc08 shRedir 987 hi def link shHereDoc09 shRedir 988 hi def link shHereDoc10 shRedir 989 hi def link shHereDoc11 shRedir 990 hi def link shHereDoc12 shRedir 991 hi def link shHereDoc13 shRedir 992 hi def link shHereDoc14 shRedir 993 hi def link shHereDoc15 shRedir 994 hi def link shHereDoc16 shRedir 995 endif 996 997 " Delete shell folding commands {{{1 998 " ============================= 999 delc ShFoldFunctions 1000 delc ShFoldHereDoc 1001 delc ShFoldIfDoFor 1002 1003 " Delete the bracket expression function {{{1 1004 " ====================================== 1005 delfun s:GenerateBracketExpressionItems 1006 1007 " Set Current Syntax: {{{1 1008 " =================== 1009 if exists("b:is_bash") 1010 let b:current_syntax = "bash" 1011 elseif exists("b:is_kornshell") 1012 let b:current_syntax = "ksh" 1013 elseif exists("b:is_posix") 1014 let b:current_syntax = "posix" 1015 else 1016 let b:current_syntax = "sh" 1017 endif 1018 1019 " vim: ts=16 fdm=marker