Merge branch 'hack/autopaste'
[vim-kana.git] / runtime / syntax / sh.vim
blobce98ac6d78a4ea327d0a326b48cd5d25becbc7ee
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:          Dec 12, 2006
6 " Version:              89
7 " URL:          http://mysite.verizon.net/astronaut/vim/index.html#vimlinks_syntax
9 " Using the following VIM variables: {{{1
10 " g:is_bash             if none of the previous three variables are
11 "               defined, then if g:is_bash is set enhance with
12 "               bash syntax highlighting
13 " g:is_kornshell        if neither b:is_kornshell or b:is_bash is
14 "               defined, then if g:is_kornshell is set
15 "               enhance with kornshell/POSIX syntax highlighting
16 " g:is_posix                    this variable is the same as g:is_kornshell
17 " g:sh_fold_enabled     if non-zero, syntax folding is enabled
18 " g:sh_minlines         sets up syn sync minlines (dflt: 200)
19 " g:sh_maxlines         sets up syn sync maxlines (dflt: 2x sh_minlines)
21 " This file includes many ideas from Éric Brunet (eric.brunet@ens.fr)
23 " For version 5.x: Clear all syntax items {{{1
24 " For version 6.x: Quit when a syntax file was already loaded
25 if version < 600
26   syntax clear
27 elseif exists("b:current_syntax")
28   finish
29 endif
31 " handling /bin/sh with is_kornshell/is_sh {{{1
32 " b:is_sh is set when "#! /bin/sh" is found;
33 " However, it often is just a masquerade by bash (typically Linux)
34 " or kornshell (typically workstations with Posix "sh").
35 " So, when the user sets "is_bash" or "is_kornshell",
36 " a b:is_sh is converted into b:is_bash/b:is_kornshell,
37 " respectively.
38 if !exists("b:is_kornshell") && !exists("b:is_bash")
39   if exists("g:is_posix") && !exists("g:is_kornshell")
40    let g:is_kornshell= g:is_posix
41   endif
42   if exists("g:is_kornshell")
43     let b:is_kornshell= 1
44     if exists("b:is_sh")
45       unlet b:is_sh
46     endif
47   elseif exists("g:is_bash")
48     let b:is_bash= 1
49     if exists("b:is_sh")
50       unlet b:is_sh
51     endif
52   else
53     let b:is_sh= 1
54   endif
55 endif
57 " set up default g:sh_fold_enabled {{{1
58 if !exists("g:sh_fold_enabled")
59  let g:sh_fold_enabled= 0
60 elseif g:sh_fold_enabled != 0 && !has("folding")
61  let g:sh_fold_enabled= 0
62  echomsg "Ignoring g:sh_fold_enabled=".g:sh_fold_enabled."; need to re-compile vim for +fold support"
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 shCaseEsacList      contains=shCaseStart,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq
74 syn cluster shCaseList  contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
75 syn cluster shColonList contains=@shCaseList
76 syn cluster shCommandSubList    contains=shArithmetic,shDeref,shDerefSimple,shNumber,shOperator,shPosnParm,shExSingleQuote,shSingleQuote,shDoubleQuote,shStatement,shVariable,shSubSh,shAlias,shTest,shCtrlSeq
77 syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial
78 syn cluster shDblQuoteList      contains=shCommandSub,shDeref,shDerefSimple,shPosnParm,shExSingleQuote,shCtrlSeq,shSpecial
79 syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPPS
80 syn cluster shDerefVarList      contains=shDerefOp,shDerefVarArray,shDerefOpError
81 syn cluster shEchoList  contains=shArithmetic,shCommandSub,shDeref,shDerefSimple,shExpr,shExSingleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq
82 syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq
83 syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest
84 syn cluster shFunctionList      contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shFunctionStart,shCtrlSeq
85 if exists("b:is_kornshell") || exists("b:is_bash")
86  syn cluster shFunctionList     add=shDblBrace,shDblParen
87 endif
88 syn cluster shHereBeginList     contains=@shCommandSubList
89 syn cluster shHereList  contains=shBeginHere,shHerePayload
90 syn cluster shHereListDQ        contains=shBeginHere,@shDblQuoteList,shHerePayload
91 syn cluster shIdList    contains=shCommandSub,shWrapLineOperator,shIdWhiteSpace,shDeref,shDerefSimple,shRedir,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq
92 syn cluster shLoopList  contains=@shCaseList,shTestOpr,shExpr,shDblBrace,shConditional,shCaseEsac,shTest
93 syn cluster shSubShList contains=@shCaseList,shOperator
94 syn cluster shTestList  contains=shCharClass,shComment,shCommandSub,shDeref,shDerefSimple,shDoubleQuote,shExpr,shExpr,shNumber,shOperator,shExSingleQuote,shSingleQuote,shTestOpr,shTest,shCtrlSeq
97 " Echo: {{{1
98 " ====
99 " This one is needed INSIDE a CommandSub, so that `echo bla` be correct
100 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
101 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
103 " This must be after the strings, so that bla \" be correct
104 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
106 " Alias: {{{1
107 " =====
108 if exists("b:is_kornshell") || exists("b:is_bash")
109  syn match shStatement "\<alias\>"
110  syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+\)\@=" skip="\\$" end="\>\|`"
111  syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+=\)\@=" skip="\\$" end="="
112 endif
114 " Error Codes: {{{1
115 " ============
116 syn match   shDoError "\<done\>"
117 syn match   shIfError "\<fi\>"
118 syn match   shInError "\<in\>"
119 syn match   shCaseError ";;"
120 syn match   shEsacError "\<esac\>"
121 syn match   shCurlyError "}"
122 syn match   shParenError ")"
123 if exists("b:is_kornshell")
124  syn match     shDTestError "]]"
125 endif
126 syn match     shTestError "]"
128 " Options Interceptor: {{{1
129 " ====================
130 syn match   shOption  "\s[\-+][a-zA-Z0-9]\+\>"ms=s+1
131 syn match   shOption  "\s--[^ \t$`'"|]\+"ms=s+1
133 " File Redirection Highlighted As Operators: {{{1
134 "===========================================
135 syn match      shRedir  "\d\=>\(&[-0-9]\)\="
136 syn match      shRedir  "\d\=>>-\="
137 syn match      shRedir  "\d\=<\(&[-0-9]\)\="
138 syn match      shRedir  "\d<<-\="
140 " Operators: {{{1
141 " ==========
142 syn match   shOperator  "<<\|>>"                contained
143 syn match   shOperator  "[!&;|]"
144 syn match   shOperator  "\[[[^:]\|\]]"
145 syn match   shOperator  "!\=="          skipwhite nextgroup=shPattern
146 syn match   shPattern   "\<\S\+\())\)\@="       contained contains=shExSingleQuote,shSingleQuote,shDoubleQuote,shDeref
148 " Subshells: {{{1
149 " ==========
150 syn region shExpr  transparent matchgroup=shExprRegion  start="{" end="}"       contains=@shExprList2
151 syn region shSubSh transparent matchgroup=shSubShRegion start="(" end=")"       contains=@shSubShList
153 " Tests: {{{1
154 "=======
155 "syn region  shExpr transparent matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList
156 syn region shExpr       matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList
157 syn region shTest       transparent matchgroup=shStatement start="\<test\>" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1
158 syn match  shTestOpr    contained       "<=\|>=\|!=\|==\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]"
159 syn match  shTestOpr    contained       '=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern
160 syn match  shTestPattern        contained       '\w\+'
161 syn match  shTestDoubleQuote    contained       '"[^"]*"'
162 syn match  shTestSingleQuote    contained       '\\.'
163 syn match  shTestSingleQuote    contained       "'[^']*'"
164 if exists("b:is_kornshell") || exists("b:is_bash")
165  syn region  shDblBrace matchgroup=Delimiter start="\[\[" skip=+\\\\\|\\$+ end="\]\]"   contains=@shTestList
166  syn region  shDblParen matchgroup=Delimiter start="((" skip=+\\\\\|\\$+ end="))"       contains=@shTestList
167 endif
169 " Character Class In Range: {{{1
170 " =========================
171 syn match   shCharClass contained       "\[:\(backspace\|escape\|return\|xdigit\|alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|tab\):\]"
173 " Loops: do, if, while, until {{{1
174 " ======
175 if g:sh_fold_enabled
176  syn region shDo        fold transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
177  syn region shIf        fold transparent matchgroup=shConditional start="\<if\>" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>"   contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
178  syn region shFor       fold matchgroup=shLoop start="\<for\>" end="\<in\>" end="\<do\>"me=e-2  contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
179 else
180  syn region shDo        transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
181  syn region shIf        transparent matchgroup=shConditional start="\<if\>" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>"   contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
182  syn region shFor       matchgroup=shLoop start="\<for\>" end="\<in\>" end="\<do\>"me=e-2       contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
183 endif
184 if exists("b:is_kornshell") || exists("b:is_bash")
185  syn cluster shCaseList add=shRepeat
186  syn region shRepeat   matchgroup=shLoop   start="\<while\>" end="\<in\>" end="\<do\>"me=e-2    contains=@shLoopList,shDblParen,shDblBrace
187  syn region shRepeat   matchgroup=shLoop   start="\<until\>" end="\<in\>" end="\<do\>"me=e-2    contains=@shLoopList,shDblParen,shDblBrace
188  syn region shCaseEsac matchgroup=shConditional start="\<select\>" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList
189 else
190  syn region shRepeat   matchgroup=shLoop   start="\<while\>" end="\<do\>"me=e-2         contains=@shLoopList
191  syn region shRepeat   matchgroup=shLoop   start="\<until\>" end="\<do\>"me=e-2         contains=@shLoopList
192 endif
193 syn region shCurlyIn   contained        matchgroup=Delimiter start="{" end="}" contains=@shCurlyList
194 syn match  shComma     contained        ","
196 " Case: case...esac {{{1
197 " ====
198 syn match   shCaseBar   contained skipwhite "[^|"`'()]\{-}|"hs=e                nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
199 syn match   shCaseStart contained skipwhite skipnl "("                  nextgroup=shCase,shCaseBar
200 syn region  shCase      contained skipwhite skipnl matchgroup=shSnglCase start="\([^#$()'" \t]\|\\.\)\{-})"ms=s,hs=e  end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment
201 if g:sh_fold_enabled
202  syn region  shCaseEsac fold matchgroup=shConditional start="\<case\>" end="\<esac\>"   contains=@shCaseEsacList
203 else
204  syn region  shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>"        contains=@shCaseEsacList
205 endif
206 syn keyword shCaseIn    contained skipwhite skipnl in                   nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
207 if exists("b:is_bash")
208  syn region  shCaseExSingleQuote        matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+      contains=shStringSpecial,shSpecial      skipwhite skipnl nextgroup=shCaseBar    contained
209 else
210  syn region  shCaseExSingleQuote        matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+   contains=shStringSpecial        skipwhite skipnl nextgroup=shCaseBar    contained
211 endif
212 syn region  shCaseSingleQuote   matchgroup=shOperator start=+'+ end=+'+         contains=shStringSpecial                skipwhite skipnl nextgroup=shCaseBar    contained
213 syn region  shCaseDoubleQuote   matchgroup=shOperator start=+"+ skip=+\\\\\|\\.+ end=+"+        contains=@shDblQuoteList,shStringSpecial        skipwhite skipnl nextgroup=shCaseBar    contained
214 syn region  shCaseCommandSub    start=+`+ skip=+\\\\\|\\.+ end=+`+              contains=@shCommandSubList              skipwhite skipnl nextgroup=shCaseBar    contained
216 " Misc: {{{1
217 "======
218 syn match   shWrapLineOperator "\\$"
219 syn region  shCommandSub   start="`" skip="\\\\\|\\." end="`" contains=@shCommandSubList
221 " $() and $(()): {{{1
222 " $(..) is not supported by sh (Bourne shell).  However, apparently
223 " some systems (HP?) have as their /bin/sh a (link to) Korn shell
224 " (ie. Posix compliant shell).  /bin/ksh should work for those
225 " systems too, however, so the following syntax will flag $(..) as
226 " an Error under /bin/sh.  By consensus of vimdev'ers!
227 if exists("b:is_kornshell") || exists("b:is_bash")
228  syn region shCommandSub matchgroup=shCmdSubRegion start="\$("  skip='\\\\\|\\.' end=")"  contains=@shCommandSubList
229  syn region shArithmetic matchgroup=shArithRegion  start="\$((" skip='\\\\\|\\.' end="))" contains=@shCommandSubList
230  syn match  shSkipInitWS contained      "^\s\+"
231 else
232  syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList
233 endif
235 if exists("b:is_bash")
236  syn cluster shCommandSubList add=bashSpecialVariables,bashStatement
237  syn cluster shCaseList add=bashAdminStatement,bashStatement
238  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
239  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
240  syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop
241 endif
243 if exists("b:is_kornshell")
244  syn cluster shCommandSubList add=kshSpecialVariables,kshStatement
245  syn cluster shCaseList add=kshStatement
246  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
247  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
248 endif
250 syn match   shSource    "^\.\s"
251 syn match   shSource    "\s\.\s"
252 syn region  shColon     start="^\s*:" end="$\|" end="#"me=e-1 contains=@shColonList
254 " String And Character Constants: {{{1
255 "================================
256 syn match   shNumber    "-\=\<\d\+\>#\="
257 syn match   shCtrlSeq   "\\\d\d\d\|\\[abcfnrtv0]"               contained
258 if exists("b:is_bash")
259  syn match   shSpecial  "\\\o\o\o\|\\x\x\x\|\\c.\|\\[abefnrtv]" contained
260 endif
261 if exists("b:is_bash")
262  syn region  shExSingleQuote    matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+      contains=shStringSpecial,shSpecial
263 else
264  syn region  shExSingleQuote    matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+   contains=shStringSpecial
265 endif
266 syn region  shSingleQuote       matchgroup=shOperator start=+'+ end=+'+         contains=shStringSpecial,@Spell
267 syn region  shDoubleQuote       matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+      contains=@shDblQuoteList,shStringSpecial,@Spell
268 syn match   shStringSpecial     "[^[:print:]]"  contained
269 syn match   shStringSpecial     "\%(\\\\\)*\\[\\"'`$()#]"
270 syn match   shSpecial   "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]"
271 syn match   shSpecial   "^\%(\\\\\)*\\[\\"'`$()#]"
273 " Comments: {{{1
274 "==========
275 syn cluster    shCommentGroup   contains=shTodo,@Spell
276 syn keyword    shTodo   contained       COMBAK FIXME TODO XXX
277 syn match      shComment        "^\s*\zs#.*$"   contains=@shCommentGroup
278 syn match      shComment        "#.*$"  contains=@shCommentGroup
280 " Here Documents: {{{1
281 " =========================================
282 if version < 600
283  syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**"  matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
284  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
285  syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir      end="^EOF$"     contains=@shDblQuoteList
286  syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir     end="^\s*EOF$"  contains=@shDblQuoteList
287  syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**"  matchgroup=shRedir      end="^\.$"      contains=@shDblQuoteList
288  syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir      end="^\s*\.$"   contains=@shDblQuoteList
290 elseif g:sh_fold_enabled
291  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)"             matchgroup=shRedir end="^\z1\s*$"       contains=@shDblQuoteList
292  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\"\z(\S*\)\""         matchgroup=shRedir end="^\z1\s*$"
293  syn region shHereDoc matchgroup=shRedir fold start="<<\s*'\z(\S*\)'"           matchgroup=shRedir end="^\z1\s*$"
294  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)"            matchgroup=shRedir end="^\s*\z1\s*$"    contains=@shDblQuoteList
295  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\"\z(\S*\)\""                matchgroup=shRedir end="^\s*\z1\s*$"
296  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*'\z(\S*\)'"          matchgroup=shRedir end="^\s*\z1\s*$"
297  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\z(\S*\)"            matchgroup=shRedir end="^\z1\s*$"
298  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\"\z(\S*\)\""        matchgroup=shRedir end="^\z1\s*$"
299  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*'\z(\S*\)'"         matchgroup=shRedir end="^\s*\z1\s*$"
300  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\z(\S*\)"           matchgroup=shRedir end="^\s*\z1\s*$"
301  syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\"\z(\S*\)\""       matchgroup=shRedir end="^\s*\z1\s*$"
302  syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'"          matchgroup=shRedir end="^\z1\s*$"
303  syn region shHereDoc matchgroup=shRedir fold start="<<\\\z(\S*\)"              matchgroup=shRedir end="^\z1\s*$"
305 else
306  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)"      matchgroup=shRedir end="^\z1\s*$"    contains=@shDblQuoteList
307  syn region shHereDoc matchgroup=shRedir start="<<\s*\"\z(\S*\)\""      matchgroup=shRedir end="^\z1\s*$"
308  syn region shHereDoc matchgroup=shRedir start="<<-\s*\z(\S*\)"         matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList
309  syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'"       matchgroup=shRedir end="^\s*\z1\s*$"
310  syn region shHereDoc matchgroup=shRedir start="<<\s*'\z(\S*\)'"        matchgroup=shRedir end="^\z1\s*$"
311  syn region shHereDoc matchgroup=shRedir start="<<-\s*\"\z(\S*\)\""     matchgroup=shRedir end="^\s*\z1\s*$"
312  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
313  syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\z(\S*\)"        matchgroup=shRedir end="^\s*\z1\s*$"
314  syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*'\z(\S*\)'"      matchgroup=shRedir end="^\s*\z1\s*$"
315  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*'\z(\S*\)'"       matchgroup=shRedir end="^\z1\s*$"
316  syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\""     matchgroup=shRedir end="^\z1\s*$"
317  syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\""    matchgroup=shRedir end="^\s*\z1\s*$"
318  syn region shHereDoc matchgroup=shRedir start="<<\\\z(\S*\)"           matchgroup=shRedir end="^\z1\s*$"
319 endif
321 " Here Strings: {{{1
322 " =============
323 if exists("b:is_bash")
324  syn match shRedir "<<<"
325 endif
327 " Identifiers: {{{1
328 "=============
329 syn match  shVariable "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze="       nextgroup=shSetIdentifier
330 syn match  shIdWhiteSpace  contained    "\s"
331 syn match  shSetIdentifier contained    "="     nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shSingleQuote,shExSingleQuote
332 if exists("b:is_bash")
333   syn region shSetList matchgroup=shSet start="\<\(declare\|typeset\|local\|export\|unset\)\>\ze[^/]" end="$"   matchgroup=shOperator end="\ze[|);&]"me=e-1 matchgroup=NONE end="#\|="me=e-1 contains=@shIdList
334   syn region shSetList matchgroup=shSet start="\<set\>[^/]"me=e-1 end="$" end="\\ze[|)]"                matchgroup=shOperator end="\ze[|);&]"me=e-1 matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList
335   syn match  shSet "\<\(declare\|typeset\|local\|export\|set\|unset\)\>"
336 elseif exists("b:is_kornshell")
337   syn region shSetList matchgroup=shSet start="\<\(typeset\|export\|unset\)\>\ze[^/]" end="$"           matchgroup=shOperator end="\ze[|);&]"me=e-1 matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList
338   syn region shSetList matchgroup=shSet start="\<set\>\ze[^/]" end="$\|\ze[})]"                 matchgroup=shOperator end="\ze[|);&]"me=e-1 matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList
339   syn match  shSet "\<\(typeset\|set\|export\|unset\)\>"
340 else
341   syn region shSetList matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[^/]" end="$\|\ze[|)]"      matchgroup=shOperator end="\ze[|);&]" matchgroup=NONE end="[#=]"me=e-1 contains=@shIdList
342   syn match  shStatement "\<\(set\|export\|unset\)\>"
343 endif
345 " Functions: {{{1
346 syn keyword shFunctionKey function      skipwhite skipnl nextgroup=shFunctionTwo
347 " COMBAK -- look at bash09.  function foo() (line#35) is folding 38 lines.  Not being terminated properly
348 "syn match   shFunctionStart    "{"     contained
349 if g:sh_fold_enabled
350  syn region shFunctionOne transparent fold      start="^\s*\h\w*\s*()\_s*\ze{"    matchgroup=shFunctionStart end="}"    contains=@shFunctionList                        skipwhite skipnl nextgroup=shFunctionStart
351  syn region shFunctionTwo transparent fold      start="\h\w*\s*\%(()\)\=\_s*\ze{" matchgroup=shFunctionStart end="}"    contains=shFunctionKey,@shFunctionList contained        skipwhite skipnl nextgroup=shFunctionStart
352 else
353  syn region shFunctionOne transparent   start="^\s*\h\w*\s*()\_s*\ze{"    matchgroup=shFunctionStart end="}"    contains=@shFunctionList
354  syn region shFunctionTwo transparent   start="\h\w*\s*\%(()\)\=\_s*\ze{" matchgroup=shFunctionStart end="}"    contains=shFunctionKey,@shFunctionList contained
355 endif
357 " Parameter Dereferencing: {{{1
358 " ========================
359 syn match  shDerefSimple        "\$\%(\h\w*\|\d\)"
360 syn region shDeref      matchgroup=PreProc start="\${" end="}"  contains=@shDerefList,shDerefVarArray
361 syn match  shDerefWordError     "[^}$[]"        contained
362 syn match  shDerefSimple        "\$[-#*@!?]"
363 syn match  shDerefSimple        "\$\$"
364 if exists("b:is_bash") || exists("b:is_kornshell")
365  syn region shDeref     matchgroup=PreProc start="\${##\=" end="}"      contains=@shDerefList
366 endif
368 " bash: ${!prefix*} and ${#parameter}: {{{1
369 " ====================================
370 if exists("b:is_bash")
371  syn region shDeref     matchgroup=PreProc start="\${!" end="\*\=}"     contains=@shDerefList,shDerefOp
372  syn match  shDerefVar  contained       "{\@<=!\w\+"            nextgroup=@shDerefVarList
373 endif
375 syn match  shDerefSpecial       contained       "{\@<=[-*@?0]"          nextgroup=shDerefOp,shDerefOpError
376 syn match  shDerefSpecial       contained       "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp
377 syn match  shDerefVar   contained       "{\@<=\w\+"             nextgroup=@shDerefVarList
379 " sh ksh bash : ${var[... ]...}  array reference: {{{1
380 syn region  shDerefVarArray   contained matchgroup=shDeref start="\[" end="]"   contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError
382 " Special ${parameter OPERATOR word} handling: {{{1
383 " sh ksh bash : ${parameter:-word}    word is default value
384 " sh ksh bash : ${parameter:=word}    assign word as default value
385 " sh ksh bash : ${parameter:?word}    display word if parameter is null
386 " sh ksh bash : ${parameter:+word}    use word if parameter is not null, otherwise nothing
387 "    ksh bash : ${parameter#pattern}  remove small left  pattern
388 "    ksh bash : ${parameter##pattern} remove large left  pattern
389 "    ksh bash : ${parameter%pattern}  remove small right pattern
390 "    ksh bash : ${parameter%%pattern} remove large right pattern
391 syn cluster shDerefPatternList  contains=shDerefPattern,shDerefString
392 syn match shDerefOpError        contained       ":[[:punct:]]"
393 syn match  shDerefOp    contained       ":\=[-=?]"      nextgroup=@shDerefPatternList
394 syn match  shDerefOp    contained       ":\=+"  nextgroup=@shDerefPatternList
395 if exists("b:is_bash") || exists("b:is_kornshell")
396  syn match  shDerefOp   contained       "#\{1,2}"       nextgroup=@shDerefPatternList
397  syn match  shDerefOp   contained       "%\{1,2}"       nextgroup=@shDerefPatternList
398  syn match  shDerefPattern      contained       "[^{}]\+"       contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern
399  syn region shDerefPattern      contained       start="{" end="}"       contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern
400  syn match  shDerefEscape       contained       '\%(\\\\\)*\\.'
401 endif
402 syn region shDerefString        contained       matchgroup=shOperator start=+'+ end=+'+         contains=shStringSpecial
403 syn region shDerefString        contained       matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+      contains=@shDblQuoteList,shStringSpecial
404 syn match  shDerefString        contained       "\\["']"
406 if exists("b:is_bash")
407  " bash : ${parameter:offset}
408  " bash : ${parameter:offset:length}
409  syn region shDerefOp   contained       start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL
410  syn match  shDerefPOL  contained       ":[^}]\+"       contains=@shCommandSubList
412  " bash : ${parameter//pattern/string}
413  " bash : ${parameter//pattern}
414  syn match  shDerefPPS  contained       '/\{1,2}'       nextgroup=shDerefPPSleft
415  syn region shDerefPPSleft      contained       start='.'       skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList
416  syn region shDerefPPSright     contained       start='.'       end='\ze}'      contains=@shCommandSubList
417 endif
419 " Useful sh Keywords: {{{1
420 " ===================
421 syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait
422 syn keyword shConditional contained elif else then
423 syn keyword shCondError elif else then
425 " Useful ksh Keywords: {{{1
426 " ====================
427 if exists("b:is_kornshell") || exists("b:is_bash")
428  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
430 " Useful bash Keywords: {{{1
431 " =====================
432  if exists("b:is_bash")
433   syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source
434  else
435   syn keyword shStatement login newgrp
436  endif
437 endif
439 " Synchronization: {{{1
440 " ================
441 if !exists("sh_minlines")
442   let sh_minlines = 200
443 endif
444 if !exists("sh_maxlines")
445   let sh_maxlines = 2 * sh_minlines
446 endif
447 exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines
448 syn sync match shCaseEsacSync   grouphere       shCaseEsac      "\<case\>"
449 syn sync match shCaseEsacSync   groupthere      shCaseEsac      "\<esac\>"
450 syn sync match shDoSync grouphere       shDo    "\<do\>"
451 syn sync match shDoSync groupthere      shDo    "\<done\>"
452 syn sync match shForSync        grouphere       shFor   "\<for\>"
453 syn sync match shForSync        groupthere      shFor   "\<in\>"
454 syn sync match shIfSync grouphere       shIf    "\<if\>"
455 syn sync match shIfSync groupthere      shIf    "\<fi\>"
456 syn sync match shUntilSync      grouphere       shRepeat        "\<until\>"
457 syn sync match shWhileSync      grouphere       shRepeat        "\<while\>"
459 " Default Highlighting: {{{1
460 " =====================
461 hi def link shArithRegion       shShellVariables
462 hi def link shBeginHere shRedir
463 hi def link shCaseBar   shConditional
464 hi def link shCaseCommandSub    shCommandSub
465 hi def link shCaseDoubleQuote   shDoubleQuote
466 hi def link shCaseIn    shConditional
467 hi def link shCaseSingleQuote   shSingleQuote
468 hi def link shCaseStart shConditional
469 hi def link shCmdSubRegion      shShellVariables
470 hi def link shColon     shStatement
471 hi def link shDerefOp   shOperator
472 hi def link shDerefPOL  shDerefOp
473 hi def link shDerefPPS  shDerefOp
474 hi def link shDeref     shShellVariables
475 hi def link shDerefSimple       shDeref
476 hi def link shDerefSpecial      shDeref
477 hi def link shDerefString       shDoubleQuote
478 hi def link shDerefVar  shDeref
479 hi def link shDoubleQuote       shString
480 hi def link shEcho      shString
481 hi def link shEmbeddedEcho      shString
482 hi def link shExSingleQuote     shSingleQuote
483 hi def link shFunctionStart     Delimiter
484 hi def link shHereDoc   shString
485 hi def link shHerePayload       shHereDoc
486 hi def link shLoop      shStatement
487 hi def link shOption    shCommandSub
488 hi def link shPattern   shString
489 hi def link shPosnParm  shShellVariables
490 hi def link shRange     shOperator
491 hi def link shRedir     shOperator
492 hi def link shSingleQuote       shString
493 hi def link shSource    shOperator
494 hi def link shStringSpecial     shSpecial
495 hi def link shSubShRegion       shOperator
496 hi def link shTestOpr   shConditional
497 hi def link shTestPattern       shString
498 hi def link shTestDoubleQuote   shString
499 hi def link shTestSingleQuote   shString
500 hi def link shVariable  shSetList
501 hi def link shWrapLineOperator  shOperator
503 if exists("b:is_bash")
504   hi def link bashAdminStatement        shStatement
505   hi def link bashSpecialVariables      shShellVariables
506   hi def link bashStatement             shStatement
507   hi def link shFunctionParen           Delimiter
508   hi def link shFunctionDelim           Delimiter
509 endif
510 if exists("b:is_kornshell")
511   hi def link kshSpecialVariables       shShellVariables
512   hi def link kshStatement              shStatement
513   hi def link shFunctionParen           Delimiter
514 endif
516 hi def link shCaseError         Error
517 hi def link shCondError         Error
518 hi def link shCurlyError                Error
519 hi def link shDerefError                Error
520 hi def link shDerefOpError              Error
521 hi def link shDerefWordError            Error
522 hi def link shDoError           Error
523 hi def link shEsacError         Error
524 hi def link shIfError           Error
525 hi def link shInError           Error
526 hi def link shParenError                Error
527 hi def link shTestError         Error
528 if exists("b:is_kornshell")
529   hi def link shDTestError              Error
530 endif
532 hi def link shArithmetic                Special
533 hi def link shCharClass         Identifier
534 hi def link shSnglCase          Statement
535 hi def link shCommandSub                Special
536 hi def link shComment           Comment
537 hi def link shConditional               Conditional
538 hi def link shCtrlSeq           Special
539 hi def link shExprRegion                Delimiter
540 hi def link shFunctionKey               Function
541 hi def link shFunctionName              Function
542 hi def link shNumber            Number
543 hi def link shOperator          Operator
544 hi def link shRepeat            Repeat
545 hi def link shSet               Statement
546 hi def link shSetList           Identifier
547 hi def link shShellVariables            PreProc
548 hi def link shSpecial           Special
549 hi def link shStatement         Statement
550 hi def link shString            String
551 hi def link shTodo              Todo
552 hi def link shAlias             Identifier
554 " Set Current Syntax: {{{1
555 " ===================
556 if exists("b:is_bash")
557  let b:current_syntax = "bash"
558 elseif exists("b:is_kornshell")
559  let b:current_syntax = "ksh"
560 else
561  let b:current_syntax = "sh"
562 endif
564 " vim: ts=16 fdm=marker