1" Vim syntax file 2" Language: shell (sh) Korn shell (ksh) bash (sh) 3" Maintainer: Dr. Charles E. Campbell, Jr. <NdrOchipS@PcampbellAfamily.Mbiz> 4" Previous Maintainer: Lennart Schultz <Lennart.Schultz@ecmwf.int> 5" Last Change: Aug 04, 2010 6" Version: 114 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 (eric.brunet@ens.fr) 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,shExDoubleQuote,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,shExDoubleQuote,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,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,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote 85syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,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,shExDoubleQuote,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,shExDoubleQuote,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=shEchoDelim 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=shEchoDelim 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=shEchoDelim 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,shExDoubleQuote,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,shExDoubleQuote,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=shQuote 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=shQuote start=+'+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained 219syn region shCaseDoubleQuote matchgroup=shQuote 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=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial 272 syn region shExDoubleQuote matchgroup=shQuote start=+\$"+ skip=+\\\\\|\\.\|\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,shSpecial 273else 274 syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial 275 syn region shExDoubleQuote matchGroup=Error start=+\$"+ skip=+\\\\\|\\.+ end=+"+ contains=shStringSpecial 276endif 277syn region shSingleQuote matchgroup=shQuote start=+'+ end=+'+ contains=@Spell 278syn region shDoubleQuote matchgroup=shQuote start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell 279syn match shStringSpecial "[^[:print:] \t]" contained 280syn match shStringSpecial "\%(\\\\\)*\\[\\"'`$()#]" 281syn match shSpecial "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial 282syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]" 283syn match shMoreSpecial "\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial contained 284 285" Comments: {{{1 286"========== 287syn cluster shCommentGroup contains=shTodo,@Spell 288syn keyword shTodo contained COMBAK FIXME TODO XXX 289syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup 290syn match shComment "\s\zs#.*$" contains=@shCommentGroup 291syn match shQuickComment contained "#.*$" 292 293" Here Documents: {{{1 294" ========================================= 295if version < 600 296 syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList 297 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 298 syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir end="^EOF$" contains=@shDblQuoteList 299 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir end="^\s*EOF$" contains=@shDblQuoteList 300 syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**" matchgroup=shRedir end="^\.$" contains=@shDblQuoteList 301 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir end="^\s*\.$" contains=@shDblQuoteList 302 303elseif (g:sh_fold_enabled % (s:sh_fold_heredoc * 2))/s:sh_fold_heredoc 304 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList 305 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 306 syn region shHereDoc matchgroup=shRedir fold start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 307 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList 308 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 309 syn region shHereDoc matchgroup=shRedir fold start="<<-\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="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\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="^\s*\z1\s*$" 314 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 315 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 316 syn region shHereDoc matchgroup=shRedir fold start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 317 318else 319 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList 320 syn region shHereDoc matchgroup=shRedir start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 321 syn region shHereDoc matchgroup=shRedir start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList 322 syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 323 syn region shHereDoc matchgroup=shRedir start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 324 syn region shHereDoc matchgroup=shRedir start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 325 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 326 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" 327 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$" 328 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$" 329 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$" 330 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$" 331 syn region shHereDoc matchgroup=shRedir start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" 332endif 333 334" Here Strings: {{{1 335" ============= 336if exists("b:is_bash") 337 syn match shRedir "<<<" 338endif 339 340" Identifiers: {{{1 341"============= 342syn match shSetOption "\s\zs[-+][a-zA-Z0-9]\+\>" contained 343syn match shVariable "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze=" nextgroup=shSetIdentifier 344syn match shSetIdentifier "=" contained nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote 345if exists("b:is_bash") 346 syn region shSetList oneline matchgroup=shSet start="\<\(declare\|typeset\|local\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+#\|=" contains=@shIdList 347 syn region shSetList oneline matchgroup=shSet start="\<set\>\ze[^/]" end="\ze[;|)]\|$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList 348elseif exists("b:is_kornshell") 349 syn region shSetList oneline matchgroup=shSet start="\<\(typeset\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList 350 syn region shSetList oneline matchgroup=shSet start="\<set\>\ze[^/]" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList 351else 352 syn region shSetList oneline matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList 353endif 354 355" Functions: {{{1 356if !exists("g:is_posix") 357 syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo 358endif 359 360if exists("b:is_bash") 361 if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions 362 syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 363 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 364 else 365 syn region shFunctionOne matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList 366 syn region shFunctionTwo matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained 367 endif 368else 369 if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions 370 syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 371 syn region shFunctionTwo fold matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment 372 else 373 syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList 374 syn region shFunctionTwo matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained 375 endif 376endif 377 378" Parameter Dereferencing: {{{1 379" ======================== 380syn match shDerefSimple "\$\%(\h\w*\|\d\)" 381syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray 382syn match shDerefWordError "[^}$[]" contained 383syn match shDerefSimple "\$[-#*@!?]" 384syn match shDerefSimple "\$\$" 385if exists("b:is_bash") || exists("b:is_kornshell") 386 syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList 387 syn region shDeref matchgroup=PreProc start="\${\$\$" end="}" contains=@shDerefList 388endif 389 390" bash: ${!prefix*} and ${#parameter}: {{{1 391" ==================================== 392if exists("b:is_bash") 393 syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOp 394 syn match shDerefVar contained "{\@<=!\w\+" nextgroup=@shDerefVarList 395endif 396 397syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOpError 398syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp 399syn match shDerefVar contained "{\@<=\w\+" nextgroup=@shDerefVarList 400 401" sh ksh bash : ${var[... ]...} array reference: {{{1 402syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError 403 404" Special ${parameter OPERATOR word} handling: {{{1 405" sh ksh bash : ${parameter:-word} word is default value 406" sh ksh bash : ${parameter:=word} assign word as default value 407" sh ksh bash : ${parameter:?word} display word if parameter is null 408" sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing 409" ksh bash : ${parameter#pattern} remove small left pattern 410" ksh bash : ${parameter##pattern} remove large left pattern 411" ksh bash : ${parameter%pattern} remove small right pattern 412" ksh bash : ${parameter%%pattern} remove large right pattern 413syn cluster shDerefPatternList contains=shDerefPattern,shDerefString 414syn match shDerefOpError contained ":[[:punct:]]" 415syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList 416syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList 417if exists("b:is_bash") || exists("b:is_kornshell") 418 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList 419 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList 420 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern 421 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern 422 syn match shDerefEscape contained '\%(\\\\\)*\\.' 423endif 424syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!'+ end=+'+ contains=shStringSpecial 425syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial 426syn match shDerefString contained "\\["']" nextgroup=shDerefPattern 427 428if exists("b:is_bash") 429 " bash : ${parameter:offset} 430 " bash : ${parameter:offset:length} 431 syn region shDerefOp contained start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL 432 syn match shDerefPOL contained ":[^}]\+" contains=@shCommandSubList 433 434 " bash : ${parameter//pattern/string} 435 " bash : ${parameter//pattern} 436 syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft 437 syn region shDerefPPSleft contained start='.' skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList 438 syn region shDerefPPSright contained start='.' end='\ze}' contains=@shCommandSubList 439endif 440 441" Arithmetic Parenthesized Expressions: {{{1 442syn region shParen matchgroup=shArithRegion start='(\ze[^(]' end=')' contains=@shArithParenList 443 444" Useful sh Keywords: {{{1 445" =================== 446syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait 447syn keyword shConditional contained elif else then 448syn keyword shCondError elif else then 449 450" Useful ksh Keywords: {{{1 451" ==================== 452if exists("b:is_kornshell") || exists("b:is_bash") 453 syn keyword shStatement autoload bg false fc fg functions getopts hash history integer jobs let nohup printf r stop suspend times true type unalias whence 454 if exists("g:is_posix") 455 syn keyword shStatement command 456 else 457 syn keyword shStatement time 458 endif 459 460" Useful bash Keywords: {{{1 461" ===================== 462 if exists("b:is_bash") 463 syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source 464 else 465 syn keyword shStatement login newgrp 466 endif 467endif 468 469" Synchronization: {{{1 470" ================ 471if !exists("sh_minlines") 472 let sh_minlines = 200 473endif 474if !exists("sh_maxlines") 475 let sh_maxlines = 2 * sh_minlines 476endif 477exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines 478syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>" 479syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>" 480syn sync match shDoSync grouphere shDo "\<do\>" 481syn sync match shDoSync groupthere shDo "\<done\>" 482syn sync match shForSync grouphere shFor "\<for\>" 483syn sync match shForSync groupthere shFor "\<in\>" 484syn sync match shIfSync grouphere shIf "\<if\>" 485syn sync match shIfSync groupthere shIf "\<fi\>" 486syn sync match shUntilSync grouphere shRepeat "\<until\>" 487syn sync match shWhileSync grouphere shRepeat "\<while\>" 488 489" Default Highlighting: {{{1 490" ===================== 491hi def link shArithRegion shShellVariables 492hi def link shBeginHere shRedir 493hi def link shCaseBar shConditional 494hi def link shCaseCommandSub shCommandSub 495hi def link shCaseDoubleQuote shDoubleQuote 496hi def link shCaseIn shConditional 497hi def link shQuote shOperator 498hi def link shCaseSingleQuote shSingleQuote 499hi def link shCaseStart shConditional 500hi def link shCmdSubRegion shShellVariables 501hi def link shColon shComment 502hi def link shDerefOp shOperator 503hi def link shDerefPOL shDerefOp 504hi def link shDerefPPS shDerefOp 505hi def link shDeref shShellVariables 506hi def link shDerefDelim shOperator 507hi def link shDerefSimple shDeref 508hi def link shDerefSpecial shDeref 509hi def link shDerefString shDoubleQuote 510hi def link shDerefVar shDeref 511hi def link shDoubleQuote shString 512hi def link shEcho shString 513hi def link shEchoDelim shOperator 514hi def link shEchoQuote shString 515hi def link shEmbeddedEcho shString 516hi def link shEscape shCommandSub 517hi def link shExDoubleQuote shDoubleQuote 518hi def link shExSingleQuote shSingleQuote 519hi def link shFunction Function 520hi def link shHereDoc shString 521hi def link shHerePayload shHereDoc 522hi def link shLoop shStatement 523hi def link shMoreSpecial shSpecial 524hi def link shOption shCommandSub 525hi def link shPattern shString 526hi def link shParen shArithmetic 527hi def link shPosnParm shShellVariables 528hi def link shQuickComment shComment 529hi def link shRange shOperator 530hi def link shRedir shOperator 531hi def link shSetListDelim shOperator 532hi def link shSetOption shOption 533hi def link shSingleQuote shString 534hi def link shSource shOperator 535hi def link shStringSpecial shSpecial 536hi def link shSubShRegion shOperator 537hi def link shTestOpr shConditional 538hi def link shTestPattern shString 539hi def link shTestDoubleQuote shString 540hi def link shTestSingleQuote shString 541hi def link shVariable shSetList 542hi def link shWrapLineOperator shOperator 543 544if exists("b:is_bash") 545 hi def link bashAdminStatement shStatement 546 hi def link bashSpecialVariables shShellVariables 547 hi def link bashStatement shStatement 548 hi def link shFunctionParen Delimiter 549 hi def link shFunctionDelim Delimiter 550endif 551if exists("b:is_kornshell") 552 hi def link kshSpecialVariables shShellVariables 553 hi def link kshStatement shStatement 554 hi def link shFunctionParen Delimiter 555endif 556 557hi def link shCaseError Error 558hi def link shCondError Error 559hi def link shCurlyError Error 560hi def link shDerefError Error 561hi def link shDerefOpError Error 562hi def link shDerefWordError Error 563hi def link shDoError Error 564hi def link shEsacError Error 565hi def link shIfError Error 566hi def link shInError Error 567hi def link shParenError Error 568hi def link shTestError Error 569if exists("b:is_kornshell") 570 hi def link shDTestError Error 571endif 572 573hi def link shArithmetic Special 574hi def link shCharClass Identifier 575hi def link shSnglCase Statement 576hi def link shCommandSub Special 577hi def link shComment Comment 578hi def link shConditional Conditional 579hi def link shCtrlSeq Special 580hi def link shExprRegion Delimiter 581hi def link shFunctionKey Function 582hi def link shFunctionName Function 583hi def link shNumber Number 584hi def link shOperator Operator 585hi def link shRepeat Repeat 586hi def link shSet Statement 587hi def link shSetList Identifier 588hi def link shShellVariables PreProc 589hi def link shSpecial Special 590hi def link shStatement Statement 591hi def link shString String 592hi def link shTodo Todo 593hi def link shAlias Identifier 594 595" Set Current Syntax: {{{1 596" =================== 597if exists("b:is_bash") 598 let b:current_syntax = "bash" 599elseif exists("b:is_kornshell") 600 let b:current_syntax = "ksh" 601else 602 let b:current_syntax = "sh" 603endif 604 605" vim: ts=16 fdm=marker 606