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