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