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: Feb 11, 2011 6" Version: 115 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,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 413" ksh bash : ${parameter^pattern} Case modification 414" ksh bash : ${parameter^^pattern} Case modification 415" ksh bash : ${parameter,pattern} Case modification 416" ksh bash : ${parameter,,pattern} Case modification 417syn cluster shDerefPatternList contains=shDerefPattern,shDerefString 418syn match shDerefOpError contained ":[[:punct:]]" 419syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList 420syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList 421if exists("b:is_bash") || exists("b:is_kornshell") 422 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList 423 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList 424 syn match shDerefOp contained "\^\{1,2}" nextgroup=@shDerefPatternList 425 syn match shDerefOp contained ",\{1,2}" nextgroup=@shDerefPatternList 426 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern 427 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern 428 syn match shDerefEscape contained '\%(\\\\\)*\\.' 429endif 430syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!'+ end=+'+ contains=shStringSpecial 431syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial 432syn match shDerefString contained "\\["']" nextgroup=shDerefPattern 433 434if exists("b:is_bash") 435 " bash : ${parameter:offset} 436 " bash : ${parameter:offset:length} 437 syn region shDerefOp contained start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL 438 syn match shDerefPOL contained ":[^}]\+" contains=@shCommandSubList 439 440 " bash : ${parameter//pattern/string} 441 " bash : ${parameter//pattern} 442 syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft 443 syn region shDerefPPSleft contained start='.' skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList 444 syn region shDerefPPSright contained start='.' end='\ze}' contains=@shCommandSubList 445endif 446 447" Arithmetic Parenthesized Expressions: {{{1 448syn region shParen matchgroup=shArithRegion start='(\ze[^(]' end=')' contains=@shArithParenList 449 450" Useful sh Keywords: {{{1 451" =================== 452syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait 453syn keyword shConditional contained elif else then 454syn keyword shCondError elif else then 455 456" Useful ksh Keywords: {{{1 457" ==================== 458if exists("b:is_kornshell") || exists("b:is_bash") 459 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 460 if exists("g:is_posix") 461 syn keyword shStatement command 462 else 463 syn keyword shStatement time 464 endif 465 466" Useful bash Keywords: {{{1 467" ===================== 468 if exists("b:is_bash") 469 syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source 470 else 471 syn keyword shStatement login newgrp 472 endif 473endif 474 475" Synchronization: {{{1 476" ================ 477if !exists("sh_minlines") 478 let sh_minlines = 200 479endif 480if !exists("sh_maxlines") 481 let sh_maxlines = 2 * sh_minlines 482endif 483exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines 484syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>" 485syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>" 486syn sync match shDoSync grouphere shDo "\<do\>" 487syn sync match shDoSync groupthere shDo "\<done\>" 488syn sync match shForSync grouphere shFor "\<for\>" 489syn sync match shForSync groupthere shFor "\<in\>" 490syn sync match shIfSync grouphere shIf "\<if\>" 491syn sync match shIfSync groupthere shIf "\<fi\>" 492syn sync match shUntilSync grouphere shRepeat "\<until\>" 493syn sync match shWhileSync grouphere shRepeat "\<while\>" 494 495" Default Highlighting: {{{1 496" ===================== 497hi def link shArithRegion shShellVariables 498hi def link shBeginHere shRedir 499hi def link shCaseBar shConditional 500hi def link shCaseCommandSub shCommandSub 501hi def link shCaseDoubleQuote shDoubleQuote 502hi def link shCaseIn shConditional 503hi def link shQuote shOperator 504hi def link shCaseSingleQuote shSingleQuote 505hi def link shCaseStart shConditional 506hi def link shCmdSubRegion shShellVariables 507hi def link shColon shComment 508hi def link shDerefOp shOperator 509hi def link shDerefPOL shDerefOp 510hi def link shDerefPPS shDerefOp 511hi def link shDeref shShellVariables 512hi def link shDerefDelim shOperator 513hi def link shDerefSimple shDeref 514hi def link shDerefSpecial shDeref 515hi def link shDerefString shDoubleQuote 516hi def link shDerefVar shDeref 517hi def link shDoubleQuote shString 518hi def link shEcho shString 519hi def link shEchoDelim shOperator 520hi def link shEchoQuote shString 521hi def link shEmbeddedEcho shString 522hi def link shEscape shCommandSub 523hi def link shExDoubleQuote shDoubleQuote 524hi def link shExSingleQuote shSingleQuote 525hi def link shFunction Function 526hi def link shHereDoc shString 527hi def link shHerePayload shHereDoc 528hi def link shLoop shStatement 529hi def link shMoreSpecial shSpecial 530hi def link shOption shCommandSub 531hi def link shPattern shString 532hi def link shParen shArithmetic 533hi def link shPosnParm shShellVariables 534hi def link shQuickComment shComment 535hi def link shRange shOperator 536hi def link shRedir shOperator 537hi def link shSetListDelim shOperator 538hi def link shSetOption shOption 539hi def link shSingleQuote shString 540hi def link shSource shOperator 541hi def link shStringSpecial shSpecial 542hi def link shSubShRegion shOperator 543hi def link shTestOpr shConditional 544hi def link shTestPattern shString 545hi def link shTestDoubleQuote shString 546hi def link shTestSingleQuote shString 547hi def link shVariable shSetList 548hi def link shWrapLineOperator shOperator 549 550if exists("b:is_bash") 551 hi def link bashAdminStatement shStatement 552 hi def link bashSpecialVariables shShellVariables 553 hi def link bashStatement shStatement 554 hi def link shFunctionParen Delimiter 555 hi def link shFunctionDelim Delimiter 556endif 557if exists("b:is_kornshell") 558 hi def link kshSpecialVariables shShellVariables 559 hi def link kshStatement shStatement 560 hi def link shFunctionParen Delimiter 561endif 562 563hi def link shCaseError Error 564hi def link shCondError Error 565hi def link shCurlyError Error 566hi def link shDerefError Error 567hi def link shDerefOpError Error 568hi def link shDerefWordError Error 569hi def link shDoError Error 570hi def link shEsacError Error 571hi def link shIfError Error 572hi def link shInError Error 573hi def link shParenError Error 574hi def link shTestError Error 575if exists("b:is_kornshell") 576 hi def link shDTestError Error 577endif 578 579hi def link shArithmetic Special 580hi def link shCharClass Identifier 581hi def link shSnglCase Statement 582hi def link shCommandSub Special 583hi def link shComment Comment 584hi def link shConditional Conditional 585hi def link shCtrlSeq Special 586hi def link shExprRegion Delimiter 587hi def link shFunctionKey Function 588hi def link shFunctionName Function 589hi def link shNumber Number 590hi def link shOperator Operator 591hi def link shRepeat Repeat 592hi def link shSet Statement 593hi def link shSetList Identifier 594hi def link shShellVariables PreProc 595hi def link shSpecial Special 596hi def link shStatement Statement 597hi def link shString String 598hi def link shTodo Todo 599hi def link shAlias Identifier 600 601" Set Current Syntax: {{{1 602" =================== 603if exists("b:is_bash") 604 let b:current_syntax = "bash" 605elseif exists("b:is_kornshell") 606 let b:current_syntax = "ksh" 607else 608 let b:current_syntax = "sh" 609endif 610 611" vim: ts=16 fdm=marker 612