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