Vim 7.2b ready for testing.
[MacVim/KaoriYa.git] / runtime / syntax / sh.vim
blobcb92bbda81deb64b410a3b4f0481730712b0a517
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:          Jul 01, 2008
6 " Version:              100
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 " adjust iskeyword for shell characters
46 "setlocal isk=@,48-57,_,192-255,#,.,/
48 " set up default g:sh_fold_enabled {{{1
49 if !exists("g:sh_fold_enabled")
50  let g:sh_fold_enabled= 0
51 elseif g:sh_fold_enabled != 0 && !has("folding")
52  let g:sh_fold_enabled= 0
53  echomsg "Ignoring g:sh_fold_enabled=".g:sh_fold_enabled."; need to re-compile vim for +fold support"
54 endif
55 if !exists("s:sh_fold_functions")
56  let s:sh_fold_functions = 1
57 endif
58 if !exists("s:sh_fold_heredoc")
59  let s:sh_fold_heredoc   = 2
60 endif
61 if !exists("s:sh_fold_ifdofor")
62  let s:sh_fold_ifdofor   = 4
63 endif
64 if g:sh_fold_enabled && &fdm == "manual"
65  set fdm=syntax
66 endif
68 " sh syntax is case sensitive {{{1
69 syn case match
71 " Clusters: contains=@... clusters {{{1
72 "==================================
73 syn cluster shErrorList contains=shDoError,shIfError,shInError,shCaseError,shEsacError,shCurlyError,shParenError,shTestError
74 if exists("b:is_kornshell")
75  syn cluster ErrorList add=shDTestError
76 endif
77 syn cluster shArithParenList    contains=shArithmetic,shDeref,shDerefSimple,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen
78 syn cluster shArithList contains=@shArithParenList,shParenError
79 syn cluster shCaseEsacList      contains=shCaseStart,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial
80 syn cluster shCaseList  contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
81 syn cluster shColonList contains=@shCaseList
82 syn cluster shCommandSubList    contains=shArithmetic,shDeref,shDerefSimple,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shSingleQuote,shDoubleQuote,shStatement,shVariable,shSubSh,shAlias,shTest,shCtrlSeq,shSpecial
83 syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial
84 syn cluster shDblQuoteList      contains=shCommandSub,shDeref,shDerefSimple,shPosnParm,shExSingleQuote,shCtrlSeq,shSpecial
85 syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPPS
86 syn cluster shDerefVarList      contains=shDerefOp,shDerefVarArray,shDerefOpError
87 syn cluster shEchoList  contains=shArithmetic,shCommandSub,shDeref,shDerefSimple,shExpr,shExSingleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote
88 syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq
89 syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest
90 syn cluster shFunctionList      contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq
91 if exists("b:is_kornshell") || exists("b:is_bash")
92  syn cluster shFunctionList     add=shRepeat
93  syn cluster shFunctionList     add=shDblBrace,shDblParen
94 endif
95 syn cluster shHereBeginList     contains=@shCommandSubList
96 syn cluster shHereList  contains=shBeginHere,shHerePayload
97 syn cluster shHereListDQ        contains=shBeginHere,@shDblQuoteList,shHerePayload
98 syn cluster shIdList    contains=shCommandSub,shWrapLineOperator,shSetOption,shDeref,shDerefSimple,shRedir,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial
99 syn cluster shLoopList  contains=@shCaseList,shTestOpr,shExpr,shDblBrace,shConditional,shCaseEsac,shTest,@shErrorList,shSet
100 syn cluster shSubShList contains=@shCaseList,shOperator
101 syn cluster shTestList  contains=shCharClass,shComment,shCommandSub,shDeref,shDerefSimple,shDoubleQuote,shExpr,shExpr,shNumber,shOperator,shExSingleQuote,shSingleQuote,shTestOpr,shTest,shCtrlSeq
104 " Echo: {{{1
105 " ====
106 " This one is needed INSIDE a CommandSub, so that `echo bla` be correct
107 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
108 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
109 syn match  shEchoQuote contained        '\%(\\\\\)*\\["`']'
111 " This must be after the strings, so that ... \" will be correct
112 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
114 " Alias: {{{1
115 " =====
116 if exists("b:is_kornshell") || exists("b:is_bash")
117  syn match shStatement "\<alias\>"
118  syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+\)\@=" skip="\\$" end="\>\|`"
119  syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+=\)\@=" skip="\\$" end="="
120 endif
122 " Error Codes: {{{1
123 " ============
124 syn match   shDoError "\<done\>"
125 syn match   shIfError "\<fi\>"
126 syn match   shInError "\<in\>"
127 syn match   shCaseError ";;"
128 syn match   shEsacError "\<esac\>"
129 syn match   shCurlyError "}"
130 syn match   shParenError ")"
131 if exists("b:is_kornshell")
132  syn match     shDTestError "]]"
133 endif
134 syn match     shTestError "]"
136 " Options: {{{1
137 " ====================
138 syn match   shOption    "\s\zs[-+][a-zA-Z0-9]\+\>"
139 syn match   shOption    "\s\zs--[^ \t$`'"|]\+"
141 " File Redirection Highlighted As Operators: {{{1
142 "===========================================
143 syn match      shRedir  "\d\=>\(&[-0-9]\)\="
144 syn match      shRedir  "\d\=>>-\="
145 syn match      shRedir  "\d\=<\(&[-0-9]\)\="
146 syn match      shRedir  "\d<<-\="
148 " Operators: {{{1
149 " ==========
150 syn match   shOperator  "<<\|>>"                contained
151 syn match   shOperator  "[!&;|]"                contained
152 syn match   shOperator  "\[[[^:]\|\]]"          contained
153 syn match   shOperator  "!\=="          skipwhite nextgroup=shPattern
154 syn match   shPattern   "\<\S\+\())\)\@="       contained contains=shExSingleQuote,shSingleQuote,shDoubleQuote,shDeref
156 " Subshells: {{{1
157 " ==========
158 syn region shExpr  transparent matchgroup=shExprRegion  start="{" end="}"       contains=@shExprList2
159 syn region shSubSh transparent matchgroup=shSubShRegion start="(" end=")"       contains=@shSubShList
161 " Tests: {{{1
162 "=======
163 "syn region  shExpr transparent matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList
164 syn region shExpr       matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList
165 syn region shTest       transparent matchgroup=shStatement start="\<test\>" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1
166 syn match  shTestOpr    contained       "<=\|>=\|!=\|==\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]"
167 syn match  shTestOpr    contained       '=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern
168 syn match  shTestPattern        contained       '\w\+'
169 syn match  shTestDoubleQuote    contained       '"[^"]*"'
170 syn match  shTestSingleQuote    contained       '\\.'
171 syn match  shTestSingleQuote    contained       "'[^']*'"
172 if exists("b:is_kornshell") || exists("b:is_bash")
173  syn region  shDblBrace matchgroup=Delimiter start="\[\[" skip=+\\\\\|\\$+ end="\]\]"   contains=@shTestList
174  syn region  shDblParen matchgroup=Delimiter start="((" skip=+\\\\\|\\$+ end="))"       contains=@shTestList
175 endif
177 " Character Class In Range: {{{1
178 " =========================
179 syn match   shCharClass contained       "\[:\(backspace\|escape\|return\|xdigit\|alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|tab\):\]"
181 " Loops: do, if, while, until {{{1
182 " ======
183 if (g:sh_fold_enabled % (s:sh_fold_ifdofor * 2))/s:sh_fold_ifdofor
184  syn region shDo        fold transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
185  syn region shIf        fold transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>"   contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
186  syn region shFor       fold matchgroup=shLoop start="\<for\_s" end="\<in\_s" end="\<do\>"me=e-2        contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
187 else
188  syn region shDo        transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
189  syn region shIf        transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>"   contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
190  syn region shFor       matchgroup=shLoop start="\<for\_s" end="\<in\>" end="\<do\>"me=e-2      contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
191 endif
192 if exists("b:is_kornshell") || exists("b:is_bash")
193  syn cluster shCaseList add=shRepeat
194  syn cluster shFunctionList     add=shRepeat
195  syn region shRepeat   matchgroup=shLoop   start="\<while\_s" end="\<in\_s" end="\<do\>"me=e-2  contains=@shLoopList,shDblParen,shDblBrace
196  syn region shRepeat   matchgroup=shLoop   start="\<until\_s" end="\<in\_s" end="\<do\>"me=e-2  contains=@shLoopList,shDblParen,shDblBrace
197  syn region shCaseEsac matchgroup=shConditional start="\<select\s" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList
198 else
199  syn region shRepeat   matchgroup=shLoop   start="\<while\_s" end="\<do\>"me=e-2                contains=@shLoopList
200  syn region shRepeat   matchgroup=shLoop   start="\<until\_s" end="\<do\>"me=e-2                contains=@shLoopList
201 endif
202 syn region shCurlyIn   contained        matchgroup=Delimiter start="{" end="}" contains=@shCurlyList
203 syn match  shComma     contained        ","
205 " Case: case...esac {{{1
206 " ====
207 syn match   shCaseBar   contained skipwhite "\(^\|[^\\]\)\(\\\\\)*\zs|"         nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
208 syn match   shCaseStart contained skipwhite skipnl "("                  nextgroup=shCase,shCaseBar
209 syn region  shCase      contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)"  end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment
210 if (g:sh_fold_enabled % (s:sh_fold_ifdofor * 2))/s:sh_fold_ifdofor
211  syn region  shCaseEsac fold matchgroup=shConditional start="\<case\>" end="\<esac\>"   contains=@shCaseEsacList
212 else
213  syn region  shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>"        contains=@shCaseEsacList
214 endif
215 syn keyword shCaseIn    contained skipwhite skipnl in                   nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
216 if exists("b:is_bash")
217  syn region  shCaseExSingleQuote        matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+      contains=shStringSpecial,shSpecial      skipwhite skipnl nextgroup=shCaseBar    contained
218 else
219  syn region  shCaseExSingleQuote        matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+   contains=shStringSpecial        skipwhite skipnl nextgroup=shCaseBar    contained
220 endif
221 syn region  shCaseSingleQuote   matchgroup=shOperator start=+'+ end=+'+         contains=shStringSpecial                skipwhite skipnl nextgroup=shCaseBar    contained
222 syn region  shCaseDoubleQuote   matchgroup=shOperator start=+"+ skip=+\\\\\|\\.+ end=+"+        contains=@shDblQuoteList,shStringSpecial        skipwhite skipnl nextgroup=shCaseBar    contained
223 syn region  shCaseCommandSub    start=+`+ skip=+\\\\\|\\.+ end=+`+              contains=@shCommandSubList              skipwhite skipnl nextgroup=shCaseBar    contained
225 " Misc: {{{1
226 "======
227 syn match   shWrapLineOperator "\\$"
228 syn region  shCommandSub   start="`" skip="\\\\\|\\." end="`" contains=@shCommandSubList
229 syn match   shEscape    contained       '\\.'
231 " $() and $(()): {{{1
232 " $(..) is not supported by sh (Bourne shell).  However, apparently
233 " some systems (HP?) have as their /bin/sh a (link to) Korn shell
234 " (ie. Posix compliant shell).  /bin/ksh should work for those
235 " systems too, however, so the following syntax will flag $(..) as
236 " an Error under /bin/sh.  By consensus of vimdev'ers!
237 if exists("b:is_kornshell") || exists("b:is_bash")
238  syn region shCommandSub matchgroup=shCmdSubRegion start="\$("  skip='\\\\\|\\.' end=")"  contains=@shCommandSubList
239  syn region shArithmetic matchgroup=shArithRegion  start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList
240  syn match  shSkipInitWS contained      "^\s\+"
241 else
242  syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList
243 endif
245 if exists("b:is_bash")
246  syn cluster shCommandSubList add=bashSpecialVariables,bashStatement
247  syn cluster shCaseList add=bashAdminStatement,bashStatement
248  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
249  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
250  syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop
251 endif
253 if exists("b:is_kornshell")
254  syn cluster shCommandSubList add=kshSpecialVariables,kshStatement
255  syn cluster shCaseList add=kshStatement
256  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
257  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
258 endif
260 syn match   shSource    "^\.\s"
261 syn match   shSource    "\s\.\s"
262 syn region  shColon     start="^\s*:" end="$\|" end="#"me=e-1 contains=@shColonList
264 " String And Character Constants: {{{1
265 "================================
266 syn match   shNumber    "-\=\<\d\+\>#\="
267 syn match   shCtrlSeq   "\\\d\d\d\|\\[abcfnrtv0]"               contained
268 if exists("b:is_bash")
269  syn match   shSpecial  "\\\o\o\o\|\\x\x\x\|\\c.\|\\[abefnrtv]" contained
270 endif
271 if exists("b:is_bash")
272  syn region  shExSingleQuote    matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+      contains=shStringSpecial,shSpecial
273 else
274  syn region  shExSingleQuote    matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+   contains=shStringSpecial
275 endif
276 syn region  shSingleQuote       matchgroup=shOperator start=+'+ end=+'+         contains=shStringSpecial,@Spell
277 syn region  shDoubleQuote       matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+      contains=@shDblQuoteList,shStringSpecial,@Spell
278 syn match   shStringSpecial     "[^[:print:]]"  contained
279 syn match   shStringSpecial     "\%(\\\\\)*\\[\\"'`$()#]"
280 syn match   shSpecial   "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]"
281 syn match   shSpecial   "^\%(\\\\\)*\\[\\"'`$()#]"
283 " Comments: {{{1
284 "==========
285 syn cluster    shCommentGroup   contains=shTodo,@Spell
286 syn keyword    shTodo   contained       COMBAK FIXME TODO XXX
287 syn match      shComment        "^\s*\zs#.*$"   contains=@shCommentGroup
288 syn match      shComment        "\s\zs#.*$"     contains=@shCommentGroup
289 syn match      shQuickComment   contained       "#.*$"
291 " Here Documents: {{{1
292 " =========================================
293 if version < 600
294  syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**"  matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
295  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
296  syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir      end="^EOF$"     contains=@shDblQuoteList
297  syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir     end="^\s*EOF$"  contains=@shDblQuoteList
298  syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**"  matchgroup=shRedir      end="^\.$"      contains=@shDblQuoteList
299  syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir      end="^\s*\.$"   contains=@shDblQuoteList
301 elseif (g:sh_fold_enabled % (s:sh_fold_heredoc * 2))/s:sh_fold_heredoc
302  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)"             matchgroup=shRedir end="^\z1\s*$"       contains=@shDblQuoteList
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="^\z1\s*$"
305  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)"            matchgroup=shRedir end="^\s*\z1\s*$"    contains=@shDblQuoteList
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*'\z(\S*\)'"          matchgroup=shRedir end="^\s*\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="^\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="^\s*\z1\s*$"
313  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'"          matchgroup=shRedir end="^\z1\s*$"
314  syn region shHereDoc matchgroup=shRedir fold start="<<\\\z(\S*\)"              matchgroup=shRedir end="^\z1\s*$"
316 else
317  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)"      matchgroup=shRedir end="^\z1\s*$"    contains=@shDblQuoteList
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*$" contains=@shDblQuoteList
320  syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'"       matchgroup=shRedir end="^\s*\z1\s*$"
321  syn region shHereDoc matchgroup=shRedir start="<<\s*'\z(\S*\)'"        matchgroup=shRedir end="^\z1\s*$"
322  syn region shHereDoc matchgroup=shRedir start="<<-\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="^\s*\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="<<\s*\\\_$\_s*'\z(\S*\)'"       matchgroup=shRedir end="^\z1\s*$"
327  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\""     matchgroup=shRedir end="^\z1\s*$"
328  syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\""    matchgroup=shRedir end="^\s*\z1\s*$"
329  syn region shHereDoc matchgroup=shRedir start="<<\\\z(\S*\)"           matchgroup=shRedir end="^\z1\s*$"
330 endif
332 " Here Strings: {{{1
333 " =============
334 if exists("b:is_bash")
335  syn match shRedir "<<<"
336 endif
338 " Identifiers: {{{1
339 "=============
340 syn match  shSetOption  "\s\zs[-+][a-zA-Z0-9]\+\>"      contained
341 syn match  shVariable   "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze="     nextgroup=shSetIdentifier
342 syn match  shSetIdentifier      "="             contained       nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shSingleQuote,shExSingleQuote
343 if exists("b:is_bash")
344  syn region shSetList oneline matchgroup=shSet start="\<\(declare\|typeset\|local\|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="\ze[;|)]\|$"                 matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze[#=]" contains=@shIdList
346 elseif exists("b:is_kornshell")
347  syn region shSetList oneline matchgroup=shSet start="\<\(typeset\|export\|unset\)\>\ze[^/]" end="$"            matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze[#=]" contains=@shIdList
348  syn region shSetList oneline matchgroup=shSet start="\<set\>\ze[^/]" end="$"                           matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze[#=]" contains=@shIdList
349 else
350  syn region shSetList oneline matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[^/]" end="$"                matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze[#=]" contains=@shIdList
351 endif
353 " Functions: {{{1
354 if !exists("g:is_posix")
355  syn keyword shFunctionKey function     skipwhite skipnl nextgroup=shFunctionTwo
356 endif
358 if exists("b:is_bash")
359  if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions
360   syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}"    contains=@shFunctionList                        skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
361   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
362  else
363   syn region shFunctionOne      matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{"    end="}" contains=@shFunctionList
364   syn region shFunctionTwo      matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
365  endif
366 else
367  if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions
368   syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}"       contains=@shFunctionList                        skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
369   syn region shFunctionTwo fold matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{"    end="}" contains=shFunctionKey,@shFunctionList contained        skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
370  else
371   syn region shFunctionOne      matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{"       end="}" contains=@shFunctionList
372   syn region shFunctionTwo      matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{"    end="}" contains=shFunctionKey,@shFunctionList contained
373  endif
374 endif
376 " Parameter Dereferencing: {{{1
377 " ========================
378 syn match  shDerefSimple        "\$\%(\h\w*\|\d\)"
379 syn region shDeref      matchgroup=PreProc start="\${" end="}"  contains=@shDerefList,shDerefVarArray
380 syn match  shDerefWordError     "[^}$[]"        contained
381 syn match  shDerefSimple        "\$[-#*@!?]"
382 syn match  shDerefSimple        "\$\$"
383 if exists("b:is_bash") || exists("b:is_kornshell")
384  syn region shDeref     matchgroup=PreProc start="\${##\=" end="}"      contains=@shDerefList
385  syn region shDeref     matchgroup=PreProc start="\${\$\$" end="}"      contains=@shDerefList
386 endif
388 " bash: ${!prefix*} and ${#parameter}: {{{1
389 " ====================================
390 if exists("b:is_bash")
391  syn region shDeref     matchgroup=PreProc start="\${!" end="\*\=}"     contains=@shDerefList,shDerefOp
392  syn match  shDerefVar  contained       "{\@<=!\w\+"            nextgroup=@shDerefVarList
393 endif
395 syn match  shDerefSpecial       contained       "{\@<=[-*@?0]"          nextgroup=shDerefOp,shDerefOpError
396 syn match  shDerefSpecial       contained       "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp
397 syn match  shDerefVar   contained       "{\@<=\w\+"             nextgroup=@shDerefVarList
399 " sh ksh bash : ${var[... ]...}  array reference: {{{1
400 syn region  shDerefVarArray   contained matchgroup=shDeref start="\[" end="]"   contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError
402 " Special ${parameter OPERATOR word} handling: {{{1
403 " sh ksh bash : ${parameter:-word}    word is default value
404 " sh ksh bash : ${parameter:=word}    assign word as default value
405 " sh ksh bash : ${parameter:?word}    display word if parameter is null
406 " sh ksh bash : ${parameter:+word}    use word if parameter is not null, otherwise nothing
407 "    ksh bash : ${parameter#pattern}  remove small left  pattern
408 "    ksh bash : ${parameter##pattern} remove large left  pattern
409 "    ksh bash : ${parameter%pattern}  remove small right pattern
410 "    ksh bash : ${parameter%%pattern} remove large right pattern
411 syn cluster shDerefPatternList  contains=shDerefPattern,shDerefString
412 syn match shDerefOpError        contained       ":[[:punct:]]"
413 syn match  shDerefOp    contained       ":\=[-=?]"      nextgroup=@shDerefPatternList
414 syn match  shDerefOp    contained       ":\=+"  nextgroup=@shDerefPatternList
415 if exists("b:is_bash") || exists("b:is_kornshell")
416  syn match  shDerefOp   contained       "#\{1,2}"       nextgroup=@shDerefPatternList
417  syn match  shDerefOp   contained       "%\{1,2}"       nextgroup=@shDerefPatternList
418  syn match  shDerefPattern      contained       "[^{}]\+"       contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern
419  syn region shDerefPattern      contained       start="{" end="}"       contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern
420  syn match  shDerefEscape       contained       '\%(\\\\\)*\\.'
421 endif
422 syn region shDerefString        contained       matchgroup=shOperator start=+\%(\\\)\@<!'+ end=+'+              contains=shStringSpecial
423 syn region shDerefString        contained       matchgroup=shOperator start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+   contains=@shDblQuoteList,shStringSpecial
424 syn match  shDerefString        contained       "\\["']"        nextgroup=shDerefPattern
426 if exists("b:is_bash")
427  " bash : ${parameter:offset}
428  " bash : ${parameter:offset:length}
429  syn region shDerefOp   contained       start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL
430  syn match  shDerefPOL  contained       ":[^}]\+"       contains=@shCommandSubList
432  " bash : ${parameter//pattern/string}
433  " bash : ${parameter//pattern}
434  syn match  shDerefPPS  contained       '/\{1,2}'       nextgroup=shDerefPPSleft
435  syn region shDerefPPSleft      contained       start='.'       skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList
436  syn region shDerefPPSright     contained       start='.'       end='\ze}'      contains=@shCommandSubList
437 endif
439 " Arithmetic Parenthesized Expressions: {{{1
440 syn region shParen matchgroup=shArithRegion start='(\ze[^(]' end=')' contains=@shArithParenList
442 " Useful sh Keywords: {{{1
443 " ===================
444 syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait
445 syn keyword shConditional contained elif else then
446 syn keyword shCondError elif else then
448 " Useful ksh Keywords: {{{1
449 " ====================
450 if exists("b:is_kornshell") || exists("b:is_bash")
451  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
452  if exists("g:is_posix")
453   syn keyword shStatement command
454  else
455   syn keyword shStatement time
456  endif
458 " Useful bash Keywords: {{{1
459 " =====================
460  if exists("b:is_bash")
461   syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source
462  else
463   syn keyword shStatement login newgrp
464  endif
465 endif
467 " Synchronization: {{{1
468 " ================
469 if !exists("sh_minlines")
470   let sh_minlines = 200
471 endif
472 if !exists("sh_maxlines")
473   let sh_maxlines = 2 * sh_minlines
474 endif
475 exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines
476 syn sync match shCaseEsacSync   grouphere       shCaseEsac      "\<case\>"
477 syn sync match shCaseEsacSync   groupthere      shCaseEsac      "\<esac\>"
478 syn sync match shDoSync grouphere       shDo    "\<do\>"
479 syn sync match shDoSync groupthere      shDo    "\<done\>"
480 syn sync match shForSync        grouphere       shFor   "\<for\>"
481 syn sync match shForSync        groupthere      shFor   "\<in\>"
482 syn sync match shIfSync grouphere       shIf    "\<if\>"
483 syn sync match shIfSync groupthere      shIf    "\<fi\>"
484 syn sync match shUntilSync      grouphere       shRepeat        "\<until\>"
485 syn sync match shWhileSync      grouphere       shRepeat        "\<while\>"
487 " Default Highlighting: {{{1
488 " =====================
489 hi def link shArithRegion       shShellVariables
490 hi def link shBeginHere shRedir
491 hi def link shCaseBar   shConditional
492 hi def link shCaseCommandSub    shCommandSub
493 hi def link shCaseDoubleQuote   shDoubleQuote
494 hi def link shCaseIn    shConditional
495 hi def link shCaseSingleQuote   shSingleQuote
496 hi def link shCaseStart shConditional
497 hi def link shCmdSubRegion      shShellVariables
498 hi def link shColon     shStatement
499 hi def link shDerefOp   shOperator
500 hi def link shDerefPOL  shDerefOp
501 hi def link shDerefPPS  shDerefOp
502 hi def link shDeref     shShellVariables
503 hi def link shDerefSimple       shDeref
504 hi def link shDerefSpecial      shDeref
505 hi def link shDerefString       shDoubleQuote
506 hi def link shDerefVar  shDeref
507 hi def link shDoubleQuote       shString
508 hi def link shEcho      shString
509 hi def link shEchoQuote shString
510 hi def link shEmbeddedEcho      shString
511 hi def link shEscape    shCommandSub
512 hi def link shExSingleQuote     shSingleQuote
513 hi def link shFunction  Function
514 hi def link shHereDoc   shString
515 hi def link shHerePayload       shHereDoc
516 hi def link shLoop      shStatement
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