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