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: Feb 16, 2005 6" Version: 72 7" URL: http://www.erols.com/astronaut/vim/index.html#vimlinks_syntax 8" 9" Using the following VIM variables: {{{1 10" b:is_kornshell if defined, enhance with kornshell syntax 11" b:is_bash if defined, enhance with bash syntax 12" is_kornshell if neither b:is_kornshell or b:is_bash is 13" defined, then if is_kornshell is set 14" b:is_kornshell is default 15" is_bash if none of the previous three variables are 16" defined, then if is_bash is set b:is_bash is default 17" g:sh_fold_enabled if non-zero, syntax folding is enabled 18" sh_minlines sets up syn sync minlines (default: 200) 19" sh_maxlines sets up syn sync maxlines (default: twice 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("is_kornshell") 40 let b:is_kornshell= 1 41 if exists("b:is_sh") 42 unlet b:is_sh 43 endif 44 elseif exists("is_bash") 45 let b:is_bash= 1 46 if exists("b:is_sh") 47 unlet b:is_sh 48 endif 49 else 50 let b:is_sh= 1 51 endif 52endif 53 54if !exists("g:sh_fold_enabled") 55 let g:sh_fold_enabled= 0 56elseif g:sh_fold_enabled != 0 && !has("folding") 57 let g:sh_fold_enabled= 0 58 echomsg "Ignoring g:sh_fold_enabled=".g:sh_fold_enabled."; re-compile vim for +fold support" 59endif 60 61" sh syntax is case sensitive 62syn case match 63 64" Clusters: contains=@... clusters {{{1 65"================================== 66syn cluster shCaseEsacList contains=shCaseStart,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shSpecial 67syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,bkshFunction,shSpecial 68syn cluster shColonList contains=@shCaseList 69syn cluster shCommandSubList contains=shArithmetic,shDeref,shDerefSimple,shNumber,shOperator,shPosnParm,shSpecial,shExSingleQuote,shSingleQuote,shDoubleQuote,shStatement,shVariable,shSubSh,shAlias,shTest 70syn cluster shDblQuoteList contains=shCommandSub,shDeref,shDerefSimple,shSpecial,shPosnParm 71syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError 72syn cluster shDerefVarList contains=shDerefOp,shDerefVarArray,shDerefOpError 73syn cluster shEchoList contains=shArithmetic,shCommandSub,shDeref,shDerefSimple,shExpr,shExSingleQuote,shSingleQuote,shDoubleQuote,shSpecial 74syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shSingleQuote,shDoubleQuote,shSpecial,shExpr,shDblBrace,shDeref,shDerefSimple 75syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest 76syn cluster shFunctionList contains=@shCaseList,shOperator 77syn cluster shHereBeginList contains=@shCommandSubList 78syn cluster shHereList contains=shBeginHere,shHerePayload 79syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload 80syn cluster shIdList contains=shCommandSub,shWrapLineOperator,shIdWhiteSpace,shDeref,shDerefSimple,shSpecial,shRedir,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr 81syn cluster shLoopList contains=@shCaseList,shTestOpr,shExpr,shDblBrace,shConditional,shCaseEsac,shTest 82syn cluster shSubShList contains=@shCaseList 83syn cluster shTestList contains=shCharClass,shComment,shCommandSub,shDeref,shDerefSimple,shDoubleQuote,shExpr,shExpr,shNumber,shOperator,shExSingleQuote,shSingleQuote,shSpecial,shTestOpr,shTest 84 85 86" Echo: {{{1 87" ==== 88" This one is needed INSIDE a CommandSub, so that `echo bla` be correct 89syn 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 90syn 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 91 92" This must be after the strings, so that bla \" be correct 93syn 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,shSpecial,shOperator,shDoubleQuote,shCharClass 94 95" Alias: {{{1 96" ===== 97if exists("b:is_kornshell") || exists("b:is_bash") 98 syn match shStatement "\<alias\>" 99 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+\)\@=" skip="\\$" end="\>\|`" 100 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+=\)\@=" skip="\\$" end="=" 101endif 102 103" Error Codes: {{{1 104" ============ 105syn match shDoError "\<done\>" 106syn match shIfError "\<fi\>" 107syn match shInError "\<in\>" 108syn match shCaseError ";;" 109syn match shEsacError "\<esac\>" 110syn match shCurlyError "}" 111syn match shParenError ")" 112if exists("b:is_kornshell") 113 syn match shDTestError "]]" 114endif 115syn match shTestError "]" 116 117" Options Interceptor: {{{1 118" ==================== 119syn match shOption "\s[\-+][a-zA-Z0-9]\+\>"ms=s+1 120syn match shOption "\s--\S\+"ms=s+1 121 122" Operators: {{{1 123" ========== 124syn match shOperator "[!&;|]" 125syn match shOperator "\[[[^:]\|\]]" 126syn match shOperator "!\==" skipwhite nextgroup=shPattern 127syn match shPattern "\<\S\+\())\)\@=" contained contains=shExSingleQuote,shSingleQuote,shDoubleQuote,shDeref 128 129" Subshells: {{{1 130" ========== 131syn region shExpr transparent matchgroup=shExprRegion start="{" end="}" contains=@shExprList2 132syn region shSubSh transparent matchgroup=shSubShRegion start="(" end=")" contains=@shSubShList 133 134" Tests: {{{1 135"======= 136"syn region shExpr transparent matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList 137syn region shExpr matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList 138syn region shTest transparent matchgroup=shStatement start="\<test\>" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1 139syn match shTestOpr contained "<=\|>=\|!=\|==\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!=<>]" 140if exists("b:is_kornshell") || exists("b:is_bash") 141 syn region shDblBrace matchgroup=Delimiter start="\[\[" skip=+\\\\\|\\$+ end="\]\]" contains=@shTestList 142 syn region shDblParen matchgroup=Delimiter start="((" skip=+\\\\\|\\$+ end="))" contains=@shTestList 143endif 144 145" Character Class In Range: {{{1 146" ========================= 147syn match shCharClass contained "\[:\(backspace\|escape\|return\|xdigit\|alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|tab\):\]" 148 149" Loops: do, if, while, until {{{1 150" ====== 151syn region shDo transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList 152syn region shIf transparent matchgroup=shConditional start="\<if\>" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>" contains=@shLoopList,shDblBrace,shDblParen 153syn region shFor matchgroup=shLoop start="\<for\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen 154if exists("b:is_kornshell") || exists("b:is_bash") 155 syn cluster shCaseList add=shRepeat 156 syn region shRepeat matchgroup=shLoop start="\<while\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace 157 syn region shRepeat matchgroup=shLoop start="\<until\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace 158 syn region shCaseEsac matchgroup=shConditional start="\<select\>" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList 159else 160 syn region shRepeat matchgroup=shLoop start="\<while\>" end="\<do\>"me=e-2 contains=@shLoopList 161 syn region shRepeat matchgroup=shLoop start="\<until\>" end="\<do\>"me=e-2 contains=@shLoopList 162endif 163 164" Case: case...esac {{{1 165" ==== 166syn match shCaseBar contained skipwhite "[^|"`'()]\{-}|"hs=e nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote 167syn match shCaseStart contained skipwhite skipnl "(" nextgroup=shCase,shCaseBar 168syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="[^$()]\{-})"ms=s,hs=e end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,,shComment 169syn region shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList 170syn keyword shCaseIn contained skipwhite skipnl in nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote 171if exists("b:is_bash") 172 syn region shCaseExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial skipwhite skipnl nextgroup=shCaseBar contained 173else 174 syn region shCaseExSingleQuote matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 175endif 176syn region shCaseSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 177syn region shCaseDoubleQuote matchgroup=shOperator start=+"+ skip=+\\\\\|\\.+ end=+"+ contains=@shDblQuoteList,shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 178syn region shCaseCommandSub start=+`+ skip=+\\\\\|\\.+ end=+`+ contains=@shCommandSubList skipwhite skipnl nextgroup=shCaseBar contained 179 180" Misc: {{{1 181"====== 182syn match shWrapLineOperator "\\$" 183syn region shCommandSub start="`" skip="\\\\\|\\." end="`" contains=@shCommandSubList 184 185" $() and $(()): {{{1 186" $(..) is not supported by sh (Bourne shell). However, apparently 187" some systems (HP?) have as their /bin/sh a (link to) Korn shell 188" (ie. Posix compliant shell). /bin/ksh should work for those 189" systems too, however, so the following syntax will flag $(..) as 190" an Error under /bin/sh. By consensus of vimdev'ers! 191if exists("b:is_kornshell") || exists("b:is_bash") 192 syn region shCommandSub matchgroup=shCmdSubRegion start="\$(" skip='\\\\\|\\.' end=")" contains=@shCommandSubList 193 syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shCommandSubList 194 syn match shSkipInitWS contained "^\s\+" 195else 196 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList 197endif 198 199if exists("b:is_bash") 200 syn cluster shCommandSubList add=bashSpecialVariables,bashStatement 201 syn cluster shCaseList add=bashAdminStatement,bashStatement 202 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 203 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 204 syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop 205endif 206 207if exists("b:is_kornshell") 208 syn cluster shCommandSubList add=kshSpecialVariables,kshStatement 209 syn cluster shCaseList add=kshStatement 210 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 211 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 212endif 213 214syn match shSource "^\.\s" 215syn match shSource "\s\.\s" 216syn region shColon start="^\s*:" end="$\|" end="#"me=e-1 contains=@shColonList 217 218" String And Character Constants: {{{1 219"================================ 220syn match shNumber "-\=\<\d\+\>" 221if exists("b:is_bash") 222 syn match shSpecial "\\\o\o\o\|\\x\x\x\|\\c.\|\\[abefnrtv]" contained 223else 224 syn match shSpecial "\\\d\d\d\|\\[abcfnrtv0]" contained 225endif 226if exists("b:is_bash") 227 syn region shExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial 228else 229 syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial 230endif 231syn region shSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial 232syn region shDoubleQuote matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial 233syn match shStringSpecial "[^[:print:]]" contained 234syn match shSpecial "\\[\\\"\'`$()#]" 235 236" Comments: {{{1 237"========== 238syn cluster shCommentGroup contains=shTodo,@Spell 239syn keyword shTodo contained TODO 240syn match shComment "#.*$" contains=@shCommentGroup 241 242" File Redirection Highlighted As Operators: {{{1 243"=========================================== 244syn match shRedir "\d\=>\(&[-0-9]\)\=" 245syn match shRedir "\d\=>>-\=" 246syn match shRedir "\d\=<\(&[-0-9]\)\=" 247syn match shRedir "\d<<-\=" 248 249" Here Documents: {{{1 250" ========================================= 251if version < 600 252 syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList 253 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 254 syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir end="^EOF$" contains=@shDblQuoteList 255 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir end="^\s*EOF$" contains=@shDblQuoteList 256 syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**" matchgroup=shRedir end="^\.$" contains=@shDblQuoteList 257 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir end="^\s*\.$" contains=@shDblQuoteList 258 259elseif g:sh_fold_enabled 260 261 if v:version > 602 || (v:version == 602 && has("patch219")) 262 syn region shHereDoc fold start="\(<<\s*\\\=\z(\S*\)\)\@=" matchgroup=shRedir end="^\z1$" contains=@shHereListDQ keepend 263 syn region shHereDoc fold start="\(<<\s*\"\z(\S*\)\"\)\@=" matchgroup=shRedir end="^\z1$"" contains=@shHereList keepend 264 syn region shHereDoc fold start="\(<<\s*'\z(\S*\)'\)\@=" matchgroup=shRedir end="^\z1$"" contains=@shHereList keepend 265 syn region shHereDoc fold start="\(<<\s*\\\_$\_s*\z(\S*\)\)\@=" matchgroup=shRedir end="^\z1$"" contains=@shHereList keepend 266 syn region shHereDoc fold start="\(<<\s*\\\_$\_s*\"\z(\S*\)\"\)\@=" matchgroup=shRedir end="^\z1$"" contains=@shHereList keepend 267 syn region shHereDoc fold start="\(<<\s*\\\_$\_s*'\z(\S*\)'\)\@=" matchgroup=shRedir end="^\z1$" contains=@shHereList keepend 268 syn region shHereDoc fold start="\(<<-\s*\z(\S*\)\)\@=" matchgroup=shRedir end="^\s*\z1$" contains=@shHereList keepend 269 syn region shHereDoc fold start="\(<<-\s*\"\z(\S*\)\"\)\@=" matchgroup=shRedir end="^\s*\z1$"" contains=@shHereListDQ keepend 270 syn region shHereDoc fold start="\(<<-\s*'\z(\S*\)'\)\@=" matchgroup=shRedir end="^\s*\z1$"" contains=@shHereList keepend 271 syn region shHereDoc fold start="\(<<-\s*\\\_$\_s*'\z(\S*\)'\)\@=" matchgroup=shRedir end="^\s*\z1$" contains=@shHereList keepend 272 syn region shHereDoc fold start="\(<<-\s*\\\_$\_s*\z(\S*\)\)\@=" matchgroup=shRedir end="^\s*\z1$" contains=@shHereList keepend 273 syn region shHereDoc fold start="\(<<-\s*\\\_$\_s*\"\z(\S*\)\"\)\@=" matchgroup=shRedir end="^\s*\z1$" contains=@shHereList keepend 274 else 275 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)" matchgroup=shRedir end="^\z1$" contains=@shDblQuoteList 276 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1$" 277 syn region shHereDoc matchgroup=shRedir fold start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1$" 278 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1$" contains=@shDblQuoteList 279 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1$" 280 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1$" 281 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1$" 282 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1$" 283 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1$" 284 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1$" 285 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1$" 286 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1$" 287 endif 288else 289 if v:version > 602 || (v:version == 602 && has("patch219")) 290 syn region shHereDoc start="\(<<\s*\\\=\z(\S*\)\)\@=" matchgroup=shRedir end="^\z1$" contains=@shHereList keepend 291 syn region shHereDoc start="\(<<\s*\"\z(\S*\)\"\)\@=" matchgroup=shRedir end="^\z1$"" contains=@shHereListDQ keepend 292 syn region shHereDoc start="\(<<\s*'\z(\S*\)'\)\@=" matchgroup=shRedir end="^\z1$"" contains=@shHereList keepend 293 syn region shHereDoc start="\(<<\s*\\\_$\_s*\z(\S*\)\)\@=" matchgroup=shRedir end="^\z1$"" contains=@shHereList keepend 294 syn region shHereDoc start="\(<<\s*\\\_$\_s*\"\z(\S*\)\"\)\@=" matchgroup=shRedir end="^\z1$"" contains=@shHereList keepend 295 syn region shHereDoc start="\(<<\s*\\\_$\_s*'\z(\S*\)'\)\@=" matchgroup=shRedir end="^\z1$" contains=@shHereList keepend 296 syn region shHereDoc start="\(<<-\s*\z(\S*\)\)\@=" matchgroup=shRedir end="^\s*\z1$" contains=@shHereList keepend 297 syn region shHereDoc start="\(<<-\s*\"\z(\S*\)\"\)\@=" matchgroup=shRedir end="^\s*\z1$"" contains=@shHereListDQ keepend 298 syn region shHereDoc start="\(<<-\s*'\z(\S*\)'\)\@=" matchgroup=shRedir end="^\s*\z1$"" contains=@shHereList keepend 299 syn region shHereDoc start="\(<<-\s*\\\_$\_s*'\z(\S*\)'\)\@=" matchgroup=shRedir end="^\s*\z1$" contains=@shHereList keepend 300 syn region shHereDoc start="\(<<-\s*\\\_$\_s*\z(\S*\)\)\@=" matchgroup=shRedir end="^\s*\z1$" contains=@shHereList keepend 301 syn region shHereDoc start="\(<<-\s*\\\_$\_s*\"\z(\S*\)\"\)\@=" matchgroup=shRedir end="^\s*\z1$" contains=@shHereList keepend 302 syn match shHerePayload "^.*$" contained skipnl nextgroup=shHerePayload contains=@shDblQuoteList 303 syn match shBeginLine ".*$" contained skipnl nextgroup=shHerePayload contains=@shCommandSubList 304 syn match shBeginHere "<<-\=\s*\S\+" contained nextgroup=shBeginLine 305 else 306 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)" matchgroup=shRedir end="^\z1$" contains=@shDblQuoteList 307 syn region shHereDoc matchgroup=shRedir start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1$" 308 syn region shHereDoc matchgroup=shRedir start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1$" contains=@shDblQuoteList 309 syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1$" 310 syn region shHereDoc matchgroup=shRedir start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1$" 311 syn region shHereDoc matchgroup=shRedir start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1$" 312 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1$" 313 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1$" 314 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1$" 315 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1$" 316 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1$" 317 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1$" 318 endif 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="[;&]"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="[;&]"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="[;&]"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="[;&]"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="[;&]" matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList 342 syn match shStatement "\<\(set\|export\|unset\)$" 343endif 344 345" Functions: {{{1 346" handles functions which start: Function () { 347" Apparently Bourne shell accepts functions too, 348" even though it isn't documented by my man pages 349" for it. 350syn cluster shCommandSubList add=bkshFunction 351if g:sh_fold_enabled 352 syn region bkshFunctionBody transparent fold matchgroup=Delimiter start="^\s*\<\h\w*\>\s*()\s*{" end="}" contains=bkshFunction,bkshFunctionDelim,@shFunctionList 353else 354 syn region bkshFunctionBody transparent matchgroup=Delimiter start="^\s*\<\h\w*\>\s*()\s*{" end="}" contains=bkshFunction,bkshFunctionDelim,@shFunctionList 355endif 356syn match bkshFunction "^\s*\<\h\w*\>\s*()" skipwhite skipnl contains=bkshFunctionParen 357syn match bkshFunctionParen "[()]" contained 358syn match bkshFunctionDelim "[{}]" contained 359 360" Parameter Dereferencing: {{{1 361" ======================== 362syn match shDerefSimple "\$\%(\h\w*\|\d\)" 363syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray 364syn match shDerefWordError "[^}$[]" contained 365syn match shDerefSimple "\$[-#*@!?]" 366syn match shDerefSimple "\$\$" 367if exists("b:is_bash") || exists("b:is_kornshell") 368 syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList 369endif 370 371" bash: ${!prefix*} and ${#parameter}: {{{1 372" ==================================== 373if exists("b:is_bash") 374 syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOp 375 syn match shDerefVar contained "{\@<=!\w\+" nextgroup=@shDerefVarList 376endif 377 378syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOpError 379syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp 380syn match shDerefVar contained "{\@<=\w\+" nextgroup=@shDerefVarList 381 382" sh ksh bash : ${var[... ]...} array reference: {{{1 383syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError 384 385" Special ${parameter OPERATOR word} handling: {{{1 386" sh ksh bash : ${parameter:-word} word is default value 387" sh ksh bash : ${parameter:=word} assign word as default value 388" sh ksh bash : ${parameter:?word} display word if parameter is null 389" sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing 390" ksh bash : ${parameter#pattern} remove small left pattern 391" ksh bash : ${parameter##pattern} remove large left pattern 392" ksh bash : ${parameter%pattern} remove small right pattern 393" ksh bash : ${parameter%%pattern} remove large right pattern 394syn cluster shDerefPatternList contains=shDerefPattern,shDerefString 395syn match shDerefOpError contained ":[[:punct:]]" 396syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList 397syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList 398if exists("b:is_bash") || exists("b:is_kornshell") 399 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList 400 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList 401 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub nextgroup=shDerefPattern 402 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern 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 408" bash : ${parameter:offset} 409" bash : ${parameter:offset:length} 410" bash : ${parameter//pattern/string} 411" bash : ${parameter//pattern} 412if exists("b:is_bash") 413 syn region shDerefOp contained start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL 414 syn match shDerefPOL contained ":[^}]\{1,}" contains=@shCommandSubList 415 syn match shDerefOp contained "/\{1,2}" nextgroup=shDerefPat 416 syn match shDerefPat contained "[^/}]\{1,}" nextgroup=shDerefPatStringOp 417 syn match shDerefPatStringOp contained "/" nextgroup=shDerefPatString 418 syn match shDerefPatString contained "[^}]\{1,}" 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 shFunction function 431 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 432 433" Useful bash Keywords: {{{1 434" ===================== 435 if exists("b:is_bash") 436 syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source 437 else 438 syn keyword shStatement login newgrp 439 endif 440endif 441 442" Synchronization: {{{1 443" ================ 444if !exists("sh_minlines") 445 let sh_minlines = 200 446endif 447if !exists("sh_maxlines") 448 let sh_maxlines = 2 * sh_minlines 449endif 450exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines 451syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>" 452syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>" 453syn sync match shDoSync grouphere shDo "\<do\>" 454syn sync match shDoSync groupthere shDo "\<done\>" 455syn sync match shForSync grouphere shFor "\<for\>" 456syn sync match shForSync groupthere shFor "\<in\>" 457syn sync match shIfSync grouphere shIf "\<if\>" 458syn sync match shIfSync groupthere shIf "\<fi\>" 459syn sync match shUntilSync grouphere shRepeat "\<until\>" 460syn sync match shWhileSync grouphere shRepeat "\<while\>" 461 462" Default Highlighting: {{{1 463" ===================== 464hi def link shArithRegion shShellVariables 465hi def link shBeginHere shRedir 466hi def link shCaseBar shConditional 467hi def link shCaseCommandSub shCommandSub 468hi def link shCaseDoubleQuote shDoubleQuote 469hi def link shCaseIn shConditional 470hi def link shCaseSingleQuote shSingleQuote 471hi def link shCaseStart shConditional 472hi def link shCmdSubRegion shShellVariables 473hi def link shColon shStatement 474hi def link shDerefOp shOperator 475hi def link shDerefPatStringOp shDerefOp 476hi def link shDerefPatString shDerefPattern 477hi def link shDerefPOL shDerefOp 478hi def link shDeref shShellVariables 479hi def link shDerefSimple shDeref 480hi def link shDerefSpecial shDeref 481hi def link shDerefString shDoubleQuote 482hi def link shDerefVar shDeref 483hi def link shDoubleQuote shString 484hi def link shEcho shString 485hi def link shEmbeddedEcho shString 486hi def link shExSingleQuote shSingleQuote 487hi def link shHereDoc shString 488hi def link shHerePayload shHereDoc 489hi def link shLoop shStatement 490hi def link shOption shCommandSub 491hi def link shPattern shString 492hi def link shPosnParm shShellVariables 493hi def link shRange shOperator 494hi def link shRedir shOperator 495hi def link shSingleQuote shString 496hi def link shSource shOperator 497hi def link shStringSpecial shSpecial 498hi def link shSubShRegion shOperator 499hi def link shTestOpr shConditional 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 bkshFunction Function 508 hi def link bkshFunctionParen Delimiter 509 hi def link bkshFunctionDelim Delimiter 510endif 511if exists("b:is_kornshell") 512 hi def link kshSpecialVariables shShellVariables 513 hi def link kshStatement shStatement 514 hi def link bkshFunction Function 515 hi def link bkshFunctionParen Delimiter 516endif 517 518hi def link shCaseError Error 519hi def link shCondError Error 520hi def link shCurlyError Error 521hi def link shDerefError Error 522hi def link shDerefOpError Error 523hi def link shDerefWordError Error 524hi def link shDoError Error 525hi def link shEsacError Error 526hi def link shIfError Error 527hi def link shInError Error 528hi def link shParenError Error 529hi def link shTestError Error 530if exists("b:is_kornshell") 531 hi def link shDTestError Error 532endif 533 534hi def link shArithmetic Special 535hi def link shCharClass Identifier 536hi def link shSnglCase Statement 537hi def link shCommandSub Special 538hi def link shComment Comment 539hi def link shConditional Conditional 540hi def link shExprRegion Delimiter 541hi def link shFunction Function 542hi def link shFunctionName Function 543hi def link shNumber Number 544hi def link shOperator Operator 545hi def link shRepeat Repeat 546hi def link shSet Statement 547hi def link shSetList Identifier 548hi def link shShellVariables PreProc 549hi def link shSpecial Special 550hi def link shStatement Statement 551hi def link shString String 552hi def link shTodo Todo 553hi def link shAlias Identifier 554 555" Set Current Syntax: {{{1 556" =================== 557if exists("b:is_bash") 558 let b:current_syntax = "bash" 559elseif exists("b:is_kornshell") 560 let b:current_syntax = "ksh" 561else 562 let b:current_syntax = "sh" 563endif 564 565" vim: ts=16 fdm=marker 566