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: Mar 06, 2008
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)
11 " For version 5.x: Clear all syntax items {{{1
12 " For version 6.x: Quit when a syntax file was already loaded
15 elseif exists("b:current_syntax")
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,
26 if !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
30 if exists("g:is_kornshell")
35 elseif exists("g:is_bash")
45 " set up default g:sh_fold_enabled {{{1
46 if !exists("g:sh_fold_enabled")
47 let g:sh_fold_enabled= 0
48 elseif 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"
52 if !exists("s:sh_fold_functions")
53 let s:sh_fold_functions = 1
55 if !exists("s:sh_fold_heredoc")
56 let s:sh_fold_heredoc = 2
58 if !exists("s:sh_fold_ifdofor")
59 let s:sh_fold_ifdofor = 4
61 if g:sh_fold_enabled && &fdm == "manual"
65 " sh syntax is case sensitive {{{1
68 " Clusters: contains=@... clusters {{{1
69 "==================================
70 syn cluster shErrorList contains=shDoError,shIfError,shInError,shCaseError,shEsacError,shCurlyError,shParenError,shTestError
71 if exists("b:is_kornshell")
72 syn cluster ErrorList add=shDTestError
74 syn cluster shArithParenList contains=shArithmetic,shDeref,shDerefSimple,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen
75 syn cluster shArithList contains=@shArithParenList,shParenError
76 syn cluster shCaseEsacList contains=shCaseStart,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial
77 syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
78 syn cluster shColonList contains=@shCaseList
79 syn cluster shCommandSubList contains=shArithmetic,shDeref,shDerefSimple,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shSingleQuote,shDoubleQuote,shStatement,shVariable,shSubSh,shAlias,shTest,shCtrlSeq,shSpecial
80 syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial
81 syn cluster shDblQuoteList contains=shCommandSub,shDeref,shDerefSimple,shPosnParm,shExSingleQuote,shCtrlSeq,shSpecial
82 syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPPS
83 syn cluster shDerefVarList contains=shDerefOp,shDerefVarArray,shDerefOpError
84 syn cluster shEchoList contains=shArithmetic,shCommandSub,shDeref,shDerefSimple,shExpr,shExSingleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote
85 syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq
86 syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest
87 syn cluster shFunctionList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq
88 if exists("b:is_kornshell") || exists("b:is_bash")
89 syn cluster shFunctionList add=shRepeat
90 syn cluster shFunctionList add=shDblBrace,shDblParen
92 syn cluster shHereBeginList contains=@shCommandSubList
93 syn cluster shHereList contains=shBeginHere,shHerePayload
94 syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload
95 syn cluster shIdList contains=shCommandSub,shWrapLineOperator,shSetOption,shDeref,shDerefSimple,shRedir,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial
96 syn cluster shLoopList contains=@shCaseList,shTestOpr,shExpr,shDblBrace,shConditional,shCaseEsac,shTest,@shErrorList,shSet
97 syn cluster shSubShList contains=@shCaseList,shOperator
98 syn cluster shTestList contains=shCharClass,shComment,shCommandSub,shDeref,shDerefSimple,shDoubleQuote,shExpr,shExpr,shNumber,shOperator,shExSingleQuote,shSingleQuote,shTestOpr,shTest,shCtrlSeq
103 " This one is needed INSIDE a CommandSub, so that `echo bla` be correct
104 syn region shEcho matchgroup=shStatement start="\<echo\>" skip="\\$" matchgroup=shOperator end="$" matchgroup=NONE end="[<>;&|()]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
105 syn region shEcho matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shOperator end="$" matchgroup=NONE end="[<>;&|()]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
106 syn match shEchoQuote contained '\%(\\\\\)*\\["`']'
108 " This must be after the strings, so that ... \" will be correct
109 syn region shEmbeddedEcho contained matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shOperator end="$" matchgroup=NONE end="[<>;&|`)]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=shNumber,shExSingleQuote,shSingleQuote,shDeref,shDerefSimple,shSpecialVar,shOperator,shDoubleQuote,shCharClass,shCtrlSeq
113 if exists("b:is_kornshell") || exists("b:is_bash")
114 syn match shStatement "\<alias\>"
115 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+\)\@=" skip="\\$" end="\>\|`"
116 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+=\)\@=" skip="\\$" end="="
121 syn match shDoError "\<done\>"
122 syn match shIfError "\<fi\>"
123 syn match shInError "\<in\>"
124 syn match shCaseError ";;"
125 syn match shEsacError "\<esac\>"
126 syn match shCurlyError "}"
127 syn match shParenError ")"
128 if exists("b:is_kornshell")
129 syn match shDTestError "]]"
131 syn match shTestError "]"
134 " ====================
135 syn match shOption "\s\zs[-+][a-zA-Z0-9]\+\>"
136 syn match shOption "\s\zs--[^ \t$`'"|]\+"
138 " File Redirection Highlighted As Operators: {{{1
139 "===========================================
140 syn match shRedir "\d\=>\(&[-0-9]\)\="
141 syn match shRedir "\d\=>>-\="
142 syn match shRedir "\d\=<\(&[-0-9]\)\="
143 syn match shRedir "\d<<-\="
147 syn match shOperator "<<\|>>" contained
148 syn match shOperator "[!&;|]" contained
149 syn match shOperator "\[[[^:]\|\]]" contained
150 syn match shOperator "!\==" skipwhite nextgroup=shPattern
151 syn match shPattern "\<\S\+\())\)\@=" contained contains=shExSingleQuote,shSingleQuote,shDoubleQuote,shDeref
155 syn region shExpr transparent matchgroup=shExprRegion start="{" end="}" contains=@shExprList2
156 syn region shSubSh transparent matchgroup=shSubShRegion start="(" end=")" contains=@shSubShList
160 "syn region shExpr transparent matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList
161 syn region shExpr matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList
162 syn region shTest transparent matchgroup=shStatement start="\<test\>" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1
163 syn match shTestOpr contained "<=\|>=\|!=\|==\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]"
164 syn match shTestOpr contained '=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern
165 syn match shTestPattern contained '\w\+'
166 syn match shTestDoubleQuote contained '"[^"]*"'
167 syn match shTestSingleQuote contained '\\.'
168 syn match shTestSingleQuote contained "'[^']*'"
169 if exists("b:is_kornshell") || exists("b:is_bash")
170 syn region shDblBrace matchgroup=Delimiter start="\[\[" skip=+\\\\\|\\$+ end="\]\]" contains=@shTestList
171 syn region shDblParen matchgroup=Delimiter start="((" skip=+\\\\\|\\$+ end="))" contains=@shTestList
174 " Character Class In Range: {{{1
175 " =========================
176 syn match shCharClass contained "\[:\(backspace\|escape\|return\|xdigit\|alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|tab\):\]"
178 " Loops: do, if, while, until {{{1
180 if (g:sh_fold_enabled % (s:sh_fold_ifdofor * 2))/s:sh_fold_ifdofor
181 syn region shDo fold transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
182 syn region shIf fold transparent matchgroup=shConditional start="\<if\>" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>" contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
183 syn region shFor fold matchgroup=shLoop start="\<for\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
185 syn region shDo transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
186 syn region shIf transparent matchgroup=shConditional start="\<if\>" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>" contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
187 syn region shFor matchgroup=shLoop start="\<for\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
189 if exists("b:is_kornshell") || exists("b:is_bash")
190 syn cluster shCaseList add=shRepeat
191 syn cluster shFunctionList add=shRepeat
192 syn region shRepeat matchgroup=shLoop start="\<while\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace
193 syn region shRepeat matchgroup=shLoop start="\<until\>" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace
194 syn region shCaseEsac matchgroup=shConditional start="\<select\>" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList
196 syn region shRepeat matchgroup=shLoop start="\<while\>" end="\<do\>"me=e-2 contains=@shLoopList
197 syn region shRepeat matchgroup=shLoop start="\<until\>" end="\<do\>"me=e-2 contains=@shLoopList
199 syn region shCurlyIn contained matchgroup=Delimiter start="{" end="}" contains=@shCurlyList
200 syn match shComma contained ","
202 " Case: case...esac {{{1
204 syn match shCaseBar contained skipwhite "\(^\|[^\\]\)\(\\\\\)*\zs|" nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
205 syn match shCaseStart contained skipwhite skipnl "(" nextgroup=shCase,shCaseBar
206 syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)" end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment
207 if (g:sh_fold_enabled % (s:sh_fold_ifdofor * 2))/s:sh_fold_ifdofor
208 syn region shCaseEsac fold matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList
210 syn region shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList
212 syn keyword shCaseIn contained skipwhite skipnl in nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
213 if exists("b:is_bash")
214 syn region shCaseExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial skipwhite skipnl nextgroup=shCaseBar contained
216 syn region shCaseExSingleQuote matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained
218 syn region shCaseSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained
219 syn region shCaseDoubleQuote matchgroup=shOperator start=+"+ skip=+\\\\\|\\.+ end=+"+ contains=@shDblQuoteList,shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained
220 syn region shCaseCommandSub start=+`+ skip=+\\\\\|\\.+ end=+`+ contains=@shCommandSubList skipwhite skipnl nextgroup=shCaseBar contained
224 syn match shWrapLineOperator "\\$"
225 syn region shCommandSub start="`" skip="\\\\\|\\." end="`" contains=@shCommandSubList
226 syn match shEscape contained '\\.'
228 " $() and $(()): {{{1
229 " $(..) is not supported by sh (Bourne shell). However, apparently
230 " some systems (HP?) have as their /bin/sh a (link to) Korn shell
231 " (ie. Posix compliant shell). /bin/ksh should work for those
232 " systems too, however, so the following syntax will flag $(..) as
233 " an Error under /bin/sh. By consensus of vimdev'ers!
234 if exists("b:is_kornshell") || exists("b:is_bash")
235 syn region shCommandSub matchgroup=shCmdSubRegion start="\$(" skip='\\\\\|\\.' end=")" contains=@shCommandSubList
236 syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList
237 syn match shSkipInitWS contained "^\s\+"
239 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList
242 if exists("b:is_bash")
243 syn cluster shCommandSubList add=bashSpecialVariables,bashStatement
244 syn cluster shCaseList add=bashAdminStatement,bashStatement
245 syn keyword bashSpecialVariables contained BASH BASH_ENV BASH_VERSINFO BASH_VERSION CDPATH DIRSTACK EUID FCEDIT FIGNORE GLOBIGNORE GROUPS HISTCMD HISTCONTROL HISTFILE HISTFILESIZE HISTIGNORE HISTSIZE HOME HOSTFILE HOSTNAME HOSTTYPE IFS IGNOREEOF INPUTRC LANG LC_ALL LC_COLLATE LC_MESSAGES LINENO MACHTYPE MAIL MAILCHECK MAILPATH OLDPWD OPTARG OPTERR OPTIND OSTYPE PATH PIPESTATUS PPID PROMPT_COMMAND PS1 PS2 PS3 PS4 PWD RANDOM REPLY SECONDS SHELLOPTS SHLVL TIMEFORMAT TIMEOUT UID auto_resume histchars
246 syn keyword bashStatement chmod clear complete du egrep expr fgrep find gnufind gnugrep grep install less ls mkdir mv rm rmdir rpm sed sleep sort strip tail touch
247 syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop
250 if exists("b:is_kornshell")
251 syn cluster shCommandSubList add=kshSpecialVariables,kshStatement
252 syn cluster shCaseList add=kshStatement
253 syn keyword kshSpecialVariables contained CDPATH COLUMNS EDITOR ENV ERRNO FCEDIT FPATH HISTFILE HISTSIZE HOME IFS LINENO LINES MAIL MAILCHECK MAILPATH OLDPWD OPTARG OPTIND PATH PPID PS1 PS2 PS3 PS4 PWD RANDOM REPLY SECONDS SHELL TMOUT VISUAL
254 syn keyword kshStatement cat chmod clear cp du egrep expr fgrep find grep install killall less ls mkdir mv nice printenv rm rmdir sed sort strip stty tail touch tput
257 syn match shSource "^\.\s"
258 syn match shSource "\s\.\s"
259 syn region shColon start="^\s*:" end="$\|" end="#"me=e-1 contains=@shColonList
261 " String And Character Constants: {{{1
262 "================================
263 syn match shNumber "-\=\<\d\+\>#\="
264 syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained
265 if exists("b:is_bash")
266 syn match shSpecial "\\\o\o\o\|\\x\x\x\|\\c.\|\\[abefnrtv]" contained
268 if exists("b:is_bash")
269 syn region shExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial
271 syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial
273 syn region shSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=shStringSpecial,@Spell
274 syn region shDoubleQuote matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell
275 syn match shStringSpecial "[^[:print:]]" contained
276 syn match shStringSpecial "\%(\\\\\)*\\[\\"'`$()#]"
277 syn match shSpecial "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]"
278 syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]"
282 syn cluster shCommentGroup contains=shTodo,@Spell
283 syn keyword shTodo contained COMBAK FIXME TODO XXX
284 syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup
285 syn match shComment "\s\zs#.*$" contains=@shCommentGroup
286 syn match shQuickComment contained "#.*$"
288 " Here Documents: {{{1
289 " =========================================
291 syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
292 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^\s*END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
293 syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir end="^EOF$" contains=@shDblQuoteList
294 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir end="^\s*EOF$" contains=@shDblQuoteList
295 syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**" matchgroup=shRedir end="^\.$" contains=@shDblQuoteList
296 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir end="^\s*\.$" contains=@shDblQuoteList
298 elseif (g:sh_fold_enabled % (s:sh_fold_heredoc * 2))/s:sh_fold_heredoc
299 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList
300 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$"
301 syn region shHereDoc matchgroup=shRedir fold start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$"
302 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList
303 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$"
304 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$"
305 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
306 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$"
307 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$"
308 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$"
309 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$"
310 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$"
311 syn region shHereDoc matchgroup=shRedir fold start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
314 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList
315 syn region shHereDoc matchgroup=shRedir start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$"
316 syn region shHereDoc matchgroup=shRedir start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList
317 syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$"
318 syn region shHereDoc matchgroup=shRedir start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$"
319 syn region shHereDoc matchgroup=shRedir start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$"
320 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
321 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$"
322 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$"
323 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$"
324 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$"
325 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$"
326 syn region shHereDoc matchgroup=shRedir start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
331 if exists("b:is_bash")
332 syn match shRedir "<<<"
337 syn match shSetOption "\s\zs[-+][a-zA-Z0-9]\+\>" contained
338 syn match shVariable "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze=" nextgroup=shSetIdentifier
339 syn match shSetIdentifier "=" contained nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shSingleQuote,shExSingleQuote
340 if exists("b:is_bash")
341 syn region shSetList oneline matchgroup=shSet start="\<\(declare\|typeset\|local\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze#\|=" contains=@shIdList
342 syn region shSetList oneline matchgroup=shSet start="\<set\>\ze[^/]" end="\ze[;|)]\|$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze[#=]" contains=@shIdList
343 elseif exists("b:is_kornshell")
344 syn region shSetList oneline matchgroup=shSet start="\<\(typeset\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze[#=]" contains=@shIdList
345 syn region shSetList oneline matchgroup=shSet start="\<set\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze[#=]" contains=@shIdList
347 syn region shSetList oneline matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze[#=]" contains=@shIdList
351 syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo
353 if exists("b:is_bash")
354 if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions
355 syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
356 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
358 syn region shFunctionOne matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList
359 syn region shFunctionTwo matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
362 if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions
363 syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
364 syn region shFunctionTwo fold matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
366 syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList
367 syn region shFunctionTwo matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
371 " Parameter Dereferencing: {{{1
372 " ========================
373 syn match shDerefSimple "\$\%(\h\w*\|\d\)"
374 syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray
375 syn match shDerefWordError "[^}$[]" contained
376 syn match shDerefSimple "\$[-#*@!?]"
377 syn match shDerefSimple "\$\$"
378 if exists("b:is_bash") || exists("b:is_kornshell")
379 syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList
380 syn region shDeref matchgroup=PreProc start="\${\$\$" end="}" contains=@shDerefList
383 " bash: ${!prefix*} and ${#parameter}: {{{1
384 " ====================================
385 if exists("b:is_bash")
386 syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOp
387 syn match shDerefVar contained "{\@<=!\w\+" nextgroup=@shDerefVarList
390 syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOpError
391 syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp
392 syn match shDerefVar contained "{\@<=\w\+" nextgroup=@shDerefVarList
394 " sh ksh bash : ${var[... ]...} array reference: {{{1
395 syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError
397 " Special ${parameter OPERATOR word} handling: {{{1
398 " sh ksh bash : ${parameter:-word} word is default value
399 " sh ksh bash : ${parameter:=word} assign word as default value
400 " sh ksh bash : ${parameter:?word} display word if parameter is null
401 " sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing
402 " ksh bash : ${parameter#pattern} remove small left pattern
403 " ksh bash : ${parameter##pattern} remove large left pattern
404 " ksh bash : ${parameter%pattern} remove small right pattern
405 " ksh bash : ${parameter%%pattern} remove large right pattern
406 syn cluster shDerefPatternList contains=shDerefPattern,shDerefString
407 syn match shDerefOpError contained ":[[:punct:]]"
408 syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList
409 syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList
410 if exists("b:is_bash") || exists("b:is_kornshell")
411 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList
412 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList
413 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern
414 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern
415 syn match shDerefEscape contained '\%(\\\\\)*\\.'
417 syn region shDerefString contained matchgroup=shOperator start=+\%(\\\)\@<!'+ end=+'+ contains=shStringSpecial
418 syn region shDerefString contained matchgroup=shOperator start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial
419 syn match shDerefString contained "\\["']" nextgroup=shDerefPattern
421 if exists("b:is_bash")
422 " bash : ${parameter:offset}
423 " bash : ${parameter:offset:length}
424 syn region shDerefOp contained start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL
425 syn match shDerefPOL contained ":[^}]\+" contains=@shCommandSubList
427 " bash : ${parameter//pattern/string}
428 " bash : ${parameter//pattern}
429 syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft
430 syn region shDerefPPSleft contained start='.' skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList
431 syn region shDerefPPSright contained start='.' end='\ze}' contains=@shCommandSubList
434 " Arithmetic Parenthesized Expressions: {{{1
435 syn region shParen matchgroup=shArithRegion start='(\ze[^(]' end=')' contains=@shArithParenList
437 " Useful sh Keywords: {{{1
438 " ===================
439 syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait
440 syn keyword shConditional contained elif else then
441 syn keyword shCondError elif else then
443 " Useful ksh Keywords: {{{1
444 " ====================
445 if exists("b:is_kornshell") || exists("b:is_bash")
446 syn keyword shStatement autoload bg false fc fg functions getopts hash history integer jobs let nohup print printf r stop suspend time times true type unalias whence
448 " Useful bash Keywords: {{{1
449 " =====================
450 if exists("b:is_bash")
451 syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source
453 syn keyword shStatement login newgrp
457 " Synchronization: {{{1
459 if !exists("sh_minlines")
460 let sh_minlines = 200
462 if !exists("sh_maxlines")
463 let sh_maxlines = 2 * sh_minlines
465 exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines
466 syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>"
467 syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>"
468 syn sync match shDoSync grouphere shDo "\<do\>"
469 syn sync match shDoSync groupthere shDo "\<done\>"
470 syn sync match shForSync grouphere shFor "\<for\>"
471 syn sync match shForSync groupthere shFor "\<in\>"
472 syn sync match shIfSync grouphere shIf "\<if\>"
473 syn sync match shIfSync groupthere shIf "\<fi\>"
474 syn sync match shUntilSync grouphere shRepeat "\<until\>"
475 syn sync match shWhileSync grouphere shRepeat "\<while\>"
477 " Default Highlighting: {{{1
478 " =====================
479 hi def link shArithRegion shShellVariables
480 hi def link shBeginHere shRedir
481 hi def link shCaseBar shConditional
482 hi def link shCaseCommandSub shCommandSub
483 hi def link shCaseDoubleQuote shDoubleQuote
484 hi def link shCaseIn shConditional
485 hi def link shCaseSingleQuote shSingleQuote
486 hi def link shCaseStart shConditional
487 hi def link shCmdSubRegion shShellVariables
488 hi def link shColon shStatement
489 hi def link shDerefOp shOperator
490 hi def link shDerefPOL shDerefOp
491 hi def link shDerefPPS shDerefOp
492 hi def link shDeref shShellVariables
493 hi def link shDerefSimple shDeref
494 hi def link shDerefSpecial shDeref
495 hi def link shDerefString shDoubleQuote
496 hi def link shDerefVar shDeref
497 hi def link shDoubleQuote shString
498 hi def link shEcho shString
499 hi def link shEchoQuote shString
500 hi def link shEmbeddedEcho shString
501 hi def link shEscape shCommandSub
502 hi def link shExSingleQuote shSingleQuote
503 hi def link shFunction Function
504 hi def link shHereDoc shString
505 hi def link shHerePayload shHereDoc
506 hi def link shLoop shStatement
507 hi def link shOption shCommandSub
508 hi def link shPattern shString
509 hi def link shParen shArithmetic
510 hi def link shPosnParm shShellVariables
511 hi def link shQuickComment shComment
512 hi def link shRange shOperator
513 hi def link shRedir shOperator
514 hi def link shSetOption shOption
515 hi def link shSingleQuote shString
516 hi def link shSource shOperator
517 hi def link shStringSpecial shSpecial
518 hi def link shSubShRegion shOperator
519 hi def link shTestOpr shConditional
520 hi def link shTestPattern shString
521 hi def link shTestDoubleQuote shString
522 hi def link shTestSingleQuote shString
523 hi def link shVariable shSetList
524 hi def link shWrapLineOperator shOperator
526 if exists("b:is_bash")
527 hi def link bashAdminStatement shStatement
528 hi def link bashSpecialVariables shShellVariables
529 hi def link bashStatement shStatement
530 hi def link shFunctionParen Delimiter
531 hi def link shFunctionDelim Delimiter
533 if exists("b:is_kornshell")
534 hi def link kshSpecialVariables shShellVariables
535 hi def link kshStatement shStatement
536 hi def link shFunctionParen Delimiter
539 hi def link shCaseError Error
540 hi def link shCondError Error
541 hi def link shCurlyError Error
542 hi def link shDerefError Error
543 hi def link shDerefOpError Error
544 hi def link shDerefWordError Error
545 hi def link shDoError Error
546 hi def link shEsacError Error
547 hi def link shIfError Error
548 hi def link shInError Error
549 hi def link shParenError Error
550 hi def link shTestError Error
551 if exists("b:is_kornshell")
552 hi def link shDTestError Error
555 hi def link shArithmetic Special
556 hi def link shCharClass Identifier
557 hi def link shSnglCase Statement
558 hi def link shCommandSub Special
559 hi def link shComment Comment
560 hi def link shConditional Conditional
561 hi def link shCtrlSeq Special
562 hi def link shExprRegion Delimiter
563 hi def link shFunctionKey Function
564 hi def link shFunctionName Function
565 hi def link shNumber Number
566 hi def link shOperator Operator
567 hi def link shRepeat Repeat
568 hi def link shSet Statement
569 hi def link shSetList Identifier
570 hi def link shShellVariables PreProc
571 hi def link shSpecial Special
572 hi def link shStatement Statement
573 hi def link shString String
574 hi def link shTodo Todo
575 hi def link shAlias Identifier
577 " Set Current Syntax: {{{1
578 " ===================
579 if exists("b:is_bash")
580 let b:current_syntax = "bash"
581 elseif exists("b:is_kornshell")
582 let b:current_syntax = "ksh"
584 let b:current_syntax = "sh"
587 " vim: ts=16 fdm=marker