Update runtime files
[MacVim.git] / runtime / syntax / sh.vim
blob5ae09804740b1742d85bb075a4de471f8b1a7440
1 " Vim syntax file
2 " Language:             shell (sh) Korn shell (ksh) bash (sh)
3 " Maintainer:           Dr. Charles E. Campbell, Jr.  <NdrOchipS@PcampbellAfamily.Mbiz>
4 " Previous Maintainer:  Lennart Schultz <Lennart.Schultz@ecmwf.int>
5 " Last Change:          Sep 01, 2009
6 " Version:              109
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
13 if version < 600
14   syntax clear
15 elseif exists("b:current_syntax")
16   finish
17 endif
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.
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
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
43 endif
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"
51 endif
52 if !exists("s:sh_fold_functions")
53  let s:sh_fold_functions = 1
54 endif
55 if !exists("s:sh_fold_heredoc")
56  let s:sh_fold_heredoc   = 2
57 endif
58 if !exists("s:sh_fold_ifdofor")
59  let s:sh_fold_ifdofor   = 4
60 endif
61 if g:sh_fold_enabled && &fdm == "manual"
62  set fdm=syntax
63 endif
65 " sh syntax is case sensitive {{{1
66 syn case match
68 " Clusters: contains=@... clusters {{{1
69 "==================================
70 syn cluster shErrorList contains=shDoError,shIfError,shInError,shCaseError,shEsacError,shCurlyError,shParenError,shTestError,shOK
71 if exists("b:is_kornshell")
72  syn cluster ErrorList add=shDTestError
73 endif
74 syn cluster shArithParenList    contains=shArithmetic,shDeref,shDerefSimple,shEcho,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement
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,shExpr
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,shOption,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
91 endif
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=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator
98 syn cluster shTestList  contains=shCharClass,shComment,shCommandSub,shDeref,shDerefSimple,shDoubleQuote,shExpr,shExpr,shNumber,shOperator,shExSingleQuote,shSingleQuote,shTestOpr,shTest,shCtrlSeq
101 " Echo: {{{1
102 " ====
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="\s#"me=e-2 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="\s#"me=e-2 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="\s#"me=e-2 contains=shNumber,shExSingleQuote,shSingleQuote,shDeref,shDerefSimple,shSpecialVar,shOperator,shDoubleQuote,shCharClass,shCtrlSeq
111 " Alias: {{{1
112 " =====
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="="
117 endif
119 " Error Codes: {{{1
120 " ============
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 syn match   shOK        '\.\(done\|fi\|in\|esac\)'
129 if exists("b:is_kornshell")
130  syn match     shDTestError "]]"
131 endif
132 syn match     shTestError "]"
134 " Options: {{{1
135 " ====================
136 syn match   shOption    "\s\zs[-+][a-zA-Z0-9]\+\>"
137 syn match   shOption    "\s\zs--[^ \t$`'"|]\+"
139 " File Redirection Highlighted As Operators: {{{1
140 "===========================================
141 syn match      shRedir  "\d\=>\(&[-0-9]\)\="
142 syn match      shRedir  "\d\=>>-\="
143 syn match      shRedir  "\d\=<\(&[-0-9]\)\="
144 syn match      shRedir  "\d<<-\="
146 " Operators: {{{1
147 " ==========
148 syn match   shOperator  "<<\|>>"                contained
149 syn match   shOperator  "[!&;|]"                contained
150 syn match   shOperator  "\[[[^:]\|\]]"          contained
151 syn match   shOperator  "!\=="          skipwhite nextgroup=shPattern
152 syn match   shPattern   "\<\S\+\())\)\@="       contained contains=shExSingleQuote,shSingleQuote,shDoubleQuote,shDeref
154 " Subshells: {{{1
155 " ==========
156 syn region shExpr  transparent matchgroup=shExprRegion  start="{" end="}"       contains=@shExprList2 nextgroup=shMoreSpecial
157 syn region shSubSh transparent matchgroup=shSubShRegion start="(" end=")"       contains=@shSubShList nextgroup=shMoreSpecial
159 " Tests: {{{1
160 "=======
161 syn region shExpr       matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList,shSpecial
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
172 endif
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
179 " ======
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\_s" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>"   contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
183  syn region shFor       fold matchgroup=shLoop start="\<for\_s" end="\<in\_s" end="\<do\>"me=e-2        contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
184 else
185  syn region shDo        transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
186  syn region shIf        transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>"   contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
187  syn region shFor       matchgroup=shLoop start="\<for\_s" end="\<in\>" end="\<do\>"me=e-2      contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
188 endif
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\_s" end="\<in\_s" end="\<do\>"me=e-2  contains=@shLoopList,shDblParen,shDblBrace
193  syn region shRepeat   matchgroup=shLoop   start="\<until\_s" end="\<in\_s" end="\<do\>"me=e-2  contains=@shLoopList,shDblParen,shDblBrace
194  syn region shCaseEsac matchgroup=shConditional start="\<select\s" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList
195 else
196  syn region shRepeat   matchgroup=shLoop   start="\<while\_s" end="\<do\>"me=e-2                contains=@shLoopList
197  syn region shRepeat   matchgroup=shLoop   start="\<until\_s" end="\<do\>"me=e-2                contains=@shLoopList
198 endif
199 syn region shCurlyIn   contained        matchgroup=Delimiter start="{" end="}" contains=@shCurlyList
200 syn match  shComma     contained        ","
202 " Case: case...esac {{{1
203 " ====
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 if (g:sh_fold_enabled % (s:sh_fold_ifdofor * 2))/s:sh_fold_ifdofor
207  syn region  shCase     fold contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)"  end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment
208  syn region  shCaseEsac fold matchgroup=shConditional start="\<case\>" end="\<esac\>"   contains=@shCaseEsacList
209 else
210  syn region  shCase     contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)"  end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment
211  syn region  shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>"        contains=@shCaseEsacList
212 endif
213 syn keyword shCaseIn    contained skipwhite skipnl in                   nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
214 if exists("b:is_bash")
215  syn region  shCaseExSingleQuote        matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+      contains=shStringSpecial,shSpecial      skipwhite skipnl nextgroup=shCaseBar    contained
216 else
217  syn region  shCaseExSingleQuote        matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+   contains=shStringSpecial        skipwhite skipnl nextgroup=shCaseBar    contained
218 endif
219 syn region  shCaseSingleQuote   matchgroup=shOperator start=+'+ end=+'+         contains=shStringSpecial                skipwhite skipnl nextgroup=shCaseBar    contained
220 syn region  shCaseDoubleQuote   matchgroup=shOperator start=+"+ skip=+\\\\\|\\.+ end=+"+        contains=@shDblQuoteList,shStringSpecial        skipwhite skipnl nextgroup=shCaseBar    contained
221 syn region  shCaseCommandSub    start=+`+ skip=+\\\\\|\\.+ end=+`+              contains=@shCommandSubList              skipwhite skipnl nextgroup=shCaseBar    contained
223 " Misc: {{{1
224 "======
225 syn match   shWrapLineOperator "\\$"
226 syn region  shCommandSub   start="`" skip="\\\\\|\\." end="`" contains=@shCommandSubList
227 syn match   shEscape    contained       '\\.'
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!
235 if 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\+"
239 else
240  syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList
241 endif
243 if 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
249 endif
251 if 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
256 endif
258 syn match   shSource    "^\.\s"
259 syn match   shSource    "\s\.\s"
260 syn region  shColon     start="^\s*:" end="$\|" end="\s#"me=e-2 contains=@shColonList
262 " String And Character Constants: {{{1
263 "================================
264 syn match   shNumber    "-\=\<\d\+\>#\="
265 syn match   shCtrlSeq   "\\\d\d\d\|\\[abcfnrtv0]"               contained
266 if exists("b:is_bash")
267  syn match   shSpecial  "\\\o\o\o\|\\x\x\x\|\\c.\|\\[abefnrtv]" contained
268 endif
269 if exists("b:is_bash")
270  syn region  shExSingleQuote    matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+      contains=shStringSpecial,shSpecial
271 else
272  syn region  shExSingleQuote    matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+   contains=shStringSpecial
273 endif
274 syn region  shSingleQuote       matchgroup=shOperator start=+'+ end=+'+         contains=shStringSpecial,@Spell
275 syn region  shDoubleQuote       matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+      contains=@shDblQuoteList,shStringSpecial,@Spell
276 syn match   shStringSpecial     "[^[:print:] \t]"       contained
277 syn match   shStringSpecial     "\%(\\\\\)*\\[\\"'`$()#]"
278 syn match   shSpecial   "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial
279 syn match   shSpecial   "^\%(\\\\\)*\\[\\"'`$()#]"
280 syn match   shMoreSpecial       "\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial contained
282 " Comments: {{{1
283 "==========
284 syn cluster    shCommentGroup   contains=shTodo,@Spell
285 syn keyword    shTodo   contained       COMBAK FIXME TODO XXX
286 syn match      shComment        "^\s*\zs#.*$"   contains=@shCommentGroup
287 syn match      shComment        "\s\zs#.*$"     contains=@shCommentGroup
288 syn match      shQuickComment   contained       "#.*$"
290 " Here Documents: {{{1
291 " =========================================
292 if version < 600
293  syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**"  matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
294  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
295  syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir      end="^EOF$"     contains=@shDblQuoteList
296  syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir     end="^\s*EOF$"  contains=@shDblQuoteList
297  syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**"  matchgroup=shRedir      end="^\.$"      contains=@shDblQuoteList
298  syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir      end="^\s*\.$"   contains=@shDblQuoteList
300 elseif (g:sh_fold_enabled % (s:sh_fold_heredoc * 2))/s:sh_fold_heredoc
301  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)"             matchgroup=shRedir end="^\z1\s*$"       contains=@shDblQuoteList
302  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\"\z(\S*\)\""         matchgroup=shRedir end="^\z1\s*$"
303  syn region shHereDoc matchgroup=shRedir fold start="<<\s*'\z(\S*\)'"           matchgroup=shRedir end="^\z1\s*$"
304  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)"            matchgroup=shRedir end="^\s*\z1\s*$"    contains=@shDblQuoteList
305  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\"\z(\S*\)\""                matchgroup=shRedir end="^\s*\z1\s*$"
306  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*'\z(\S*\)'"          matchgroup=shRedir end="^\s*\z1\s*$"
307  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\z(\S*\)"            matchgroup=shRedir end="^\z1\s*$"
308  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\"\z(\S*\)\""        matchgroup=shRedir end="^\z1\s*$"
309  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*'\z(\S*\)'"         matchgroup=shRedir end="^\s*\z1\s*$"
310  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\z(\S*\)"           matchgroup=shRedir end="^\s*\z1\s*$"
311  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\"\z(\S*\)\""       matchgroup=shRedir end="^\s*\z1\s*$"
312  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'"          matchgroup=shRedir end="^\z1\s*$"
313  syn region shHereDoc matchgroup=shRedir fold start="<<\\\z(\S*\)"              matchgroup=shRedir end="^\z1\s*$"
315 else
316  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)"      matchgroup=shRedir end="^\z1\s*$"    contains=@shDblQuoteList
317  syn region shHereDoc matchgroup=shRedir start="<<\s*\"\z(\S*\)\""      matchgroup=shRedir end="^\z1\s*$"
318  syn region shHereDoc matchgroup=shRedir start="<<-\s*\z(\S*\)"         matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList
319  syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'"       matchgroup=shRedir end="^\s*\z1\s*$"
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*$"
322  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
323  syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\z(\S*\)"        matchgroup=shRedir end="^\s*\z1\s*$"
324  syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*'\z(\S*\)'"      matchgroup=shRedir end="^\s*\z1\s*$"
325  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*'\z(\S*\)'"       matchgroup=shRedir end="^\z1\s*$"
326  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\""     matchgroup=shRedir end="^\z1\s*$"
327  syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\""    matchgroup=shRedir end="^\s*\z1\s*$"
328  syn region shHereDoc matchgroup=shRedir start="<<\\\z(\S*\)"           matchgroup=shRedir end="^\z1\s*$"
329 endif
331 " Here Strings: {{{1
332 " =============
333 if exists("b:is_bash")
334  syn match shRedir "<<<"
335 endif
337 " Identifiers: {{{1
338 "=============
339 syn match  shSetOption  "\s\zs[-+][a-zA-Z0-9]\+\>"      contained
340 syn match  shVariable   "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze="     nextgroup=shSetIdentifier
341 syn match  shSetIdentifier      "="             contained       nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shSingleQuote,shExSingleQuote
342 if exists("b:is_bash")
343  syn region shSetList oneline matchgroup=shSet start="\<\(declare\|typeset\|local\|export\|unset\)\>\ze[^/]" end="$"    matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+#\|=" contains=@shIdList
344  syn region shSetList oneline matchgroup=shSet start="\<set\>\ze[^/]" end="\ze[;|)]\|$"                 matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList
345 elseif exists("b:is_kornshell")
346  syn region shSetList oneline matchgroup=shSet start="\<\(typeset\|export\|unset\)\>\ze[^/]" end="$"            matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList
347  syn region shSetList oneline matchgroup=shSet start="\<set\>\ze[^/]" end="$"                           matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList
348 else
349  syn region shSetList oneline matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[^/]" end="$"                matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList
350 endif
352 " Functions: {{{1
353 if !exists("g:is_posix")
354  syn keyword shFunctionKey function     skipwhite skipnl nextgroup=shFunctionTwo
355 endif
357 if exists("b:is_bash")
358  if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions
359   syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}"    contains=@shFunctionList                        skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
360   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
361  else
362   syn region shFunctionOne      matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{"    end="}" contains=@shFunctionList
363   syn region shFunctionTwo      matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
364  endif
365 else
366  if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions
367   syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}"       contains=@shFunctionList                        skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
368   syn region shFunctionTwo fold matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{"    end="}" contains=shFunctionKey,@shFunctionList contained        skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
369  else
370   syn region shFunctionOne      matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{"       end="}" contains=@shFunctionList
371   syn region shFunctionTwo      matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{"    end="}" contains=shFunctionKey,@shFunctionList contained
372  endif
373 endif
375 " Parameter Dereferencing: {{{1
376 " ========================
377 syn match  shDerefSimple        "\$\%(\h\w*\|\d\)"
378 syn region shDeref      matchgroup=PreProc start="\${" end="}"  contains=@shDerefList,shDerefVarArray
379 syn match  shDerefWordError     "[^}$[]"        contained
380 syn match  shDerefSimple        "\$[-#*@!?]"
381 syn match  shDerefSimple        "\$\$"
382 if exists("b:is_bash") || exists("b:is_kornshell")
383  syn region shDeref     matchgroup=PreProc start="\${##\=" end="}"      contains=@shDerefList
384  syn region shDeref     matchgroup=PreProc start="\${\$\$" end="}"      contains=@shDerefList
385 endif
387 " bash: ${!prefix*} and ${#parameter}: {{{1
388 " ====================================
389 if exists("b:is_bash")
390  syn region shDeref     matchgroup=PreProc start="\${!" end="\*\=}"     contains=@shDerefList,shDerefOp
391  syn match  shDerefVar  contained       "{\@<=!\w\+"            nextgroup=@shDerefVarList
392 endif
394 syn match  shDerefSpecial       contained       "{\@<=[-*@?0]"          nextgroup=shDerefOp,shDerefOpError
395 syn match  shDerefSpecial       contained       "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp
396 syn match  shDerefVar   contained       "{\@<=\w\+"             nextgroup=@shDerefVarList
398 " sh ksh bash : ${var[... ]...}  array reference: {{{1
399 syn region  shDerefVarArray   contained matchgroup=shDeref start="\[" end="]"   contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError
401 " Special ${parameter OPERATOR word} handling: {{{1
402 " sh ksh bash : ${parameter:-word}    word is default value
403 " sh ksh bash : ${parameter:=word}    assign word as default value
404 " sh ksh bash : ${parameter:?word}    display word if parameter is null
405 " sh ksh bash : ${parameter:+word}    use word if parameter is not null, otherwise nothing
406 "    ksh bash : ${parameter#pattern}  remove small left  pattern
407 "    ksh bash : ${parameter##pattern} remove large left  pattern
408 "    ksh bash : ${parameter%pattern}  remove small right pattern
409 "    ksh bash : ${parameter%%pattern} remove large right pattern
410 syn cluster shDerefPatternList  contains=shDerefPattern,shDerefString
411 syn match shDerefOpError        contained       ":[[:punct:]]"
412 syn match  shDerefOp    contained       ":\=[-=?]"      nextgroup=@shDerefPatternList
413 syn match  shDerefOp    contained       ":\=+"  nextgroup=@shDerefPatternList
414 if exists("b:is_bash") || exists("b:is_kornshell")
415  syn match  shDerefOp   contained       "#\{1,2}"       nextgroup=@shDerefPatternList
416  syn match  shDerefOp   contained       "%\{1,2}"       nextgroup=@shDerefPatternList
417  syn match  shDerefPattern      contained       "[^{}]\+"       contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern
418  syn region shDerefPattern      contained       start="{" end="}"       contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern
419  syn match  shDerefEscape       contained       '\%(\\\\\)*\\.'
420 endif
421 syn region shDerefString        contained       matchgroup=shOperator start=+\%(\\\)\@<!'+ end=+'+              contains=shStringSpecial
422 syn region shDerefString        contained       matchgroup=shOperator start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+   contains=@shDblQuoteList,shStringSpecial
423 syn match  shDerefString        contained       "\\["']"        nextgroup=shDerefPattern
425 if exists("b:is_bash")
426  " bash : ${parameter:offset}
427  " bash : ${parameter:offset:length}
428  syn region shDerefOp   contained       start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL
429  syn match  shDerefPOL  contained       ":[^}]\+"       contains=@shCommandSubList
431  " bash : ${parameter//pattern/string}
432  " bash : ${parameter//pattern}
433  syn match  shDerefPPS  contained       '/\{1,2}'       nextgroup=shDerefPPSleft
434  syn region shDerefPPSleft      contained       start='.'       skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList
435  syn region shDerefPPSright     contained       start='.'       end='\ze}'      contains=@shCommandSubList
436 endif
438 " Arithmetic Parenthesized Expressions: {{{1
439 syn region shParen matchgroup=shArithRegion start='(\ze[^(]' end=')' contains=@shArithParenList
441 " Useful sh Keywords: {{{1
442 " ===================
443 syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait
444 syn keyword shConditional contained elif else then
445 syn keyword shCondError elif else then
447 " Useful ksh Keywords: {{{1
448 " ====================
449 if exists("b:is_kornshell") || exists("b:is_bash")
450  syn keyword shStatement autoload bg false fc fg functions getopts hash history integer jobs let nohup print printf r stop suspend times true type unalias whence
451  if exists("g:is_posix")
452   syn keyword shStatement command
453  else
454   syn keyword shStatement time
455  endif
457 " Useful bash Keywords: {{{1
458 " =====================
459  if exists("b:is_bash")
460   syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source
461  else
462   syn keyword shStatement login newgrp
463  endif
464 endif
466 " Synchronization: {{{1
467 " ================
468 if !exists("sh_minlines")
469   let sh_minlines = 200
470 endif
471 if !exists("sh_maxlines")
472   let sh_maxlines = 2 * sh_minlines
473 endif
474 exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines
475 syn sync match shCaseEsacSync   grouphere       shCaseEsac      "\<case\>"
476 syn sync match shCaseEsacSync   groupthere      shCaseEsac      "\<esac\>"
477 syn sync match shDoSync grouphere       shDo    "\<do\>"
478 syn sync match shDoSync groupthere      shDo    "\<done\>"
479 syn sync match shForSync        grouphere       shFor   "\<for\>"
480 syn sync match shForSync        groupthere      shFor   "\<in\>"
481 syn sync match shIfSync grouphere       shIf    "\<if\>"
482 syn sync match shIfSync groupthere      shIf    "\<fi\>"
483 syn sync match shUntilSync      grouphere       shRepeat        "\<until\>"
484 syn sync match shWhileSync      grouphere       shRepeat        "\<while\>"
486 " Default Highlighting: {{{1
487 " =====================
488 hi def link shArithRegion       shShellVariables
489 hi def link shBeginHere shRedir
490 hi def link shCaseBar   shConditional
491 hi def link shCaseCommandSub    shCommandSub
492 hi def link shCaseDoubleQuote   shDoubleQuote
493 hi def link shCaseIn    shConditional
494 hi def link shCaseSingleQuote   shSingleQuote
495 hi def link shCaseStart shConditional
496 hi def link shCmdSubRegion      shShellVariables
497 hi def link shColon     shStatement
498 hi def link shDerefOp   shOperator
499 hi def link shDerefPOL  shDerefOp
500 hi def link shDerefPPS  shDerefOp
501 hi def link shDeref     shShellVariables
502 hi def link shDerefSimple       shDeref
503 hi def link shDerefSpecial      shDeref
504 hi def link shDerefString       shDoubleQuote
505 hi def link shDerefVar  shDeref
506 hi def link shDoubleQuote       shString
507 hi def link shEcho      shString
508 hi def link shEchoQuote shString
509 hi def link shEmbeddedEcho      shString
510 hi def link shEscape    shCommandSub
511 hi def link shExSingleQuote     shSingleQuote
512 hi def link shFunction  Function
513 hi def link shHereDoc   shString
514 hi def link shHerePayload       shHereDoc
515 hi def link shLoop      shStatement
516 hi def link shMoreSpecial       shSpecial
517 hi def link shOption    shCommandSub
518 hi def link shPattern   shString
519 hi def link shParen     shArithmetic
520 hi def link shPosnParm  shShellVariables
521 hi def link shQuickComment      shComment
522 hi def link shRange     shOperator
523 hi def link shRedir     shOperator
524 hi def link shSetOption shOption
525 hi def link shSingleQuote       shString
526 hi def link shSource    shOperator
527 hi def link shStringSpecial     shSpecial
528 hi def link shSubShRegion       shOperator
529 hi def link shTestOpr   shConditional
530 hi def link shTestPattern       shString
531 hi def link shTestDoubleQuote   shString
532 hi def link shTestSingleQuote   shString
533 hi def link shVariable  shSetList
534 hi def link shWrapLineOperator  shOperator
536 if exists("b:is_bash")
537   hi def link bashAdminStatement        shStatement
538   hi def link bashSpecialVariables      shShellVariables
539   hi def link bashStatement             shStatement
540   hi def link shFunctionParen           Delimiter
541   hi def link shFunctionDelim           Delimiter
542 endif
543 if exists("b:is_kornshell")
544   hi def link kshSpecialVariables       shShellVariables
545   hi def link kshStatement              shStatement
546   hi def link shFunctionParen           Delimiter
547 endif
549 hi def link shCaseError         Error
550 hi def link shCondError         Error
551 hi def link shCurlyError                Error
552 hi def link shDerefError                Error
553 hi def link shDerefOpError              Error
554 hi def link shDerefWordError            Error
555 hi def link shDoError           Error
556 hi def link shEsacError         Error
557 hi def link shIfError           Error
558 hi def link shInError           Error
559 hi def link shParenError                Error
560 hi def link shTestError         Error
561 if exists("b:is_kornshell")
562   hi def link shDTestError              Error
563 endif
565 hi def link shArithmetic                Special
566 hi def link shCharClass         Identifier
567 hi def link shSnglCase          Statement
568 hi def link shCommandSub                Special
569 hi def link shComment           Comment
570 hi def link shConditional               Conditional
571 hi def link shCtrlSeq           Special
572 hi def link shExprRegion                Delimiter
573 hi def link shFunctionKey               Function
574 hi def link shFunctionName              Function
575 hi def link shNumber            Number
576 hi def link shOperator          Operator
577 hi def link shRepeat            Repeat
578 hi def link shSet               Statement
579 hi def link shSetList           Identifier
580 hi def link shShellVariables            PreProc
581 hi def link shSpecial           Special
582 hi def link shStatement         Statement
583 hi def link shString            String
584 hi def link shTodo              Todo
585 hi def link shAlias             Identifier
587 " Set Current Syntax: {{{1
588 " ===================
589 if exists("b:is_bash")
590  let b:current_syntax = "bash"
591 elseif exists("b:is_kornshell")
592  let b:current_syntax = "ksh"
593 else
594  let b:current_syntax = "sh"
595 endif
597 " vim: ts=16 fdm=marker