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: Sep 15, 2006 6" Version: 88 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 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 85syn cluster shHereBeginList contains=@shCommandSubList 86syn cluster shHereList contains=shBeginHere,shHerePayload 87syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload 88syn cluster shIdList contains=shCommandSub,shWrapLineOperator,shIdWhiteSpace,shDeref,shDerefSimple,shRedir,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq 89syn cluster shLoopList contains=@shCaseList,shTestOpr,shExpr,shDblBrace,shConditional,shCaseEsac,shTest 90syn cluster shSubShList contains=@shCaseList 91syn cluster shTestList contains=shCharClass,shComment,shCommandSub,shDeref,shDerefSimple,shDoubleQuote,shExpr,shExpr,shNumber,shOperator,shExSingleQuote,shSingleQuote,shTestOpr,shTest,shCtrlSeq 92 93 94" Echo: {{{1 95" ==== 96" This one is needed INSIDE a CommandSub, so that `echo bla` be correct 97syn 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 98syn 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 99 100" This must be after the strings, so that bla \" be correct 101syn 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 102 103" Alias: {{{1 104" ===== 105if exists("b:is_kornshell") || exists("b:is_bash") 106 syn match shStatement "\<alias\>" 107 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+\)\@=" skip="\\$" end="\>\|`" 108 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+=\)\@=" skip="\\$" end="=" 109endif 110 111" Error Codes: {{{1 112" ============ 113syn match shDoError "\<done\>" 114syn match shIfError "\<fi\>" 115syn match shInError "\<in\>" 116syn match shCaseError ";;" 117syn match shEsacError "\<esac\>" 118syn match shCurlyError "}" 119syn match shParenError ")" 120if exists("b:is_kornshell") 121 syn match shDTestError "]]" 122endif 123syn match shTestError "]" 124 125" Options Interceptor: {{{1 126" ==================== 127syn match shOption "\s[\-+][a-zA-Z0-9]\+\>"ms=s+1 128syn match shOption "\s--[^ \t$`'"|]\+"ms=s+1 129 130" Operators: {{{1 131" ========== 132syn match shOperator "[!&;|]" 133syn match shOperator "\[[[^:]\|\]]" 134syn match shOperator "!\==" skipwhite nextgroup=shPattern 135syn match shPattern "\<\S\+\())\)\@=" contained contains=shExSingleQuote,shSingleQuote,shDoubleQuote,shDeref 136 137" Subshells: {{{1 138" ========== 139syn region shExpr transparent matchgroup=shExprRegion start="{" end="}" contains=@shExprList2 140syn region shSubSh transparent matchgroup=shSubShRegion start="(" end=")" contains=@shSubShList 141 142" Tests: {{{1 143"======= 144"syn region shExpr transparent matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList 145syn region shExpr matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList 146syn region shTest transparent matchgroup=shStatement start="\<test\>" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1 147syn match shTestOpr contained "<=\|>=\|!=\|==\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]" 148syn match shTestOpr contained '=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern 149syn match shTestPattern contained '\w\+' 150syn match shTestDoubleQuote contained '"[^"]*"' 151syn match shTestSingleQuote contained '\\.' 152syn match shTestSingleQuote contained "'[^']*'" 153if exists("b:is_kornshell") || exists("b:is_bash") 154 syn region shDblBrace matchgroup=Delimiter start="\[\[" skip=+\\\\\|\\$+ end="\]\]" contains=@shTestList 155 syn region shDblParen matchgroup=Delimiter start="((" skip=+\\\\\|\\$+ end="))" contains=@shTestList 156endif 157 158" Character Class In Range: {{{1 159" ========================= 160syn match shCharClass contained "\[:\(backspace\|escape\|return\|xdigit\|alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|tab\):\]" 161 162" Loops: do, if, while, until {{{1 163" ====== 164if g:sh_fold_enabled 165 syn region shDo fold transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList 166 syn region shIf fold transparent matchgroup=shConditional start="\<if\>" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>" contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey 167 syn region shFor fold matchgroup=shLoop start="\<for\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn 168else 169 syn region shDo transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList 170 syn region shIf transparent matchgroup=shConditional start="\<if\>" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>" contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey 171 syn region shFor matchgroup=shLoop start="\<for\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn 172endif 173if exists("b:is_kornshell") || exists("b:is_bash") 174 syn cluster shCaseList add=shRepeat 175 syn region shRepeat matchgroup=shLoop start="\<while\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace 176 syn region shRepeat matchgroup=shLoop start="\<until\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace 177 syn region shCaseEsac matchgroup=shConditional start="\<select\>" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList 178else 179 syn region shRepeat matchgroup=shLoop start="\<while\>" end="\<do\>"me=e-2 contains=@shLoopList 180 syn region shRepeat matchgroup=shLoop start="\<until\>" end="\<do\>"me=e-2 contains=@shLoopList 181endif 182syn region shCurlyIn contained matchgroup=Delimiter start="{" end="}" contains=@shCurlyList 183syn match shComma contained "," 184 185" Case: case...esac {{{1 186" ==== 187syn match shCaseBar contained skipwhite "[^|"`'()]\{-}|"hs=e nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote 188syn match shCaseStart contained skipwhite skipnl "(" nextgroup=shCase,shCaseBar 189syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="[^#$()'"]\{-})"ms=s,hs=e end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment 190if g:sh_fold_enabled 191 syn region shCaseEsac fold matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList 192else 193 syn region shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList 194endif 195syn keyword shCaseIn contained skipwhite skipnl in nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote 196if exists("b:is_bash") 197 syn region shCaseExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial skipwhite skipnl nextgroup=shCaseBar contained 198else 199 syn region shCaseExSingleQuote matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 200endif 201syn region shCaseSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 202syn region shCaseDoubleQuote matchgroup=shOperator start=+"+ skip=+\\\\\|\\.+ end=+"+ contains=@shDblQuoteList,shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 203syn region shCaseCommandSub start=+`+ skip=+\\\\\|\\.+ end=+`+ contains=@shCommandSubList skipwhite skipnl nextgroup=shCaseBar contained 204 205" Misc: {{{1 206"====== 207syn match shWrapLineOperator "\\$" 208syn region shCommandSub start="`" skip="\\\\\|\\." end="`" contains=@shCommandSubList 209 210" $() and $(()): {{{1 211" $(..) is not supported by sh (Bourne shell). However, apparently 212" some systems (HP?) have as their /bin/sh a (link to) Korn shell 213" (ie. Posix compliant shell). /bin/ksh should work for those 214" systems too, however, so the following syntax will flag $(..) as 215" an Error under /bin/sh. By consensus of vimdev'ers! 216if exists("b:is_kornshell") || exists("b:is_bash") 217 syn region shCommandSub matchgroup=shCmdSubRegion start="\$(" skip='\\\\\|\\.' end=")" contains=@shCommandSubList 218 syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shCommandSubList 219 syn match shSkipInitWS contained "^\s\+" 220else 221 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList 222endif 223 224if exists("b:is_bash") 225 syn cluster shCommandSubList add=bashSpecialVariables,bashStatement 226 syn cluster shCaseList add=bashAdminStatement,bashStatement 227 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 228 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 229 syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop 230endif 231 232if exists("b:is_kornshell") 233 syn cluster shCommandSubList add=kshSpecialVariables,kshStatement 234 syn cluster shCaseList add=kshStatement 235 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 236 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 237endif 238 239syn match shSource "^\.\s" 240syn match shSource "\s\.\s" 241syn region shColon start="^\s*:" end="$\|" end="#"me=e-1 contains=@shColonList 242 243" String And Character Constants: {{{1 244"================================ 245syn match shNumber "-\=\<\d\+\>#\=" 246syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained 247if exists("b:is_bash") 248 syn match shSpecial "\\\o\o\o\|\\x\x\x\|\\c.\|\\[abefnrtv]" contained 249endif 250if exists("b:is_bash") 251 syn region shExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial 252else 253 syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial 254endif 255syn region shSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial,@Spell 256syn region shDoubleQuote matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell 257syn match shStringSpecial "[^[:print:]]" contained 258syn match shSpecial "\\[\\\"\'`$()#]" 259 260" Comments: {{{1 261"========== 262syn cluster shCommentGroup contains=shTodo,@Spell 263syn keyword shTodo contained COMBAK FIXME TODO XXX 264syn match shComment "^#.*$" contains=@shCommentGroup 265syn match shComment "[^0-9]#.*$" contains=@shCommentGroup 266 267" File Redirection Highlighted As Operators: {{{1 268"=========================================== 269syn match shRedir "\d\=>\(&[-0-9]\)\=" 270syn match shRedir "\d\=>>-\=" 271syn match shRedir "\d\=<\(&[-0-9]\)\=" 272syn match shRedir "\d<<-\=" 273 274" Here Documents: {{{1 275" ========================================= 276if version < 600 277 syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList 278 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 279 syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir end="^EOF$" contains=@shDblQuoteList 280 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir end="^\s*EOF$" contains=@shDblQuoteList 281 syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**" matchgroup=shRedir end="^\.$" contains=@shDblQuoteList 282 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir end="^\s*\.$" contains=@shDblQuoteList 283 284elseif g:sh_fold_enabled 285 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList 286 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 287 syn region shHereDoc matchgroup=shRedir fold start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 288 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList 289 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 290 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 291 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 292 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 293 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 294 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" 295 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 296 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 297 syn region shHereDoc matchgroup=shRedir fold start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 298 299else 300 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList 301 syn region shHereDoc matchgroup=shRedir start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 302 syn region shHereDoc matchgroup=shRedir start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList 303 syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 304 syn region shHereDoc matchgroup=shRedir start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 305 syn region shHereDoc matchgroup=shRedir start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 306 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 307 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" 308 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 309 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 310 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 311 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 312 syn region shHereDoc matchgroup=shRedir start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 313endif 314 315" Here Strings: {{{1 316" ============= 317if exists("b:is_bash") 318 syn match shRedir "<<<" 319endif 320 321" Identifiers: {{{1 322"============= 323syn match shVariable "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze=" nextgroup=shSetIdentifier 324syn match shIdWhiteSpace contained "\s" 325syn match shSetIdentifier contained "=" nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shSingleQuote,shExSingleQuote 326if exists("b:is_bash") 327 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 328 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 329 syn match shSet "\<\(declare\|typeset\|local\|export\|set\|unset\)\>" 330elseif exists("b:is_kornshell") 331 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 332 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 333 syn match shSet "\<\(typeset\|set\|export\|unset\)\>" 334else 335 syn region shSetList matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[^/]" end="$\|\ze[|)]" matchgroup=shOperator end="\ze[|);&]" matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList 336 syn match shStatement "\<\(set\|export\|unset\)\>" 337endif 338 339" Functions: {{{1 340syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo 341syn match shFunctionStart "^\s*{" contained 342if g:sh_fold_enabled 343 syn region shFunctionOne transparent fold start="^\s*\h\w*\s*()\_s*\ze{" matchgroup=shFunctionStart end="}" contains=@shFunctionList 344 syn region shFunctionTwo transparent fold start="\h\w*\s*\%(()\)\=\_s*\ze{" matchgroup=shFunctionStart end="}" contains=shFunctionKey,@shFunctionList contained 345else 346 syn region shFunctionOne transparent start="^\s*\h\w*\s*()\_s*\ze{" matchgroup=shFunctionStart end="}" contains=@shFunctionList 347 syn region shFunctionTwo transparent start="\h\w*\s*\%(()\)\=\_s*\ze{" matchgroup=shFunctionStart end="}" contains=shFunctionKey,@shFunctionList contained 348endif 349 350" Parameter Dereferencing: {{{1 351" ======================== 352syn match shDerefSimple "\$\%(\h\w*\|\d\)" 353syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray 354syn match shDerefWordError "[^}$[]" contained 355syn match shDerefSimple "\$[-#*@!?]" 356syn match shDerefSimple "\$\$" 357if exists("b:is_bash") || exists("b:is_kornshell") 358 syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList 359endif 360 361" bash: ${!prefix*} and ${#parameter}: {{{1 362" ==================================== 363if exists("b:is_bash") 364 syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOp 365 syn match shDerefVar contained "{\@<=!\w\+" nextgroup=@shDerefVarList 366endif 367 368syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOpError 369syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp 370syn match shDerefVar contained "{\@<=\w\+" nextgroup=@shDerefVarList 371 372" sh ksh bash : ${var[... ]...} array reference: {{{1 373syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError 374 375" Special ${parameter OPERATOR word} handling: {{{1 376" sh ksh bash : ${parameter:-word} word is default value 377" sh ksh bash : ${parameter:=word} assign word as default value 378" sh ksh bash : ${parameter:?word} display word if parameter is null 379" sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing 380" ksh bash : ${parameter#pattern} remove small left pattern 381" ksh bash : ${parameter##pattern} remove large left pattern 382" ksh bash : ${parameter%pattern} remove small right pattern 383" ksh bash : ${parameter%%pattern} remove large right pattern 384syn cluster shDerefPatternList contains=shDerefPattern,shDerefString 385syn match shDerefOpError contained ":[[:punct:]]" 386syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList 387syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList 388if exists("b:is_bash") || exists("b:is_kornshell") 389 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList 390 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList 391 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern 392 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern 393 syn match shDerefEscape contained '\%(\\\\\)*\\.' 394endif 395syn region shDerefString contained matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial 396syn region shDerefString contained matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial 397syn match shDerefString contained "\\["']" 398 399if exists("b:is_bash") 400 " bash : ${parameter:offset} 401 " bash : ${parameter:offset:length} 402 syn region shDerefOp contained start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL 403 syn match shDerefPOL contained ":[^}]\+" contains=@shCommandSubList 404 405 " bash : ${parameter//pattern/string} 406 " bash : ${parameter//pattern} 407 syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft 408 syn region shDerefPPSleft contained start='.' skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList 409 syn region shDerefPPSright contained start='.' end='\ze}' contains=@shCommandSubList 410endif 411 412" Useful sh Keywords: {{{1 413" =================== 414syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait 415syn keyword shConditional contained elif else then 416syn keyword shCondError elif else then 417 418" Useful ksh Keywords: {{{1 419" ==================== 420if exists("b:is_kornshell") || exists("b:is_bash") 421 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 422 423" Useful bash Keywords: {{{1 424" ===================== 425 if exists("b:is_bash") 426 syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source 427 else 428 syn keyword shStatement login newgrp 429 endif 430endif 431 432" Synchronization: {{{1 433" ================ 434if !exists("sh_minlines") 435 let sh_minlines = 200 436endif 437if !exists("sh_maxlines") 438 let sh_maxlines = 2 * sh_minlines 439endif 440exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines 441syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>" 442syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>" 443syn sync match shDoSync grouphere shDo "\<do\>" 444syn sync match shDoSync groupthere shDo "\<done\>" 445syn sync match shForSync grouphere shFor "\<for\>" 446syn sync match shForSync groupthere shFor "\<in\>" 447syn sync match shIfSync grouphere shIf "\<if\>" 448syn sync match shIfSync groupthere shIf "\<fi\>" 449syn sync match shUntilSync grouphere shRepeat "\<until\>" 450syn sync match shWhileSync grouphere shRepeat "\<while\>" 451 452" Default Highlighting: {{{1 453" ===================== 454hi def link shArithRegion shShellVariables 455hi def link shBeginHere shRedir 456hi def link shCaseBar shConditional 457hi def link shCaseCommandSub shCommandSub 458hi def link shCaseDoubleQuote shDoubleQuote 459hi def link shCaseIn shConditional 460hi def link shCaseSingleQuote shSingleQuote 461hi def link shCaseStart shConditional 462hi def link shCmdSubRegion shShellVariables 463hi def link shColon shStatement 464hi def link shDerefOp shOperator 465hi def link shDerefPOL shDerefOp 466hi def link shDerefPPS shDerefOp 467hi def link shDeref shShellVariables 468hi def link shDerefSimple shDeref 469hi def link shDerefSpecial shDeref 470hi def link shDerefString shDoubleQuote 471hi def link shDerefVar shDeref 472hi def link shDoubleQuote shString 473hi def link shEcho shString 474hi def link shEmbeddedEcho shString 475hi def link shExSingleQuote shSingleQuote 476hi def link shFunctionStart Delimiter 477hi def link shHereDoc shString 478hi def link shHerePayload shHereDoc 479hi def link shLoop shStatement 480hi def link shOption shCommandSub 481hi def link shPattern shString 482hi def link shPosnParm shShellVariables 483hi def link shRange shOperator 484hi def link shRedir shOperator 485hi def link shSingleQuote shString 486hi def link shSource shOperator 487hi def link shStringSpecial shSpecial 488hi def link shSubShRegion shOperator 489hi def link shTestOpr shConditional 490hi def link shTestPattern shString 491hi def link shTestDoubleQuote shString 492hi def link shTestSingleQuote shString 493hi def link shVariable shSetList 494hi def link shWrapLineOperator shOperator 495 496if exists("b:is_bash") 497 hi def link bashAdminStatement shStatement 498 hi def link bashSpecialVariables shShellVariables 499 hi def link bashStatement shStatement 500 hi def link shFunctionParen Delimiter 501 hi def link shFunctionDelim Delimiter 502endif 503if exists("b:is_kornshell") 504 hi def link kshSpecialVariables shShellVariables 505 hi def link kshStatement shStatement 506 hi def link shFunctionParen Delimiter 507endif 508 509hi def link shCaseError Error 510hi def link shCondError Error 511hi def link shCurlyError Error 512hi def link shDerefError Error 513hi def link shDerefOpError Error 514hi def link shDerefWordError Error 515hi def link shDoError Error 516hi def link shEsacError Error 517hi def link shIfError Error 518hi def link shInError Error 519hi def link shParenError Error 520hi def link shTestError Error 521if exists("b:is_kornshell") 522 hi def link shDTestError Error 523endif 524 525hi def link shArithmetic Special 526hi def link shCharClass Identifier 527hi def link shSnglCase Statement 528hi def link shCommandSub Special 529hi def link shComment Comment 530hi def link shConditional Conditional 531hi def link shCtrlSeq Special 532hi def link shExprRegion Delimiter 533hi def link shFunctionKey Function 534hi def link shFunctionName Function 535hi def link shNumber Number 536hi def link shOperator Operator 537hi def link shRepeat Repeat 538hi def link shSet Statement 539hi def link shSetList Identifier 540hi def link shShellVariables PreProc 541hi def link shSpecial Special 542hi def link shStatement Statement 543hi def link shString String 544hi def link shTodo Todo 545hi def link shAlias Identifier 546 547" Set Current Syntax: {{{1 548" =================== 549if exists("b:is_bash") 550 let b:current_syntax = "bash" 551elseif exists("b:is_kornshell") 552 let b:current_syntax = "ksh" 553else 554 let b:current_syntax = "sh" 555endif 556 557" vim: ts=16 fdm=marker 558