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: Apr 24, 2008 6" Version: 90 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 209 syn region shCaseExDoubleQuote matchgroup=shOperator start=+\$"+ skip=+\\\\\|\\.+ end=+"+ contains=shStringSpecial,shSpecial,shCommandSub,shDeref skipwhite skipnl nextgroup=shCaseBar contained 210else 211 syn region shCaseExSingleQuote matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 212endif 213syn region shCaseSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 214syn region shCaseDoubleQuote matchgroup=shOperator start=+"+ skip=+\\\\\|\\.+ end=+"+ contains=@shDblQuoteList,shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 215syn region shCaseCommandSub start=+`+ skip=+\\\\\|\\.+ end=+`+ contains=@shCommandSubList skipwhite skipnl nextgroup=shCaseBar contained 216 217" Misc: {{{1 218"====== 219syn match shWrapLineOperator "\\$" 220syn region shCommandSub start="`" skip="\\\\\|\\." end="`" contains=@shCommandSubList 221 222" $() and $(()): {{{1 223" $(..) is not supported by sh (Bourne shell). However, apparently 224" some systems (HP?) have as their /bin/sh a (link to) Korn shell 225" (ie. Posix compliant shell). /bin/ksh should work for those 226" systems too, however, so the following syntax will flag $(..) as 227" an Error under /bin/sh. By consensus of vimdev'ers! 228if exists("b:is_kornshell") || exists("b:is_bash") 229 syn region shCommandSub matchgroup=shCmdSubRegion start="\$(" skip='\\\\\|\\.' end=")" contains=@shCommandSubList 230 syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shCommandSubList 231 syn match shSkipInitWS contained "^\s\+" 232else 233 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList 234endif 235 236if exists("b:is_bash") 237 syn cluster shCommandSubList add=bashSpecialVariables,bashStatement 238 syn cluster shCaseList add=bashAdminStatement,bashStatement 239 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 240 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 241 syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop 242endif 243 244if exists("b:is_kornshell") 245 syn cluster shCommandSubList add=kshSpecialVariables,kshStatement 246 syn cluster shCaseList add=kshStatement 247 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 248 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 249endif 250 251syn match shSource "^\.\s" 252syn match shSource "\s\.\s" 253syn region shColon start="^\s*:" end="$\|" end="#"me=e-1 contains=@shColonList 254 255" String And Character Constants: {{{1 256"================================ 257syn match shNumber "-\=\<\d\+\>#\=" 258syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained 259if exists("b:is_bash") 260 syn match shSpecial "\\\o\o\o\|\\x\x\x\|\\c.\|\\[abefnrtv]" contained 261endif 262if exists("b:is_bash") 263 syn region shExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial 264 syn region shExDoubleQuote matchgroup=shOperator start=+\$"+ skip=+\\\\\|\\.+ end=+"+ contains=shStringSpecial,shSpecial,shCommandSub,shDeref 265else 266 syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial 267endif 268syn region shSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial,@Spell 269syn region shDoubleQuote matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell 270syn match shStringSpecial "[^[:print:]]" contained 271syn match shStringSpecial "\%(\\\\\)*\\[\\"'`$()#]" 272syn match shSpecial "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]" 273syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]" 274 275" Comments: {{{1 276"========== 277syn cluster shCommentGroup contains=shTodo,@Spell 278syn keyword shTodo contained COMBAK FIXME TODO XXX 279syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup 280syn match shComment "#.*$" contains=@shCommentGroup 281 282" Here Documents: {{{1 283" ========================================= 284if version < 600 285 syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList 286 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 287 syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir end="^EOF$" contains=@shDblQuoteList 288 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir end="^\s*EOF$" contains=@shDblQuoteList 289 syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**" matchgroup=shRedir end="^\.$" contains=@shDblQuoteList 290 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir end="^\s*\.$" contains=@shDblQuoteList 291 292elseif g:sh_fold_enabled 293 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList 294 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 295 syn region shHereDoc matchgroup=shRedir fold start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 296 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList 297 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 298 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 299 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 300 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\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="^\s*\z1\s*$" 303 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 304 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 305 syn region shHereDoc matchgroup=shRedir fold start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 306 307else 308 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList 309 syn region shHereDoc matchgroup=shRedir start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 310 syn region shHereDoc matchgroup=shRedir start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList 311 syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 312 syn region shHereDoc matchgroup=shRedir start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 313 syn region shHereDoc matchgroup=shRedir start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 314 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 315 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" 316 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 317 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 318 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 319 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 320 syn region shHereDoc matchgroup=shRedir start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 321endif 322 323" Here Strings: {{{1 324" ============= 325if exists("b:is_bash") 326 syn match shRedir "<<<" 327endif 328 329" Identifiers: {{{1 330"============= 331syn match shVariable "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze=" nextgroup=shSetIdentifier 332syn match shIdWhiteSpace contained "\s" 333syn match shSetIdentifier contained "=" nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shSingleQuote,shExSingleQuote 334if exists("b:is_bash") 335 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 336 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 337 syn match shSet "\<\(declare\|typeset\|local\|export\|set\|unset\)\>" 338elseif exists("b:is_kornshell") 339 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 340 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 341 syn match shSet "\<\(typeset\|set\|export\|unset\)\>" 342else 343 syn region shSetList matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[^/]" end="$\|\ze[|)]" matchgroup=shOperator end="\ze[|);&]" matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList 344 syn match shStatement "\<\(set\|export\|unset\)\>" 345endif 346 347" Functions: {{{1 348syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo 349" COMBAK -- look at bash09. function foo() (line#35) is folding 38 lines. Not being terminated properly 350"syn match shFunctionStart "{" contained 351if g:sh_fold_enabled 352 syn region shFunctionOne transparent fold start="^\s*\h\w*\s*()\_s*\ze{" matchgroup=shFunctionStart end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart 353 syn region shFunctionTwo transparent fold start="\h\w*\s*\%(()\)\=\_s*\ze{" matchgroup=shFunctionStart end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart 354else 355 syn region shFunctionOne transparent start="^\s*\h\w*\s*()\_s*\ze{" matchgroup=shFunctionStart end="}" contains=@shFunctionList 356 syn region shFunctionTwo transparent start="\h\w*\s*\%(()\)\=\_s*\ze{" matchgroup=shFunctionStart end="}" contains=shFunctionKey,@shFunctionList contained 357endif 358 359" Parameter Dereferencing: {{{1 360" ======================== 361syn match shDerefSimple "\$\%(\h\w*\|\d\)" 362syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray 363syn match shDerefWordError "[^}$[]" contained 364syn match shDerefSimple "\$[-#*@!?]" 365syn match shDerefSimple "\$\$" 366if exists("b:is_bash") || exists("b:is_kornshell") 367 syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList 368endif 369 370" bash: ${!prefix*} and ${#parameter}: {{{1 371" ==================================== 372if exists("b:is_bash") 373 syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOp 374 syn match shDerefVar contained "{\@<=!\w\+" nextgroup=@shDerefVarList 375endif 376 377syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOpError 378syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp 379syn match shDerefVar contained "{\@<=\w\+" nextgroup=@shDerefVarList 380 381" sh ksh bash : ${var[... ]...} array reference: {{{1 382syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError 383 384" Special ${parameter OPERATOR word} handling: {{{1 385" sh ksh bash : ${parameter:-word} word is default value 386" sh ksh bash : ${parameter:=word} assign word as default value 387" sh ksh bash : ${parameter:?word} display word if parameter is null 388" sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing 389" ksh bash : ${parameter#pattern} remove small left pattern 390" ksh bash : ${parameter##pattern} remove large left pattern 391" ksh bash : ${parameter%pattern} remove small right pattern 392" ksh bash : ${parameter%%pattern} remove large right pattern 393syn cluster shDerefPatternList contains=shDerefPattern,shDerefString 394syn match shDerefOpError contained ":[[:punct:]]" 395syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList 396syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList 397if exists("b:is_bash") || exists("b:is_kornshell") 398 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList 399 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList 400 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern 401 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern 402 syn match shDerefEscape contained '\%(\\\\\)*\\.' 403endif 404syn region shDerefString contained matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial 405syn region shDerefString contained matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial 406syn match shDerefString contained "\\["']" 407 408if exists("b:is_bash") 409 " bash : ${parameter:offset} 410 " bash : ${parameter:offset:length} 411 syn region shDerefOp contained start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL 412 syn match shDerefPOL contained ":[^}]\+" contains=@shCommandSubList 413 414 " bash : ${parameter//pattern/string} 415 " bash : ${parameter//pattern} 416 syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft 417 syn region shDerefPPSleft contained start='.' skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList 418 syn region shDerefPPSright contained start='.' end='\ze}' contains=@shCommandSubList 419endif 420 421" Useful sh Keywords: {{{1 422" =================== 423syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait 424syn keyword shConditional contained elif else then 425syn keyword shCondError elif else then 426 427" Useful ksh Keywords: {{{1 428" ==================== 429if exists("b:is_kornshell") || exists("b:is_bash") 430 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 431 432" Useful bash Keywords: {{{1 433" ===================== 434 if exists("b:is_bash") 435 syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source 436 else 437 syn keyword shStatement login newgrp 438 endif 439endif 440 441" Synchronization: {{{1 442" ================ 443if !exists("sh_minlines") 444 let sh_minlines = 200 445endif 446if !exists("sh_maxlines") 447 let sh_maxlines = 2 * sh_minlines 448endif 449exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines 450syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>" 451syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>" 452syn sync match shDoSync grouphere shDo "\<do\>" 453syn sync match shDoSync groupthere shDo "\<done\>" 454syn sync match shForSync grouphere shFor "\<for\>" 455syn sync match shForSync groupthere shFor "\<in\>" 456syn sync match shIfSync grouphere shIf "\<if\>" 457syn sync match shIfSync groupthere shIf "\<fi\>" 458syn sync match shUntilSync grouphere shRepeat "\<until\>" 459syn sync match shWhileSync grouphere shRepeat "\<while\>" 460 461" Default Highlighting: {{{1 462" ===================== 463hi def link shArithRegion shShellVariables 464hi def link shBeginHere shRedir 465hi def link shCaseBar shConditional 466hi def link shCaseCommandSub shCommandSub 467hi def link shCaseDoubleQuote shDoubleQuote 468hi def link shCaseIn shConditional 469hi def link shCaseSingleQuote shSingleQuote 470hi def link shCaseDoubleQuote shSingleQuote 471hi def link shCaseStart shConditional 472hi def link shCmdSubRegion shShellVariables 473hi def link shColon shStatement 474hi def link shDerefOp shOperator 475hi def link shDerefPOL shDerefOp 476hi def link shDerefPPS shDerefOp 477hi def link shDeref shShellVariables 478hi def link shDerefSimple shDeref 479hi def link shDerefSpecial shDeref 480hi def link shDerefString shDoubleQuote 481hi def link shDerefVar shDeref 482hi def link shDoubleQuote shString 483hi def link shEcho shString 484hi def link shEmbeddedEcho shString 485hi def link shExSingleQuote shSingleQuote 486hi def link shExDoubleQuote shSingleQuote 487hi def link shFunctionStart Delimiter 488hi def link shHereDoc shString 489hi def link shHerePayload shHereDoc 490hi def link shLoop shStatement 491hi def link shOption shCommandSub 492hi def link shPattern shString 493hi def link shPosnParm shShellVariables 494hi def link shRange shOperator 495hi def link shRedir shOperator 496hi def link shSingleQuote shString 497hi def link shSource shOperator 498hi def link shStringSpecial shSpecial 499hi def link shSubShRegion shOperator 500hi def link shTestOpr shConditional 501hi def link shTestPattern shString 502hi def link shTestDoubleQuote shString 503hi def link shTestSingleQuote shString 504hi def link shVariable shSetList 505hi def link shWrapLineOperator shOperator 506 507if exists("b:is_bash") 508 hi def link bashAdminStatement shStatement 509 hi def link bashSpecialVariables shShellVariables 510 hi def link bashStatement shStatement 511 hi def link shFunctionParen Delimiter 512 hi def link shFunctionDelim Delimiter 513endif 514if exists("b:is_kornshell") 515 hi def link kshSpecialVariables shShellVariables 516 hi def link kshStatement shStatement 517 hi def link shFunctionParen Delimiter 518endif 519 520hi def link shCaseError Error 521hi def link shCondError Error 522hi def link shCurlyError Error 523hi def link shDerefError Error 524hi def link shDerefOpError Error 525hi def link shDerefWordError Error 526hi def link shDoError Error 527hi def link shEsacError Error 528hi def link shIfError Error 529hi def link shInError Error 530hi def link shParenError Error 531hi def link shTestError Error 532if exists("b:is_kornshell") 533 hi def link shDTestError Error 534endif 535 536hi def link shArithmetic Special 537hi def link shCharClass Identifier 538hi def link shSnglCase Statement 539hi def link shCommandSub Special 540hi def link shComment Comment 541hi def link shConditional Conditional 542hi def link shCtrlSeq Special 543hi def link shExprRegion Delimiter 544hi def link shFunctionKey Function 545hi def link shFunctionName Function 546hi def link shNumber Number 547hi def link shOperator Operator 548hi def link shRepeat Repeat 549hi def link shSet Statement 550hi def link shSetList Identifier 551hi def link shShellVariables PreProc 552hi def link shSpecial Special 553hi def link shStatement Statement 554hi def link shString String 555hi def link shTodo Todo 556hi def link shAlias Identifier 557 558" Set Current Syntax: {{{1 559" =================== 560if exists("b:is_bash") 561 let b:current_syntax = "bash" 562elseif exists("b:is_kornshell") 563 let b:current_syntax = "ksh" 564else 565 let b:current_syntax = "sh" 566endif 567 568" vim: ts=16 fdm=marker 569