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