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