xref: /vim-8.2.3635/runtime/syntax/sh.vim (revision fa79be6b)
1" Vim syntax file
2" Language:		shell (sh) Korn shell (ksh) bash (sh)
3" Maintainer:		Charles E. Campbell <[email protected]>
4" Previous Maintainer:	Lennart Schultz <[email protected]>
5" Last Change:		Aug 10, 2020
6" Version:		193
7" URL:		http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
8" For options and settings, please use:      :help ft-sh-syntax
9" This file includes many ideas from Eric Brunet ([email protected])
10
11" quit when a syntax file was already loaded {{{1
12if exists("b:current_syntax")
13  finish
14endif
15
16" trying to answer the question: which shell is /bin/sh, really?
17" If the user has not specified any of g:is_kornshell, g:is_bash, g:is_posix, g:is_sh, then guess.
18if getline(1) =~ '\<ksh$'
19 let b:is_kornshell = 1
20elseif getline(1) =~ '\<bash$'
21 let b:is_bash      = 1
22elseif getline(1) =~ '\<dash$'
23 let b:is_dash      = 1
24elseif !exists("g:is_kornshell") && !exists("g:is_bash") && !exists("g:is_posix") && !exists("g:is_sh") && !exists("g:is_dash")
25 let s:shell = ""
26 if executable("/bin/sh")
27  let s:shell = resolve("/bin/sh")
28 elseif executable("/usr/bin/sh")
29  let s:shell = resolve("/usr/bin/sh")
30 endif
31 if     s:shell =~ 'ksh$'
32  let b:is_kornshell= 1
33 elseif s:shell =~ 'bash$'
34  let b:is_bash = 1
35 elseif s:shell =~ 'dash$'
36  let b:is_dash = 1
37 endif
38 unlet s:shell
39endif
40
41" handling /bin/sh with is_kornshell/is_sh {{{1
42" b:is_sh is set when "#! /bin/sh" is found;
43" However, it often is just a masquerade by bash (typically Linux)
44" or kornshell (typically workstations with Posix "sh").
45" So, when the user sets "g:is_bash", "g:is_kornshell",
46" or "g:is_posix", a b:is_sh is converted into b:is_bash/b:is_kornshell,
47" respectively.
48if !exists("b:is_kornshell") && !exists("b:is_bash") && !exists("b:is_dash")
49  if exists("g:is_posix") && !exists("g:is_kornshell")
50   let g:is_kornshell= g:is_posix
51  endif
52  if exists("g:is_kornshell")
53    let b:is_kornshell= 1
54    if exists("b:is_sh")
55      unlet b:is_sh
56    endif
57  elseif exists("g:is_bash")
58    let b:is_bash= 1
59    if exists("b:is_sh")
60      unlet b:is_sh
61    endif
62  elseif exists("g:is_dash")
63    let b:is_dash= 1
64    if exists("b:is_sh")
65      unlet b:is_sh
66    endif
67  else
68    let b:is_sh= 1
69  endif
70endif
71
72" if b:is_dash, set b:is_posix too
73if exists("b:is_dash")
74 let b:is_posix= 1
75endif
76
77" set up default g:sh_fold_enabled {{{1
78" ================================
79if !exists("g:sh_fold_enabled")
80 let g:sh_fold_enabled= 0
81elseif g:sh_fold_enabled != 0 && !has("folding")
82 let g:sh_fold_enabled= 0
83 echomsg "Ignoring g:sh_fold_enabled=".g:sh_fold_enabled."; need to re-compile vim for +fold support"
84endif
85if !exists("s:sh_fold_functions")
86 let s:sh_fold_functions= and(g:sh_fold_enabled,1)
87endif
88if !exists("s:sh_fold_heredoc")
89 let s:sh_fold_heredoc  = and(g:sh_fold_enabled,2)
90endif
91if !exists("s:sh_fold_ifdofor")
92 let s:sh_fold_ifdofor  = and(g:sh_fold_enabled,4)
93endif
94if g:sh_fold_enabled && &fdm == "manual"
95 " Given that	the	user provided g:sh_fold_enabled
96 " 	AND	g:sh_fold_enabled is manual (usual default)
97 " 	implies	a desire for syntax-based folding
98 setl fdm=syntax
99endif
100
101" set up the syntax-highlighting iskeyword
102if (v:version == 704 && has("patch-7.4.1142")) || v:version > 704
103 if exists("b:is_bash")
104  exe "syn iskeyword ".&iskeyword.",-,:"
105 else
106  exe "syn iskeyword ".&iskeyword.",-"
107 endif
108endif
109
110" Set up folding commands for shell {{{1
111" =================================
112if s:sh_fold_functions
113 com! -nargs=* ShFoldFunctions <args> fold
114else
115 com! -nargs=* ShFoldFunctions <args>
116endif
117if s:sh_fold_heredoc
118 com! -nargs=* ShFoldHereDoc <args> fold
119else
120 com! -nargs=* ShFoldHereDoc <args>
121endif
122if s:sh_fold_ifdofor
123 com! -nargs=* ShFoldIfDoFor <args> fold
124else
125 com! -nargs=* ShFoldIfDoFor <args>
126endif
127
128" sh syntax is case sensitive {{{1
129syn case match
130
131" Clusters: contains=@... clusters {{{1
132"==================================
133syn cluster shErrorList	contains=shDoError,shIfError,shInError,shCaseError,shEsacError,shCurlyError,shParenError,shTestError,shOK
134if exists("b:is_kornshell") || exists("b:is_bash")
135 syn cluster ErrorList add=shDTestError
136endif
137syn cluster shArithParenList	contains=shArithmetic,shCaseEsac,shComment,shDeref,shDo,shDerefSimple,shEcho,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shExDoubleQuote,shHereString,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement,shIf,shFor,shFunctionKey,shFunctionOne,shFunctionTwo
138syn cluster shArithList	contains=@shArithParenList,shParenError
139syn cluster shCaseEsacList	contains=shCaseStart,shCaseLabel,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial,shCaseRange
140syn cluster shCaseList	contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSubBQ,shComment,shDo,shEcho,shExpr,shFor,shForPP,shHereDoc,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
141syn cluster shCommandSubList	contains=shAlias,shArithmetic,shCmdParenRegion,shCommandSub,shComment,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable
142syn cluster shCurlyList	contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial
143" COMBAK: removing shEscape fromshDblQuoteList fails ksh04:43
144syn cluster shDblQuoteList	contains=shArithmetic,shCommandSub,shCommandSubBQ,shDeref,shDerefSimple,shPosnParm,shCtrlSeq,shSpecial,shSpecialDQ
145syn cluster shDerefList	contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPSR,shDerefPPS
146syn cluster shDerefVarList	contains=shDerefOffset,shDerefOp,shDerefVarArray,shDerefOpError
147syn cluster shEchoList	contains=shArithmetic,shCommandSub,shCommandSubBQ,shDeref,shDerefSimple,shEscape,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote
148syn cluster shExprList1	contains=shCharClass,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq
149syn cluster shExprList2	contains=@shExprList1,@shCaseList,shTest
150syn cluster shFunctionList	contains=@shCommandSubList,shCaseEsac,shColon,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shOption,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq
151if exists("b:is_kornshell") || exists("b:is_bash")
152 syn cluster shFunctionList	add=shRepeat
153 syn cluster shFunctionList	add=shDblBrace,shDblParen
154endif
155syn cluster shHereBeginList	contains=@shCommandSubList
156syn cluster shHereList	contains=shBeginHere,shHerePayload
157syn cluster shHereListDQ	contains=shBeginHere,@shDblQuoteList,shHerePayload
158syn cluster shIdList	contains=shCommandSub,shCommandSubBQ,shWrapLineOperator,shSetOption,shComment,shDeref,shDerefSimple,shHereString,shNumber,shOperator,shRedir,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial,shAtExpr
159syn cluster shIfList	contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey,shFunctionOne,shFunctionTwo
160syn cluster shLoopList	contains=@shCaseList,@shErrorList,shCaseEsac,shConditional,shDblBrace,shExpr,shFor,shForPP,shIf,shOption,shSet,shTest,shTestOpr,shTouch
161syn cluster shPPSLeftList	contains=shAlias,shArithmetic,shCmdParenRegion,shCommandSub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable
162syn cluster shPPSRightList	contains=shComment,shDeref,shDerefSimple,shEscape,shPosnParm
163syn cluster shSubShList	contains=@shCommandSubList,shCommandSubBQ,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator
164syn cluster shTestList	contains=shArithmetic,shCharClass,shCommandSub,shCommandSubBQ,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shSpecialDQ,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr
165syn cluster shNoZSList	contains=shSpecialNoZS
166syn cluster shForList	contains=shTestOpr,shNumber,shDerefSimple,shDeref,shCommandSub,shCommandSubBQ,shArithmetic
167
168" Echo: {{{1
169" ====
170" This one is needed INSIDE a CommandSub, so that `echo bla` be correct
171syn region shEcho matchgroup=shStatement start="\<echo\>"  skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
172syn region shEcho matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
173syn match  shEchoQuote contained	'\%(\\\\\)*\\["`'()]'
174
175" This must be after the strings, so that ... \" will be correct
176syn 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
177
178" Alias: {{{1
179" =====
180if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")
181 syn match shStatement "\<alias\>"
182 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\h[-._[:alnum:]]\+\)\@="  skip="\\$" end="\>\|`"
183 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\h[-._[:alnum:]]\+=\)\@=" skip="\\$" end="="
184
185 " Touch: {{{1
186 " =====
187 syn match shTouch	'\<touch\>[^;#]*'	skipwhite nextgroup=shComment contains=shTouchCmd,shDoubleQuote,shSingleQuote,shDeref,shDerefSimple
188 syn match shTouchCmd	'\<touch\>'		contained
189endif
190
191" Error Codes: {{{1
192" ============
193if !exists("g:sh_no_error")
194 syn match   shDoError "\<done\>"
195 syn match   shIfError "\<fi\>"
196 syn match   shInError "\<in\>"
197 syn match   shCaseError ";;"
198 syn match   shEsacError "\<esac\>"
199 syn match   shCurlyError "}"
200 syn match   shParenError ")"
201 syn match   shOK	'\.\(done\|fi\|in\|esac\)'
202 if exists("b:is_kornshell") || exists("b:is_bash")
203  syn match     shDTestError "]]"
204 endif
205 syn match     shTestError "]"
206endif
207
208" Options: {{{1
209" ====================
210syn match   shOption	"\s\zs[-+][-_a-zA-Z#@]\+"
211syn match   shOption	"\s\zs--[^ \t$=`'"|);]\+"
212
213" File Redirection Highlighted As Operators: {{{1
214"===========================================
215syn match      shRedir	"\d\=>\(&[-0-9]\)\="
216syn match      shRedir	"\d\=>>-\="
217syn match      shRedir	"\d\=<\(&[-0-9]\)\="
218syn match      shRedir	"\d<<-\="
219
220" Operators: {{{1
221" ==========
222syn match   shOperator	"<<\|>>"		contained
223syn match   shOperator	"[!&;|]"		contained
224syn match   shOperator	"\[[[^:]\|\]]"		contained
225syn match   shOperator	"[-=/*+%]\=="		skipwhite nextgroup=shPattern
226syn match   shPattern	"\<\S\+\())\)\@="	contained contains=shExSingleQuote,shSingleQuote,shExDoubleQuote,shDoubleQuote,shDeref
227
228" Subshells: {{{1
229" ==========
230syn region shExpr  transparent matchgroup=shExprRegion  start="{" end="}"		contains=@shExprList2 nextgroup=shSpecialNxt
231syn region shSubSh transparent matchgroup=shSubShRegion start="[^(]\zs(" end=")"	contains=@shSubShList nextgroup=shSpecialNxt
232
233" Tests: {{{1
234"=======
235syn region shExpr	matchgroup=shRange start="\[" skip=+\\\\\|\\$\|\[+ end="\]" contains=@shTestList,shSpecial
236syn region shTest	transparent matchgroup=shStatement start="\<test\s" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1
237syn region shNoQuote	start='\S'	skip='\%(\\\\\)*\\.'	end='\ze\s' end="\ze['"]"	contained contains=shDerefSimple,shDeref
238syn match  shAstQuote	contained	'\*\ze"'	nextgroup=shString
239syn match  shTestOpr	contained	'[^-+/%]\zs=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern
240syn match  shTestOpr	contained	"<=\|>=\|!=\|==\|=\~\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]"
241syn match  shTestPattern	contained	'\w\+'
242syn region shTestDoubleQuote	contained	start='\%(\%(\\\\\)*\\\)\@<!"' skip=+\\\\\|\\"+ end='"'	contains=shDeref,shDerefSimple,shDerefSpecial
243syn match  shTestSingleQuote	contained	'\\.'	nextgroup=shTestSingleQuote
244syn match  shTestSingleQuote	contained	"'[^']*'"
245if exists("b:is_kornshell") || exists("b:is_bash")
246 syn region  shDblBrace matchgroup=Delimiter start="\[\["	skip=+\%(\\\\\)*\\$+ end="\]\]"	contains=@shTestList,shAstQuote,shNoQuote,shComment
247 syn region  shDblParen matchgroup=Delimiter start="(("	skip=+\%(\\\\\)*\\$+ end="))"	contains=@shTestList,shComment
248endif
249
250" Character Class In Range: {{{1
251" =========================
252syn match   shCharClass	contained	"\[:\(backspace\|escape\|return\|xdigit\|alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|tab\):\]"
253
254" Loops: do, if, while, until {{{1
255" ======
256ShFoldIfDoFor syn region shDo	transparent	matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>"			contains=@shLoopList
257ShFoldIfDoFor syn region shIf	transparent	matchgroup=shConditional start="\<if\_s" matchgroup=shConditional skip=+-fi\>+ end="\<;\_s*then\>" end="\<fi\>"	contains=@shIfList
258ShFoldIfDoFor syn region shFor		matchgroup=shLoop start="\<for\ze\_s\s*\%(((\)\@!" end="\<in\>" end="\<do\>"me=e-2			contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
259ShFoldIfDoFor syn region shForPP	matchgroup=shLoop start='\<for\>\_s*((' end='))' contains=@shForList
260
261if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")
262 syn cluster shCaseList	add=shRepeat
263 syn cluster shFunctionList	add=shRepeat
264 syn region shRepeat   matchgroup=shLoop   start="\<while\_s" end="\<do\>"me=e-2	contains=@shLoopList,shDblParen,shDblBrace
265 syn region shRepeat   matchgroup=shLoop   start="\<until\_s" end="\<do\>"me=e-2	contains=@shLoopList,shDblParen,shDblBrace
266 if !exists("b:is_posix")
267  syn region shCaseEsac matchgroup=shConditional start="\<select\s" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList
268 endif
269else
270 syn region shRepeat   matchgroup=shLoop   start="\<while\_s" end="\<do\>"me=e-2		contains=@shLoopList
271 syn region shRepeat   matchgroup=shLoop   start="\<until\_s" end="\<do\>"me=e-2		contains=@shLoopList
272endif
273syn region shCurlyIn   contained	matchgroup=Delimiter start="{" end="}" contains=@shCurlyList
274syn match  shComma     contained	","
275
276" Case: case...esac {{{1
277" ====
278syn match shCaseBar	contained skipwhite "\(^\|[^\\]\)\(\\\\\)*\zs|"		nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
279syn match shCaseStart	contained skipwhite skipnl "("			nextgroup=shCase,shCaseBar
280syn match shCaseLabel	contained skipwhite	"\%(\\.\|[-a-zA-Z0-9_*.]\)\+"	contains=shCharClass
281if exists("b:is_bash")
282 ShFoldIfDoFor syn region	shCase	contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)"  end=";;" end=";&" end=";;&" end="esac"me=s-1	contains=@shCaseList	nextgroup=shCaseStart,shCase,shComment
283else
284 ShFoldIfDoFor syn region	shCase	contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)"  end=";;" end="esac"me=s-1		contains=@shCaseList	nextgroup=shCaseStart,shCase,shComment
285endif
286ShFoldIfDoFor syn region	shCaseEsac	matchgroup=shConditional start="\<case\>" end="\<esac\>"	contains=@shCaseEsacList
287
288syn keyword shCaseIn	contained skipwhite skipnl in			nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
289if exists("b:is_bash")
290 syn region  shCaseExSingleQuote	matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+	contains=shStringSpecial,shSpecial	skipwhite skipnl nextgroup=shCaseBar	contained
291elseif !exists("g:sh_no_error")
292 syn region  shCaseExSingleQuote	matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+	contains=shStringSpecial	skipwhite skipnl nextgroup=shCaseBar	contained
293endif
294syn region  shCaseSingleQuote	matchgroup=shQuote start=+'+ end=+'+		contains=shStringSpecial		skipwhite skipnl nextgroup=shCaseBar	contained
295syn region  shCaseDoubleQuote	matchgroup=shQuote start=+"+ skip=+\\\\\|\\.+ end=+"+	contains=@shDblQuoteList,shStringSpecial	skipwhite skipnl nextgroup=shCaseBar	contained
296syn region  shCaseCommandSub	start=+`+ skip=+\\\\\|\\.+ end=+`+		contains=@shCommandSubList		skipwhite skipnl nextgroup=shCaseBar	contained
297if exists("b:is_bash")
298 syn region  shCaseRange	matchgroup=Delimiter start=+\[+ skip=+\\\\+ end=+\]+	contained	contains=shCharClass
299 syn match   shCharClass	'\[:\%(alnum\|alpha\|ascii\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|word\|or\|xdigit\):\]'			contained
300else
301 syn region  shCaseRange	matchgroup=Delimiter start=+\[+ skip=+\\\\+ end=+\]+	contained
302endif
303" Misc: {{{1
304"======
305syn match   shWrapLineOperator "\\$"
306syn region  shCommandSubBQ   	start="`" skip="\\\\\|\\." end="`"	contains=shBQComment,@shCommandSubList
307"COMBAK: see ksh13:50
308"syn match   shEscape	contained	'\%(^\)\@!\%(\\\\\)*\\.'	nextgroup=shSingleQuote,shDoubleQuote,shComment
309"COMBAK: see sh11:27
310syn match   shEscape	contained	'\%(^\)\@!\%(\\\\\)*\\.'	nextgroup=shComment
311"COMBAK: see ksh13:53
312"syn match   shEscape	contained	'\%(^\)\@!\%(\\\\\)*\\.'
313
314" $() and $(()): {{{1
315" $(..) is not supported by sh (Bourne shell).  However, apparently
316" some systems (HP?) have as their /bin/sh a (link to) Korn shell
317" (ie. Posix compliant shell).  /bin/ksh should work for those
318" systems too, however, so the following syntax will flag $(..) as
319" an Error under /bin/sh.  By consensus of vimdev'ers!
320if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")
321 syn region shCommandSub matchgroup=shCmdSubRegion start="\$("  skip='\\\\\|\\.' end=")"  contains=@shCommandSubList
322 syn region shArithmetic matchgroup=shArithRegion  start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList
323 syn region shArithmetic matchgroup=shArithRegion  start="\$\[" skip='\\\\\|\\.' end="\]" contains=@shArithList
324 syn match  shSkipInitWS contained	"^\s\+"
325elseif !exists("g:sh_no_error")
326 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList
327endif
328syn region shCmdParenRegion matchgroup=shCmdSubRegion start="(\ze[^(]" skip='\\\\\|\\.' end=")" contains=@shCommandSubList
329
330if exists("b:is_bash")
331 syn cluster shCommandSubList add=bashSpecialVariables,bashStatement
332 syn cluster shCaseList add=bashAdminStatement,bashStatement
333 syn keyword bashSpecialVariables contained auto_resume BASH BASH_ALIASES BASH_ALIASES BASH_ARGC BASH_ARGC BASH_ARGV BASH_ARGV BASH_CMDS BASH_CMDS BASH_COMMAND BASH_COMMAND BASH_ENV BASH_EXECUTION_STRING BASH_EXECUTION_STRING BASH_LINENO BASH_LINENO BASHOPTS BASHOPTS BASHPID BASHPID BASH_REMATCH BASH_REMATCH BASH_SOURCE BASH_SOURCE BASH_SUBSHELL BASH_SUBSHELL BASH_VERSINFO BASH_VERSION BASH_XTRACEFD BASH_XTRACEFD CDPATH COLUMNS COLUMNS COMP_CWORD COMP_CWORD COMP_KEY COMP_KEY COMP_LINE COMP_LINE COMP_POINT COMP_POINT COMPREPLY COMPREPLY COMP_TYPE COMP_TYPE COMP_WORDBREAKS COMP_WORDBREAKS COMP_WORDS COMP_WORDS COPROC COPROC DIRSTACK EMACS EMACS ENV ENV EUID FCEDIT FIGNORE FUNCNAME FUNCNAME FUNCNEST FUNCNEST GLOBIGNORE GROUPS histchars HISTCMD HISTCONTROL HISTFILE HISTFILESIZE HISTIGNORE HISTSIZE HISTTIMEFORMAT HISTTIMEFORMAT HOME HOSTFILE HOSTNAME HOSTTYPE IFS IGNOREEOF INPUTRC LANG LC_ALL LC_COLLATE LC_CTYPE LC_CTYPE LC_MESSAGES LC_NUMERIC LC_NUMERIC LINENO LINES LINES MACHTYPE MAIL MAILCHECK MAILPATH MAPFILE MAPFILE OLDPWD OPTARG OPTERR OPTIND OSTYPE PATH PIPESTATUS POSIXLY_CORRECT POSIXLY_CORRECT PPID PROMPT_COMMAND PS1 PS2 PS3 PS4 PWD RANDOM READLINE_LINE READLINE_LINE READLINE_POINT READLINE_POINT REPLY SECONDS SHELL SHELL SHELLOPTS SHLVL TIMEFORMAT TIMEOUT TMPDIR TMPDIR UID
334 syn keyword bashStatement chmod clear complete du egrep expr fgrep find gnufind gnugrep grep less ls mkdir mv rm rmdir rpm sed sleep sort strip tail
335 syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop
336 syn keyword bashStatement	command compgen
337endif
338
339if exists("b:is_kornshell") || exists("b:is_posix")
340 syn cluster shCommandSubList add=kshSpecialVariables,kshStatement
341 syn cluster shCaseList add=kshStatement
342 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
343 syn keyword kshStatement cat chmod clear cp du egrep expr fgrep find grep killall less ls mkdir mv nice printenv rm rmdir sed sort strip stty tail tput
344 syn keyword kshStatement command setgroups setsenv
345endif
346
347syn match   shSource	"^\.\s"
348syn match   shSource	"\s\.\s"
349"syn region  shColon	start="^\s*:" end="$" end="\s#"me=e-2 contains=@shColonList
350"syn region  shColon	start="^\s*\zs:" end="$" end="\s#"me=e-2
351if exists("b:is_kornshell") || exists("b:is_posix")
352 syn match   shColon	'^\s*\zs:'
353endif
354
355" String And Character Constants: {{{1
356"================================
357syn match   shNumber	"\<\d\+\>#\="
358syn match   shNumber	"\<-\=\.\=\d\+\>#\="
359syn match   shCtrlSeq	"\\\d\d\d\|\\[abcfnrtv0]"			contained
360if exists("b:is_bash")
361 syn match   shSpecial	"[^\\]\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]"	contained
362 syn match   shSpecial	"^\(\\\\\)*\zs\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]"	contained
363 syn region  shExSingleQuote	matchgroup=shQuote start=+\$'+ skip=+\\\\\|\\.+ end=+'+	contains=shStringSpecial,shSpecial		nextgroup=shSpecialNxt
364 syn region  shExDoubleQuote	matchgroup=shQuote start=+\$"+ skip=+\\\\\|\\.\|\\"+ end=+"+	contains=@shDblQuoteList,shStringSpecial,shSpecial	nextgroup=shSpecialNxt
365elseif !exists("g:sh_no_error")
366 syn region  shExSingleQuote	matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+	contains=shStringSpecial
367 syn region  shExDoubleQuote	matchGroup=Error start=+\$"+ skip=+\\\\\|\\.+ end=+"+	contains=shStringSpecial
368endif
369syn region  shSingleQuote	matchgroup=shQuote start=+'+ end=+'+		contains=@Spell	nextgroup=shSpecialStart,shSpecialSQ
370syn region  shDoubleQuote	matchgroup=shQuote start=+\%(\%(\\\\\)*\\\)\@<!"+ skip=+\\.+ end=+"+	contains=@shDblQuoteList,shStringSpecial,@Spell	nextgroup=shSpecialStart
371syn region  shDoubleQuote	matchgroup=shQuote start=+"+ matchgroup=shSpecial skip=+\\"+ matchgroup=shQuote end=+"+		contained	contains=@shDblQuoteList,shStringSpecial,@Spell	nextgroup=shSpecialStart
372syn match   shStringSpecial	"[^[:print:] \t]"			contained
373syn match   shStringSpecial	"[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]"			nextgroup=shComment
374syn match   shSpecialSQ	"[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]"		contained	nextgroup=shBkslshSnglQuote,@shNoZSList
375syn match   shSpecialDQ	"[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]"		contained	nextgroup=shBkslshDblQuote,@shNoZSList
376syn match   shSpecialStart	"\%(\\\\\)*\\[\\"'`$()#]"			contained	nextgroup=shBkslshSnglQuote,shBkslshDblQuote,@shNoZSList
377syn match   shSpecial	"^\%(\\\\\)*\\[\\"'`$()#]"
378syn match   shSpecialNoZS	contained	"\%(\\\\\)*\\[\\"'`$()#]"
379syn match   shSpecialNxt	contained	"\\[\\"'`$()#]"
380"syn region  shBkslshSnglQuote	contained	matchgroup=shQuote start=+'+ end=+'+	contains=@Spell	nextgroup=shSpecialStart
381"syn region  shBkslshDblQuote	contained	matchgroup=shQuote start=+"+ skip=+\\"+ end=+"+	contains=@shDblQuoteList,shStringSpecial,@Spell	nextgroup=shSpecialStart
382
383" Comments: {{{1
384"==========
385syn cluster	shCommentGroup	contains=shTodo,@Spell
386if exists("b:is_bash")
387 syn match	shTodo	contained		"\<\%(COMBAK\|FIXME\|TODO\|XXX\)\ze:\=\>"
388else
389 syn keyword	shTodo	contained		COMBAK FIXME TODO XXX
390endif
391syn match	shComment		"^\s*\zs#.*$"	contains=@shCommentGroup
392syn match	shComment		"\s\zs#.*$"	contains=@shCommentGroup
393syn match	shComment	contained	"#.*$"	contains=@shCommentGroup
394syn match	shQuickComment	contained	"#.*$"
395syn match	shBQComment	contained	"#.\{-}\ze`"	contains=@shCommentGroup
396
397" Here Documents: {{{1
398" =========================================
399"  Note : shHereDoc0[137] only had shDblQuoteList contained
400ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc01 start="<<\s*\\\=\z([^ \t|>]\+\)"		matchgroup=shHereDoc01 end="^\z1\s*$"	contains=@shDblQuoteList
401ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc02 start="<<\s*\"\z([^"]\+\)\""		matchgroup=shHereDoc02 end="^\z1\s*$"
402ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc03 start="<<-\s*\z([^ \t|>]\+\)"		matchgroup=shHereDoc03 end="^\s*\z1\s*$"	contains=@shDblQuoteList
403ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc04 start="<<-\s*'\z([^']\+\)'"		matchgroup=shHereDoc04 end="^\s*\z1\s*$"
404ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc05 start="<<\s*'\z([^']\+\)'"		matchgroup=shHereDoc05 end="^\z1\s*$"
405ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc06 start="<<-\s*\"\z([^"]\+\)\""		matchgroup=shHereDoc06 end="^\s*\z1\s*$"
406ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc07 start="<<\s*\\\_$\_s*\z([^ \t'"|>]\+\)"	matchgroup=shHereDoc07 end="^\z1\s*$"
407ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc08 start="<<\s*\\\_$\_s*'\z([^\t|>]\+\)'"	matchgroup=shHereDoc08 end="^\z1\s*$"
408ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc09 start="<<\s*\\\_$\_s*\"\z([^\t|>]\+\)\""	matchgroup=shHereDoc09 end="^\z1\s*$"
409ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc10 start="<<-\s*\\\_$\_s*\z([^ \t|>]\+\)"	matchgroup=shHereDoc10 end="^\s*\z1\s*$"
410ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc11 start="<<-\s*\\\_$\_s*\\\z([^ \t|>]\+\)"	matchgroup=shHereDoc11 end="^\s*\z1\s*$"        contains=@shDblQuoteList
411ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc12 start="<<-\s*\\\_$\_s*'\z([^']\+\)'"		matchgroup=shHereDoc12 end="^\s*\z1\s*$"
412ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc13 start="<<-\s*\\\_$\_s*\"\z([^"]\+\)\""	matchgroup=shHereDoc13 end="^\s*\z1\s*$"
413ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc14 start="<<\\\z([^ \t|>]\+\)"		matchgroup=shHereDoc14 end="^\z1\s*$"           contains=@shDblQuoteList
414ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc15 start="<<-\s*\\\z([^ \t|>]\+\)"		matchgroup=shHereDoc15 end="^\s*\z1\s*$"        contains=@shDblQuoteList
415ShFoldHereDoc syn region shHereDoc matchgroup=shHereDoc16 start="<<-\s*\\\z([^ \t|>]\+\)"		matchgroup=shHereDoc15 end="^\s*\z1\s*$"        contains=@shDblQuoteList
416
417" Here Strings: {{{1
418" =============
419" available for: bash; ksh (really should be ksh93 only) but not if its a posix
420if exists("b:is_bash") || (exists("b:is_kornshell") && !exists("b:is_posix"))
421 syn match shHereString "<<<"	skipwhite	nextgroup=shCmdParenRegion
422endif
423
424" Identifiers: {{{1
425"=============
426syn match  shSetOption	"\s\zs[-+][a-zA-Z0-9]\+\>"	contained
427syn match  shVariable	"\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze="	nextgroup=shVarAssign
428syn match  shVarAssign	"="		contained	nextgroup=shCmdParenRegion,shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote,shVar
429syn match  shVar	contained	"\h\w*"
430syn region shAtExpr	contained	start="@(" end=")" contains=@shIdList
431if exists("b:is_bash")
432 syn match  shSet "^\s*set\ze\s\+$"
433 syn region shSetList oneline matchgroup=shSet start="\<\%(declare\|local\|export\)\>\ze[/a-zA-Z_]\@!" end="$"	matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+#\|="	contains=@shIdList
434 syn region shSetList oneline matchgroup=shSet start="\<\%(set\|unset\)\>[/a-zA-Z_]\@!" end="\ze[;|#)]\|$"		matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+="	contains=@shIdList nextgroup=shComment
435elseif exists("b:is_kornshell") || exists("b:is_posix")
436 syn match  shSet "^\s*set\ze\s\+$"
437 if exists("b:is_dash")
438  syn region shSetList oneline matchgroup=shSet start="\<\%(local\)\>\ze[/]\@!" end="$"	                 matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]"	contains=@shIdList
439 endif
440 syn region shSetList oneline matchgroup=shSet start="\<\(export\)\>\ze[/]\@!" end="$"		matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]"	contains=@shIdList
441 syn region shSetList oneline matchgroup=shSet start="\<\%(set\|unset\>\)\ze[/a-zA-Z_]\@!" end="\ze[;|#)]\|$"		matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]"	contains=@shIdList nextgroup=shComment
442else
443 syn region shSetList oneline matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[/a-zA-Z_]\@!" end="\ze[;|#)]\|$"	matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]"	contains=@shIdList
444endif
445
446" Functions: {{{1
447if !exists("b:is_posix")
448 syn keyword shFunctionKey function	skipwhite skipnl nextgroup=shFunctionTwo
449endif
450
451if exists("b:is_bash")
452 ShFoldFunctions syn region shFunctionOne	matchgroup=shFunction start="^\s*[A-Za-z_0-9:][-a-zA-Z_0-9:]*\s*()\_s*{"		end="}"	contains=@shFunctionList		 skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
453 ShFoldFunctions syn region shFunctionTwo	matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_0-9:][-a-zA-Z_0-9:]*\>\s*\%(()\)\=\_s*{"	end="}"	contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
454 ShFoldFunctions syn region shFunctionThree	matchgroup=shFunction start="^\s*[A-Za-z_0-9:][-a-zA-Z_0-9:]*\s*()\_s*("		end=")"	contains=@shFunctionList		 skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
455 ShFoldFunctions syn region shFunctionFour	matchgroup=shFunction start="\%(do\)\@!\&\<[A-Za-z_0-9:][-a-zA-Z_0-9:]*\>\s*\%(()\)\=\_s*)"	end=")"	contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
456else
457 ShFoldFunctions syn region shFunctionOne	matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{"			end="}"	contains=@shFunctionList		 skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
458 ShFoldFunctions syn region shFunctionTwo	matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*{"		end="}"	contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
459 ShFoldFunctions syn region shFunctionThree	matchgroup=shFunction start="^\s*\h\w*\s*()\_s*("			end=")"	contains=@shFunctionList		 skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
460 ShFoldFunctions syn region shFunctionFour	matchgroup=shFunction start="\%(do\)\@!\&\<\h\w*\>\s*\%(()\)\=\_s*("		end=")"	contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
461endif
462
463" Parameter Dereferencing: {{{1
464" ========================
465if !exists("g:sh_no_error")
466 syn match  shDerefWordError	"[^}$[~]"	contained
467endif
468syn match  shDerefSimple	"\$\%(\h\w*\|\d\)"	nextgroup=@shNoZSList
469syn region shDeref	matchgroup=PreProc start="\${" end="}"	contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart
470syn match  shDerefSimple	"\$[-#*@!?]"	nextgroup=@shNoZSList
471syn match  shDerefSimple	"\$\$"	nextgroup=@shNoZSList
472syn match  shDerefSimple	"\${\d}"	nextgroup=@shNoZSList	nextgroup=shSpecialStart
473if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix")
474 syn region shDeref	matchgroup=PreProc start="\${##\=" end="}"	contains=@shDerefList	nextgroup=@shSpecialNoZS,shSpecialStart
475 syn region shDeref	matchgroup=PreProc start="\${\$\$" end="}"	contains=@shDerefList	nextgroup=@shSpecialNoZS,shSpecialStart
476endif
477
478" ksh: ${!var[*]} array index list syntax: {{{1
479" ========================================
480if exists("b:is_kornshell") || exists("b:is_posix")
481 syn region shDeref	matchgroup=PreProc start="\${!" end="}"	contains=@shDerefVarArray
482endif
483
484" bash: ${!prefix*} and ${#parameter}: {{{1
485" ====================================
486if exists("b:is_bash")
487 syn region shDeref	matchgroup=PreProc start="\${!" end="\*\=}"	contains=@shDerefList,shDerefOffset
488 syn match  shDerefVar	contained	"{\@<=!\h\w*"		nextgroup=@shDerefVarList
489endif
490if exists("b:is_kornshell")
491 syn match  shDerefVar	contained	"{\@<=!\h\w*[[:alnum:]_.]*"	nextgroup=@shDerefVarList
492endif
493
494syn match  shDerefSpecial	contained	"{\@<=[-*@?0]"		nextgroup=shDerefOp,shDerefOffset,shDerefOpError
495syn match  shDerefSpecial	contained	"\({[#!]\)\@<=[[:alnum:]*@_]\+"	nextgroup=@shDerefVarList,shDerefOp
496syn match  shDerefVar	contained	"{\@<=\h\w*"		nextgroup=@shDerefVarList
497syn match  shDerefVar	contained	'\d'                            nextgroup=@shDerefVarList
498if exists("b:is_kornshell") || exists("b:is_posix")
499  syn match  shDerefVar	contained	"{\@<=\h\w*[[:alnum:]_.]*"	nextgroup=@shDerefVarList
500endif
501
502" sh ksh bash : ${var[... ]...}  array reference: {{{1
503syn region  shDerefVarArray   contained	matchgroup=shDeref start="\[" end="]"	contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError
504
505" Special ${parameter OPERATOR word} handling: {{{1
506" sh ksh bash : ${parameter:-word}    word is default value
507" sh ksh bash : ${parameter:=word}    assign word as default value
508" sh ksh bash : ${parameter:?word}    display word if parameter is null
509" sh ksh bash : ${parameter:+word}    use word if parameter is not null, otherwise nothing
510"    ksh bash : ${parameter#pattern}  remove small left  pattern
511"    ksh bash : ${parameter##pattern} remove large left  pattern
512"    ksh bash : ${parameter%pattern}  remove small right pattern
513"    ksh bash : ${parameter%%pattern} remove large right pattern
514"        bash : ${parameter^pattern}  Case modification
515"        bash : ${parameter^^pattern} Case modification
516"        bash : ${parameter,pattern}  Case modification
517"        bash : ${parameter,,pattern} Case modification
518"        bash : ${@:start:qty}        display command line arguments from start to start+qty-1 (inferred)
519syn cluster shDerefPatternList	contains=shDerefPattern,shDerefString
520if !exists("g:sh_no_error")
521 syn match shDerefOpError	contained	":[[:punct:]]"
522endif
523syn match  shDerefOp	contained	":\=[-=?]"	nextgroup=@shDerefPatternList
524syn match  shDerefOp	contained	":\=+"	nextgroup=@shDerefPatternList
525if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix")
526 syn match  shDerefOp	contained	"#\{1,2}"		nextgroup=@shDerefPatternList
527 syn match  shDerefOp	contained	"%\{1,2}"		nextgroup=@shDerefPatternList
528 syn match  shDerefPattern	contained	"[^{}]\+"		contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern
529 syn region shDerefPattern	contained	start="{" end="}"	contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern
530 syn match  shDerefEscape	contained	'\%(\\\\\)*\\.'
531endif
532if exists("b:is_bash")
533 syn match  shDerefOp	contained	"[,^]\{1,2}"	nextgroup=@shDerefPatternList
534endif
535syn region shDerefString	contained	matchgroup=shDerefDelim start=+\%(\\\)\@<!'+ end=+'+	contains=shStringSpecial
536syn region shDerefString	contained	matchgroup=shDerefDelim start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+	contains=@shDblQuoteList,shStringSpecial
537syn match  shDerefString	contained	"\\["']"	nextgroup=shDerefPattern
538
539if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix")
540 " bash ksh posix : ${parameter:offset}
541 " bash ksh posix : ${parameter:offset:length}
542 syn region shDerefOffset	contained	start=':[^-=?+]' end='\ze:'	end='\ze}'	contains=shDeref,shDerefSimple,shDerefEscape	nextgroup=shDerefLen,shDeref,shDerefSimple
543 syn region shDerefOffset	contained	start=':\s-'	end='\ze:'	end='\ze}'	contains=shDeref,shDerefSimple,shDerefEscape	nextgroup=shDerefLen,shDeref,shDerefSimple
544 syn match  shDerefLen	contained	":[^}]\+"	contains=shDeref,shDerefSimple,shArithmetic
545endif
546
547if exists("b:is_bash")
548 " bash : ${parameter//pattern/string}
549 " bash : ${parameter//pattern}
550 syn match  shDerefPPS	contained	'/\{1,2}'	nextgroup=shDerefPPSleft
551 syn region shDerefPPSleft	contained	start='.'	skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp	end='/' end='\ze}' end='"'	nextgroup=shDerefPPSright	contains=@shPPSLeftList
552 syn region shDerefPPSright	contained	start='.'	skip=@\%(\\\\\)\+@		end='\ze}'				contains=@shPPSRightList
553
554 " bash : ${parameter/#substring/replacement}
555 syn match  shDerefPSR	contained	'/#'	nextgroup=shDerefPSRleft,shDoubleQuote,shSingleQuote
556 syn region shDerefPSRleft	contained	start='[^"']'	skip=@\%(\\\\\)*\\/@ matchgroup=shDerefOp	end='/' end='\ze}'	nextgroup=shDerefPSRright
557 syn region shDerefPSRright	contained	start='.'	skip=@\%(\\\\\)\+@		end='\ze}'
558endif
559
560" Arithmetic Parenthesized Expressions: {{{1
561"syn region shParen matchgroup=shArithRegion start='[^$]\zs(\%(\ze[^(]\|$\)' end=')' contains=@shArithParenList
562syn region shParen matchgroup=shArithRegion start='\$\@!(\%(\ze[^(]\|$\)' end=')' contains=@shArithParenList
563
564" Additional sh Keywords: {{{1
565" ===================
566syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait
567syn keyword shConditional contained elif else then
568if !exists("g:sh_no_error")
569 syn keyword shCondError elif else then
570endif
571
572" Additional ksh Keywords and Aliases: {{{1
573" ===================================
574if exists("b:is_kornshell") || exists("b:is_posix")
575 syn keyword shStatement bg builtin disown enum export false fg getconf getopts hist jobs let printf sleep true unalias whence
576 syn keyword shStatement typeset skipwhite nextgroup=shSetOption
577 syn keyword shStatement autoload compound fc float functions hash history integer nameref nohup r redirect source stop suspend times type
578 if exists("b:is_posix")
579  syn keyword shStatement command
580 else
581  syn keyword shStatement time
582 endif
583
584" Additional bash Keywords: {{{1
585" =====================
586elseif exists("b:is_bash")
587 syn keyword shStatement bg builtin disown export false fg getopts jobs let printf sleep true unalias
588 syn keyword shStatement typeset nextgroup=shSetOption
589 syn keyword shStatement fc hash history source suspend times type
590 syn keyword shStatement bind builtin caller compopt declare dirs disown enable export help logout mapfile popd pushd readarray shopt source typeset
591else
592 syn keyword shStatement login newgrp
593endif
594
595" Synchronization: {{{1
596" ================
597if !exists("g:sh_minlines")
598 let s:sh_minlines = 200
599else
600 let s:sh_minlines= g:sh_minlines
601endif
602if !exists("g:sh_maxlines")
603 let s:sh_maxlines = 2*s:sh_minlines
604 if s:sh_maxlines < 25
605  let s:sh_maxlines= 25
606 endif
607else
608 let s:sh_maxlines= g:sh_maxlines
609endif
610exec "syn sync minlines=" . s:sh_minlines . " maxlines=" . s:sh_maxlines
611syn sync match shCaseEsacSync	grouphere	shCaseEsac	"\<case\>"
612syn sync match shCaseEsacSync	groupthere	shCaseEsac	"\<esac\>"
613syn sync match shDoSync	grouphere	shDo	"\<do\>"
614syn sync match shDoSync	groupthere	shDo	"\<done\>"
615syn sync match shForSync	grouphere	shFor	"\<for\>"
616syn sync match shForSync	groupthere	shFor	"\<in\>"
617syn sync match shIfSync	grouphere	shIf	"\<if\>"
618syn sync match shIfSync	groupthere	shIf	"\<fi\>"
619syn sync match shUntilSync	grouphere	shRepeat	"\<until\>"
620syn sync match shWhileSync	grouphere	shRepeat	"\<while\>"
621
622" Default Highlighting: {{{1
623" =====================
624if !exists("skip_sh_syntax_inits")
625 hi def link shArithRegion	shShellVariables
626 hi def link shAstQuote	shDoubleQuote
627 hi def link shAtExpr	shSetList
628 hi def link shBkslshSnglQuote	shSingleQuote
629 hi def link shBkslshDblQuote	shDOubleQuote
630 hi def link shBeginHere	shRedir
631 hi def link shCaseBar	shConditional
632 hi def link shCaseCommandSub	shCommandSub
633 hi def link shCaseDoubleQuote	shDoubleQuote
634 hi def link shCaseIn	shConditional
635 hi def link shQuote	shOperator
636 hi def link shCaseSingleQuote	shSingleQuote
637 hi def link shCaseStart	shConditional
638 hi def link shCmdSubRegion	shShellVariables
639 hi def link shColon	shComment
640 hi def link shDerefOp	shOperator
641 hi def link shDerefPOL	shDerefOp
642 hi def link shDerefPPS	shDerefOp
643 hi def link shDerefPSR	shDerefOp
644 hi def link shDeref	shShellVariables
645 hi def link shDerefDelim	shOperator
646 hi def link shDerefSimple	shDeref
647 hi def link shDerefSpecial	shDeref
648 hi def link shDerefString	shDoubleQuote
649 hi def link shDerefVar	shDeref
650 hi def link shDoubleQuote	shString
651 hi def link shEcho	shString
652 hi def link shEchoDelim	shOperator
653 hi def link shEchoQuote	shString
654 hi def link shForPP	shLoop
655 hi def link shFunction	Function
656 hi def link shEmbeddedEcho	shString
657 hi def link shEscape	shCommandSub
658 hi def link shExDoubleQuote	shDoubleQuote
659 hi def link shExSingleQuote	shSingleQuote
660 hi def link shHereDoc	shString
661 hi def link shHereString	shRedir
662 hi def link shHerePayload	shHereDoc
663 hi def link shLoop	shStatement
664 hi def link shSpecialNxt	shSpecial
665 hi def link shNoQuote	shDoubleQuote
666 hi def link shOption	shCommandSub
667 hi def link shPattern	shString
668 hi def link shParen	shArithmetic
669 hi def link shPosnParm	shShellVariables
670 hi def link shQuickComment	shComment
671 hi def link shBQComment	shComment
672 hi def link shRange	shOperator
673 hi def link shRedir	shOperator
674 hi def link shSetListDelim	shOperator
675 hi def link shSetOption	shOption
676 hi def link shSingleQuote	shString
677 hi def link shSource	shOperator
678 hi def link shStringSpecial	shSpecial
679 hi def link shSpecialStart	shSpecial
680 hi def link shSubShRegion	shOperator
681 hi def link shTestOpr	shConditional
682 hi def link shTestPattern	shString
683 hi def link shTestDoubleQuote	shString
684 hi def link shTestSingleQuote	shString
685 hi def link shTouchCmd	shStatement
686 hi def link shVariable	shSetList
687 hi def link shWrapLineOperator	shOperator
688
689 if exists("b:is_bash")
690   hi def link bashAdminStatement	shStatement
691   hi def link bashSpecialVariables	shShellVariables
692   hi def link bashStatement		shStatement
693   hi def link shCharClass		shSpecial
694   hi def link shDerefOffset		shDerefOp
695   hi def link shDerefLen		shDerefOffset
696 endif
697 if exists("b:is_kornshell") || exists("b:is_posix")
698   hi def link kshSpecialVariables	shShellVariables
699   hi def link kshStatement		shStatement
700 endif
701
702 if !exists("g:sh_no_error")
703  hi def link shCaseError		Error
704  hi def link shCondError		Error
705  hi def link shCurlyError		Error
706  hi def link shDerefOpError		Error
707  hi def link shDerefWordError		Error
708  hi def link shDoError		Error
709  hi def link shEsacError		Error
710  hi def link shIfError		Error
711  hi def link shInError		Error
712  hi def link shParenError		Error
713  hi def link shTestError		Error
714  if exists("b:is_kornshell") || exists("b:is_posix")
715    hi def link shDTestError		Error
716  endif
717 endif
718
719 hi def link shArithmetic		Special
720 hi def link shCharClass		Identifier
721 hi def link shSnglCase		Statement
722 hi def link shCommandSub		Special
723 hi def link shCommandSubBQ		shCommandSub
724 hi def link shComment		Comment
725 hi def link shConditional		Conditional
726 hi def link shCtrlSeq		Special
727 hi def link shExprRegion		Delimiter
728 hi def link shFunctionKey		Function
729 hi def link shFunctionName		Function
730 hi def link shNumber		Number
731 hi def link shOperator		Operator
732 hi def link shRepeat		Repeat
733 hi def link shSet		Statement
734 hi def link shSetList		Identifier
735 hi def link shShellVariables		PreProc
736 hi def link shSpecial		Special
737 hi def link shSpecialDQ		Special
738 hi def link shSpecialSQ		Special
739 hi def link shSpecialNoZS		shSpecial
740 hi def link shStatement		Statement
741 hi def link shString		String
742 hi def link shTodo		Todo
743 hi def link shAlias		Identifier
744 hi def link shHereDoc01		shRedir
745 hi def link shHereDoc02		shRedir
746 hi def link shHereDoc03		shRedir
747 hi def link shHereDoc04		shRedir
748 hi def link shHereDoc05		shRedir
749 hi def link shHereDoc06		shRedir
750 hi def link shHereDoc07		shRedir
751 hi def link shHereDoc08		shRedir
752 hi def link shHereDoc09		shRedir
753 hi def link shHereDoc10		shRedir
754 hi def link shHereDoc11		shRedir
755 hi def link shHereDoc12		shRedir
756 hi def link shHereDoc13		shRedir
757 hi def link shHereDoc14		shRedir
758 hi def link shHereDoc15		shRedir
759endif
760
761" Delete shell folding commands {{{1
762" =============================
763delc ShFoldFunctions
764delc ShFoldHereDoc
765delc ShFoldIfDoFor
766
767" Set Current Syntax: {{{1
768" ===================
769if exists("b:is_bash")
770 let b:current_syntax = "bash"
771elseif exists("b:is_kornshell")
772 let b:current_syntax = "ksh"
773elseif exists("b:is_posix")
774 let b:current_syntax = "posix"
775else
776 let b:current_syntax = "sh"
777endif
778
779" vim: ts=16 fdm=marker
780