1" Vim syntax file 2" Language: shell (sh) Korn shell (ksh) bash (sh) 3" Maintainer: Dr. Charles E. Campbell, Jr. <[email protected]> 4" Previous Maintainer: Lennart Schultz <[email protected]> 5" Last Change: Dec 12, 2006 6" Version: 89 7" URL: http://mysite.verizon.net/astronaut/vim/index.html#vimlinks_syntax 8" 9" Using the following VIM variables: {{{1 10" g:is_bash if none of the previous three variables are 11" defined, then if g:is_bash is set enhance with 12" bash syntax highlighting 13" g:is_kornshell if neither b:is_kornshell or b:is_bash is 14" defined, then if g:is_kornshell is set 15" enhance with kornshell/POSIX syntax highlighting 16" g:is_posix this variable is the same as g:is_kornshell 17" g:sh_fold_enabled if non-zero, syntax folding is enabled 18" g:sh_minlines sets up syn sync minlines (dflt: 200) 19" g:sh_maxlines sets up syn sync maxlines (dflt: 2x sh_minlines) 20" 21" This file includes many ideas from �ric Brunet ([email protected]) 22 23" For version 5.x: Clear all syntax items {{{1 24" For version 6.x: Quit when a syntax file was already loaded 25if version < 600 26 syntax clear 27elseif exists("b:current_syntax") 28 finish 29endif 30 31" handling /bin/sh with is_kornshell/is_sh {{{1 32" b:is_sh is set when "#! /bin/sh" is found; 33" However, it often is just a masquerade by bash (typically Linux) 34" or kornshell (typically workstations with Posix "sh"). 35" So, when the user sets "is_bash" or "is_kornshell", 36" a b:is_sh is converted into b:is_bash/b:is_kornshell, 37" respectively. 38if !exists("b:is_kornshell") && !exists("b:is_bash") 39 if exists("g:is_posix") && !exists("g:is_kornshell") 40 let g:is_kornshell= g:is_posix 41 endif 42 if exists("g:is_kornshell") 43 let b:is_kornshell= 1 44 if exists("b:is_sh") 45 unlet b:is_sh 46 endif 47 elseif exists("g:is_bash") 48 let b:is_bash= 1 49 if exists("b:is_sh") 50 unlet b:is_sh 51 endif 52 else 53 let b:is_sh= 1 54 endif 55endif 56 57" set up default g:sh_fold_enabled {{{1 58if !exists("g:sh_fold_enabled") 59 let g:sh_fold_enabled= 0 60elseif g:sh_fold_enabled != 0 && !has("folding") 61 let g:sh_fold_enabled= 0 62 echomsg "Ignoring g:sh_fold_enabled=".g:sh_fold_enabled."; need to re-compile vim for +fold support" 63endif 64if g:sh_fold_enabled && &fdm == "manual" 65 set fdm=syntax 66endif 67 68" sh syntax is case sensitive {{{1 69syn case match 70 71" Clusters: contains=@... clusters {{{1 72"================================== 73syn cluster shCaseEsacList contains=shCaseStart,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq 74syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq 75syn cluster shColonList contains=@shCaseList 76syn cluster shCommandSubList contains=shArithmetic,shDeref,shDerefSimple,shNumber,shOperator,shPosnParm,shExSingleQuote,shSingleQuote,shDoubleQuote,shStatement,shVariable,shSubSh,shAlias,shTest,shCtrlSeq 77syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial 78syn cluster shDblQuoteList contains=shCommandSub,shDeref,shDerefSimple,shPosnParm,shExSingleQuote,shCtrlSeq,shSpecial 79syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPPS 80syn cluster shDerefVarList contains=shDerefOp,shDerefVarArray,shDerefOpError 81syn cluster shEchoList contains=shArithmetic,shCommandSub,shDeref,shDerefSimple,shExpr,shExSingleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq 82syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq 83syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest 84syn cluster shFunctionList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shFunctionStart,shCtrlSeq 85if exists("b:is_kornshell") || exists("b:is_bash") 86 syn cluster shFunctionList add=shDblBrace,shDblParen 87endif 88syn cluster shHereBeginList contains=@shCommandSubList 89syn cluster shHereList contains=shBeginHere,shHerePayload 90syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload 91syn cluster shIdList contains=shCommandSub,shWrapLineOperator,shIdWhiteSpace,shDeref,shDerefSimple,shRedir,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq 92syn cluster shLoopList contains=@shCaseList,shTestOpr,shExpr,shDblBrace,shConditional,shCaseEsac,shTest 93syn cluster shSubShList contains=@shCaseList,shOperator 94syn cluster shTestList contains=shCharClass,shComment,shCommandSub,shDeref,shDerefSimple,shDoubleQuote,shExpr,shExpr,shNumber,shOperator,shExSingleQuote,shSingleQuote,shTestOpr,shTest,shCtrlSeq 95 96 97" Echo: {{{1 98" ==== 99" This one is needed INSIDE a CommandSub, so that `echo bla` be correct 100syn region shEcho matchgroup=shStatement start="\<echo\>" skip="\\$" matchgroup=shOperator end="$" matchgroup=NONE end="[<>;&|()]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList 101syn region shEcho matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shOperator end="$" matchgroup=NONE end="[<>;&|()]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList 102 103" This must be after the strings, so that bla \" be correct 104syn region shEmbeddedEcho contained matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shOperator end="$" matchgroup=NONE end="[<>;&|`)]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=shNumber,shExSingleQuote,shSingleQuote,shDeref,shDerefSimple,shSpecialVar,shOperator,shDoubleQuote,shCharClass,shCtrlSeq 105 106" Alias: {{{1 107" ===== 108if exists("b:is_kornshell") || exists("b:is_bash") 109 syn match shStatement "\<alias\>" 110 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+\)\@=" skip="\\$" end="\>\|`" 111 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+=\)\@=" skip="\\$" end="=" 112endif 113 114" Error Codes: {{{1 115" ============ 116syn match shDoError "\<done\>" 117syn match shIfError "\<fi\>" 118syn match shInError "\<in\>" 119syn match shCaseError ";;" 120syn match shEsacError "\<esac\>" 121syn match shCurlyError "}" 122syn match shParenError ")" 123if exists("b:is_kornshell") 124 syn match shDTestError "]]" 125endif 126syn match shTestError "]" 127 128" Options Interceptor: {{{1 129" ==================== 130syn match shOption "\s[\-+][a-zA-Z0-9]\+\>"ms=s+1 131syn match shOption "\s--[^ \t$`'"|]\+"ms=s+1 132 133" File Redirection Highlighted As Operators: {{{1 134"=========================================== 135syn match shRedir "\d\=>\(&[-0-9]\)\=" 136syn match shRedir "\d\=>>-\=" 137syn match shRedir "\d\=<\(&[-0-9]\)\=" 138syn match shRedir "\d<<-\=" 139 140" Operators: {{{1 141" ========== 142syn match shOperator "<<\|>>" contained 143syn match shOperator "[!&;|]" 144syn match shOperator "\[[[^:]\|\]]" 145syn match shOperator "!\==" skipwhite nextgroup=shPattern 146syn match shPattern "\<\S\+\())\)\@=" contained contains=shExSingleQuote,shSingleQuote,shDoubleQuote,shDeref 147 148" Subshells: {{{1 149" ========== 150syn region shExpr transparent matchgroup=shExprRegion start="{" end="}" contains=@shExprList2 151syn region shSubSh transparent matchgroup=shSubShRegion start="(" end=")" contains=@shSubShList 152 153" Tests: {{{1 154"======= 155"syn region shExpr transparent matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList 156syn region shExpr matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList 157syn region shTest transparent matchgroup=shStatement start="\<test\>" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1 158syn match shTestOpr contained "<=\|>=\|!=\|==\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]" 159syn match shTestOpr contained '=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern 160syn match shTestPattern contained '\w\+' 161syn match shTestDoubleQuote contained '"[^"]*"' 162syn match shTestSingleQuote contained '\\.' 163syn match shTestSingleQuote contained "'[^']*'" 164if exists("b:is_kornshell") || exists("b:is_bash") 165 syn region shDblBrace matchgroup=Delimiter start="\[\[" skip=+\\\\\|\\$+ end="\]\]" contains=@shTestList 166 syn region shDblParen matchgroup=Delimiter start="((" skip=+\\\\\|\\$+ end="))" contains=@shTestList 167endif 168 169" Character Class In Range: {{{1 170" ========================= 171syn match shCharClass contained "\[:\(backspace\|escape\|return\|xdigit\|alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|tab\):\]" 172 173" Loops: do, if, while, until {{{1 174" ====== 175if g:sh_fold_enabled 176 syn region shDo fold transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList 177 syn region shIf fold transparent matchgroup=shConditional start="\<if\>" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>" contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey 178 syn region shFor fold matchgroup=shLoop start="\<for\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn 179else 180 syn region shDo transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList 181 syn region shIf transparent matchgroup=shConditional start="\<if\>" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>" contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey 182 syn region shFor matchgroup=shLoop start="\<for\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn 183endif 184if exists("b:is_kornshell") || exists("b:is_bash") 185 syn cluster shCaseList add=shRepeat 186 syn region shRepeat matchgroup=shLoop start="\<while\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace 187 syn region shRepeat matchgroup=shLoop start="\<until\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace 188 syn region shCaseEsac matchgroup=shConditional start="\<select\>" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList 189else 190 syn region shRepeat matchgroup=shLoop start="\<while\>" end="\<do\>"me=e-2 contains=@shLoopList 191 syn region shRepeat matchgroup=shLoop start="\<until\>" end="\<do\>"me=e-2 contains=@shLoopList 192endif 193syn region shCurlyIn contained matchgroup=Delimiter start="{" end="}" contains=@shCurlyList 194syn match shComma contained "," 195 196" Case: case...esac {{{1 197" ==== 198syn match shCaseBar contained skipwhite "[^|"`'()]\{-}|"hs=e nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote 199syn match shCaseStart contained skipwhite skipnl "(" nextgroup=shCase,shCaseBar 200syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="\([^#$()'" \t]\|\\.\)\{-})"ms=s,hs=e end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment 201if g:sh_fold_enabled 202 syn region shCaseEsac fold matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList 203else 204 syn region shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList 205endif 206syn keyword shCaseIn contained skipwhite skipnl in nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote 207if exists("b:is_bash") 208 syn region shCaseExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial skipwhite skipnl nextgroup=shCaseBar contained 209else 210 syn region shCaseExSingleQuote matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 211endif 212syn region shCaseSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 213syn region shCaseDoubleQuote matchgroup=shOperator start=+"+ skip=+\\\\\|\\.+ end=+"+ contains=@shDblQuoteList,shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 214syn region shCaseCommandSub start=+`+ skip=+\\\\\|\\.+ end=+`+ contains=@shCommandSubList skipwhite skipnl nextgroup=shCaseBar contained 215 216" Misc: {{{1 217"====== 218syn match shWrapLineOperator "\\$" 219syn region shCommandSub start="`" skip="\\\\\|\\." end="`" contains=@shCommandSubList 220 221" $() and $(()): {{{1 222" $(..) is not supported by sh (Bourne shell). However, apparently 223" some systems (HP?) have as their /bin/sh a (link to) Korn shell 224" (ie. Posix compliant shell). /bin/ksh should work for those 225" systems too, however, so the following syntax will flag $(..) as 226" an Error under /bin/sh. By consensus of vimdev'ers! 227if exists("b:is_kornshell") || exists("b:is_bash") 228 syn region shCommandSub matchgroup=shCmdSubRegion start="\$(" skip='\\\\\|\\.' end=")" contains=@shCommandSubList 229 syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shCommandSubList 230 syn match shSkipInitWS contained "^\s\+" 231else 232 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList 233endif 234 235if exists("b:is_bash") 236 syn cluster shCommandSubList add=bashSpecialVariables,bashStatement 237 syn cluster shCaseList add=bashAdminStatement,bashStatement 238 syn keyword bashSpecialVariables contained BASH BASH_ENV BASH_VERSINFO BASH_VERSION CDPATH DIRSTACK EUID FCEDIT FIGNORE GLOBIGNORE GROUPS HISTCMD HISTCONTROL HISTFILE HISTFILESIZE HISTIGNORE HISTSIZE HOME HOSTFILE HOSTNAME HOSTTYPE IFS IGNOREEOF INPUTRC LANG LC_ALL LC_COLLATE LC_MESSAGES LINENO MACHTYPE MAIL MAILCHECK MAILPATH OLDPWD OPTARG OPTERR OPTIND OSTYPE PATH PIPESTATUS PPID PROMPT_COMMAND PS1 PS2 PS3 PS4 PWD RANDOM REPLY SECONDS SHELLOPTS SHLVL TIMEFORMAT TIMEOUT UID auto_resume histchars 239 syn keyword bashStatement chmod clear complete du egrep expr fgrep find gnufind gnugrep grep install less ls mkdir mv rm rmdir rpm sed sleep sort strip tail touch 240 syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop 241endif 242 243if exists("b:is_kornshell") 244 syn cluster shCommandSubList add=kshSpecialVariables,kshStatement 245 syn cluster shCaseList add=kshStatement 246 syn keyword kshSpecialVariables contained CDPATH COLUMNS EDITOR ENV ERRNO FCEDIT FPATH HISTFILE HISTSIZE HOME IFS LINENO LINES MAIL MAILCHECK MAILPATH OLDPWD OPTARG OPTIND PATH PPID PS1 PS2 PS3 PS4 PWD RANDOM REPLY SECONDS SHELL TMOUT VISUAL 247 syn keyword kshStatement cat chmod clear cp du egrep expr fgrep find grep install killall less ls mkdir mv nice printenv rm rmdir sed sort strip stty tail touch tput 248endif 249 250syn match shSource "^\.\s" 251syn match shSource "\s\.\s" 252syn region shColon start="^\s*:" end="$\|" end="#"me=e-1 contains=@shColonList 253 254" String And Character Constants: {{{1 255"================================ 256syn match shNumber "-\=\<\d\+\>#\=" 257syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained 258if exists("b:is_bash") 259 syn match shSpecial "\\\o\o\o\|\\x\x\x\|\\c.\|\\[abefnrtv]" contained 260endif 261if exists("b:is_bash") 262 syn region shExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial 263else 264 syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial 265endif 266syn region shSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial,@Spell 267syn region shDoubleQuote matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell 268syn match shStringSpecial "[^[:print:]]" contained 269syn match shStringSpecial "\%(\\\\\)*\\[\\"'`$()#]" 270syn match shSpecial "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]" 271syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]" 272 273" Comments: {{{1 274"========== 275syn cluster shCommentGroup contains=shTodo,@Spell 276syn keyword shTodo contained COMBAK FIXME TODO XXX 277syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup 278syn match shComment "#.*$" contains=@shCommentGroup 279 280" Here Documents: {{{1 281" ========================================= 282if version < 600 283 syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList 284 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^\s*END[a-zA-Z_0-9]*$" contains=@shDblQuoteList 285 syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir end="^EOF$" contains=@shDblQuoteList 286 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir end="^\s*EOF$" contains=@shDblQuoteList 287 syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**" matchgroup=shRedir end="^\.$" contains=@shDblQuoteList 288 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir end="^\s*\.$" contains=@shDblQuoteList 289 290elseif g:sh_fold_enabled 291 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList 292 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 293 syn region shHereDoc matchgroup=shRedir fold start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 294 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList 295 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 296 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 297 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 298 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 299 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 300 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" 301 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 302 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 303 syn region shHereDoc matchgroup=shRedir fold start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 304 305else 306 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList 307 syn region shHereDoc matchgroup=shRedir start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 308 syn region shHereDoc matchgroup=shRedir start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList 309 syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 310 syn region shHereDoc matchgroup=shRedir start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 311 syn region shHereDoc matchgroup=shRedir start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 312 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 313 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" 314 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 315 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 316 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 317 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 318 syn region shHereDoc matchgroup=shRedir start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 319endif 320 321" Here Strings: {{{1 322" ============= 323if exists("b:is_bash") 324 syn match shRedir "<<<" 325endif 326 327" Identifiers: {{{1 328"============= 329syn match shVariable "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze=" nextgroup=shSetIdentifier 330syn match shIdWhiteSpace contained "\s" 331syn match shSetIdentifier contained "=" nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shSingleQuote,shExSingleQuote 332if exists("b:is_bash") 333 syn region shSetList matchgroup=shSet start="\<\(declare\|typeset\|local\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[|);&]"me=e-1 matchgroup=NONE end="#\|="me=e-1 contains=@shIdList 334 syn region shSetList matchgroup=shSet start="\<set\>[^/]"me=e-1 end="$" end="\\ze[|)]" matchgroup=shOperator end="\ze[|);&]"me=e-1 matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList 335 syn match shSet "\<\(declare\|typeset\|local\|export\|set\|unset\)\>" 336elseif exists("b:is_kornshell") 337 syn region shSetList matchgroup=shSet start="\<\(typeset\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[|);&]"me=e-1 matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList 338 syn region shSetList matchgroup=shSet start="\<set\>\ze[^/]" end="$\|\ze[})]" matchgroup=shOperator end="\ze[|);&]"me=e-1 matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList 339 syn match shSet "\<\(typeset\|set\|export\|unset\)\>" 340else 341 syn region shSetList matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[^/]" end="$\|\ze[|)]" matchgroup=shOperator end="\ze[|);&]" matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList 342 syn match shStatement "\<\(set\|export\|unset\)\>" 343endif 344 345" Functions: {{{1 346syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo 347" COMBAK -- look at bash09. function foo() (line#35) is folding 38 lines. Not being terminated properly 348"syn match shFunctionStart "{" contained 349if g:sh_fold_enabled 350 syn region shFunctionOne transparent fold start="^\s*\h\w*\s*()\_s*\ze{" matchgroup=shFunctionStart end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart 351 syn region shFunctionTwo transparent fold start="\h\w*\s*\%(()\)\=\_s*\ze{" matchgroup=shFunctionStart end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart 352else 353 syn region shFunctionOne transparent start="^\s*\h\w*\s*()\_s*\ze{" matchgroup=shFunctionStart end="}" contains=@shFunctionList 354 syn region shFunctionTwo transparent start="\h\w*\s*\%(()\)\=\_s*\ze{" matchgroup=shFunctionStart end="}" contains=shFunctionKey,@shFunctionList contained 355endif 356 357" Parameter Dereferencing: {{{1 358" ======================== 359syn match shDerefSimple "\$\%(\h\w*\|\d\)" 360syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray 361syn match shDerefWordError "[^}$[]" contained 362syn match shDerefSimple "\$[-#*@!?]" 363syn match shDerefSimple "\$\$" 364if exists("b:is_bash") || exists("b:is_kornshell") 365 syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList 366endif 367 368" bash: ${!prefix*} and ${#parameter}: {{{1 369" ==================================== 370if exists("b:is_bash") 371 syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOp 372 syn match shDerefVar contained "{\@<=!\w\+" nextgroup=@shDerefVarList 373endif 374 375syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOpError 376syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp 377syn match shDerefVar contained "{\@<=\w\+" nextgroup=@shDerefVarList 378 379" sh ksh bash : ${var[... ]...} array reference: {{{1 380syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError 381 382" Special ${parameter OPERATOR word} handling: {{{1 383" sh ksh bash : ${parameter:-word} word is default value 384" sh ksh bash : ${parameter:=word} assign word as default value 385" sh ksh bash : ${parameter:?word} display word if parameter is null 386" sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing 387" ksh bash : ${parameter#pattern} remove small left pattern 388" ksh bash : ${parameter##pattern} remove large left pattern 389" ksh bash : ${parameter%pattern} remove small right pattern 390" ksh bash : ${parameter%%pattern} remove large right pattern 391syn cluster shDerefPatternList contains=shDerefPattern,shDerefString 392syn match shDerefOpError contained ":[[:punct:]]" 393syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList 394syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList 395if exists("b:is_bash") || exists("b:is_kornshell") 396 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList 397 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList 398 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern 399 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern 400 syn match shDerefEscape contained '\%(\\\\\)*\\.' 401endif 402syn region shDerefString contained matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial 403syn region shDerefString contained matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial 404syn match shDerefString contained "\\["']" 405 406if exists("b:is_bash") 407 " bash : ${parameter:offset} 408 " bash : ${parameter:offset:length} 409 syn region shDerefOp contained start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL 410 syn match shDerefPOL contained ":[^}]\+" contains=@shCommandSubList 411 412 " bash : ${parameter//pattern/string} 413 " bash : ${parameter//pattern} 414 syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft 415 syn region shDerefPPSleft contained start='.' skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList 416 syn region shDerefPPSright contained start='.' end='\ze}' contains=@shCommandSubList 417endif 418 419" Useful sh Keywords: {{{1 420" =================== 421syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait 422syn keyword shConditional contained elif else then 423syn keyword shCondError elif else then 424 425" Useful ksh Keywords: {{{1 426" ==================== 427if exists("b:is_kornshell") || exists("b:is_bash") 428 syn keyword shStatement autoload bg false fc fg functions getopts hash history integer jobs let nohup print printf r stop suspend time times true type unalias whence 429 430" Useful bash Keywords: {{{1 431" ===================== 432 if exists("b:is_bash") 433 syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source 434 else 435 syn keyword shStatement login newgrp 436 endif 437endif 438 439" Synchronization: {{{1 440" ================ 441if !exists("sh_minlines") 442 let sh_minlines = 200 443endif 444if !exists("sh_maxlines") 445 let sh_maxlines = 2 * sh_minlines 446endif 447exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines 448syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>" 449syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>" 450syn sync match shDoSync grouphere shDo "\<do\>" 451syn sync match shDoSync groupthere shDo "\<done\>" 452syn sync match shForSync grouphere shFor "\<for\>" 453syn sync match shForSync groupthere shFor "\<in\>" 454syn sync match shIfSync grouphere shIf "\<if\>" 455syn sync match shIfSync groupthere shIf "\<fi\>" 456syn sync match shUntilSync grouphere shRepeat "\<until\>" 457syn sync match shWhileSync grouphere shRepeat "\<while\>" 458 459" Default Highlighting: {{{1 460" ===================== 461hi def link shArithRegion shShellVariables 462hi def link shBeginHere shRedir 463hi def link shCaseBar shConditional 464hi def link shCaseCommandSub shCommandSub 465hi def link shCaseDoubleQuote shDoubleQuote 466hi def link shCaseIn shConditional 467hi def link shCaseSingleQuote shSingleQuote 468hi def link shCaseStart shConditional 469hi def link shCmdSubRegion shShellVariables 470hi def link shColon shStatement 471hi def link shDerefOp shOperator 472hi def link shDerefPOL shDerefOp 473hi def link shDerefPPS shDerefOp 474hi def link shDeref shShellVariables 475hi def link shDerefSimple shDeref 476hi def link shDerefSpecial shDeref 477hi def link shDerefString shDoubleQuote 478hi def link shDerefVar shDeref 479hi def link shDoubleQuote shString 480hi def link shEcho shString 481hi def link shEmbeddedEcho shString 482hi def link shExSingleQuote shSingleQuote 483hi def link shFunctionStart Delimiter 484hi def link shHereDoc shString 485hi def link shHerePayload shHereDoc 486hi def link shLoop shStatement 487hi def link shOption shCommandSub 488hi def link shPattern shString 489hi def link shPosnParm shShellVariables 490hi def link shRange shOperator 491hi def link shRedir shOperator 492hi def link shSingleQuote shString 493hi def link shSource shOperator 494hi def link shStringSpecial shSpecial 495hi def link shSubShRegion shOperator 496hi def link shTestOpr shConditional 497hi def link shTestPattern shString 498hi def link shTestDoubleQuote shString 499hi def link shTestSingleQuote shString 500hi def link shVariable shSetList 501hi def link shWrapLineOperator shOperator 502 503if exists("b:is_bash") 504 hi def link bashAdminStatement shStatement 505 hi def link bashSpecialVariables shShellVariables 506 hi def link bashStatement shStatement 507 hi def link shFunctionParen Delimiter 508 hi def link shFunctionDelim Delimiter 509endif 510if exists("b:is_kornshell") 511 hi def link kshSpecialVariables shShellVariables 512 hi def link kshStatement shStatement 513 hi def link shFunctionParen Delimiter 514endif 515 516hi def link shCaseError Error 517hi def link shCondError Error 518hi def link shCurlyError Error 519hi def link shDerefError Error 520hi def link shDerefOpError Error 521hi def link shDerefWordError Error 522hi def link shDoError Error 523hi def link shEsacError Error 524hi def link shIfError Error 525hi def link shInError Error 526hi def link shParenError Error 527hi def link shTestError Error 528if exists("b:is_kornshell") 529 hi def link shDTestError Error 530endif 531 532hi def link shArithmetic Special 533hi def link shCharClass Identifier 534hi def link shSnglCase Statement 535hi def link shCommandSub Special 536hi def link shComment Comment 537hi def link shConditional Conditional 538hi def link shCtrlSeq Special 539hi def link shExprRegion Delimiter 540hi def link shFunctionKey Function 541hi def link shFunctionName Function 542hi def link shNumber Number 543hi def link shOperator Operator 544hi def link shRepeat Repeat 545hi def link shSet Statement 546hi def link shSetList Identifier 547hi def link shShellVariables PreProc 548hi def link shSpecial Special 549hi def link shStatement Statement 550hi def link shString String 551hi def link shTodo Todo 552hi def link shAlias Identifier 553 554" Set Current Syntax: {{{1 555" =================== 556if exists("b:is_bash") 557 let b:current_syntax = "bash" 558elseif exists("b:is_kornshell") 559 let b:current_syntax = "ksh" 560else 561 let b:current_syntax = "sh" 562endif 563 564" vim: ts=16 fdm=marker 565