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: Nov 17, 2009
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
15 elseif exists("b:current_syntax")
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,
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
30 if exists("g:is_kornshell")
35 elseif exists("g:is_bash")
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"
52 if !exists("s:sh_fold_functions")
53 let s:sh_fold_functions = 1
55 if !exists("s:sh_fold_heredoc")
56 let s:sh_fold_heredoc = 2
58 if !exists("s:sh_fold_ifdofor")
59 let s:sh_fold_ifdofor = 4
61 if g:sh_fold_enabled && &fdm == "manual"
65 " sh syntax is case sensitive {{{1
68 " Clusters: contains=@... clusters {{{1
69 "==================================
70 syn cluster shErrorList contains=shDoError,shIfError,shInError,shCaseError,shEsacError,shCurlyError,shParenError,shTestError,shOK
71 if exists("b:is_kornshell")
72 syn cluster ErrorList add=shDTestError
74 syn cluster shArithParenList contains=shArithmetic,shCaseEsac,shDeref,shDerefSimple,shEcho,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement
75 syn cluster shArithList contains=@shArithParenList,shParenError
76 syn cluster shCaseEsacList contains=shCaseStart,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial,shCaseRange
77 syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
78 syn cluster shColonList contains=@shCaseList
79 syn cluster shCommandSubList contains=shArithmetic,shDeref,shDerefSimple,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shSingleQuote,shDoubleQuote,shStatement,shVariable,shSubSh,shAlias,shTest,shCtrlSeq,shSpecial
80 syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial
81 syn cluster shDblQuoteList contains=shCommandSub,shDeref,shDerefSimple,shPosnParm,shExSingleQuote,shCtrlSeq,shSpecial
82 syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPPS
83 syn cluster shDerefVarList contains=shDerefOp,shDerefVarArray,shDerefOpError
84 syn cluster shEchoList contains=shArithmetic,shCommandSub,shDeref,shDerefSimple,shExpr,shExSingleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote
85 syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq
86 syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest
87 syn cluster shFunctionList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shOption,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq
88 if exists("b:is_kornshell") || exists("b:is_bash")
89 syn cluster shFunctionList add=shRepeat
90 syn cluster shFunctionList add=shDblBrace,shDblParen
92 syn cluster shHereBeginList contains=@shCommandSubList
93 syn cluster shHereList contains=shBeginHere,shHerePayload
94 syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload
95 syn cluster shIdList contains=shCommandSub,shWrapLineOperator,shSetOption,shDeref,shDerefSimple,shRedir,shExSingleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial
96 syn cluster shLoopList contains=@shCaseList,shTestOpr,shExpr,shDblBrace,shConditional,shCaseEsac,shTest,@shErrorList,shSet
97 syn cluster shSubShList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator
98 syn cluster shTestList contains=shCharClass,shComment,shCommandSub,shDeref,shDerefSimple,shDoubleQuote,shExpr,shExpr,shNumber,shOperator,shExSingleQuote,shSingleQuote,shTestOpr,shTest,shCtrlSeq
102 " This one is needed INSIDE a CommandSub, so that `echo bla` be correct
103 syn region shEcho matchgroup=shStatement start="\<echo\>" skip="\\$" matchgroup=shOperator end="$" matchgroup=NONE end="[<>;&|()]"me=e-1 end="\d[<>]"me=e-2 end="\s#"me=e-2 contains=@shEchoList skipwhite nextgroup=shQuickComment
104 syn region shEcho matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shOperator end="$" matchgroup=NONE end="[<>;&|()]"me=e-1 end="\d[<>]"me=e-2 end="\s#"me=e-2 contains=@shEchoList skipwhite nextgroup=shQuickComment
105 syn match shEchoQuote contained '\%(\\\\\)*\\["`'()]'
107 " This must be after the strings, so that ... \" will be correct
108 syn region shEmbeddedEcho contained matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shOperator end="$" matchgroup=NONE end="[<>;&|`)]"me=e-1 end="\d[<>]"me=e-2 end="\s#"me=e-2 contains=shNumber,shExSingleQuote,shSingleQuote,shDeref,shDerefSimple,shSpecialVar,shOperator,shDoubleQuote,shCharClass,shCtrlSeq
112 if exists("b:is_kornshell") || exists("b:is_bash")
113 syn match shStatement "\<alias\>"
114 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+\)\@=" skip="\\$" end="\>\|`"
115 syn region shAlias matchgroup=shStatement start="\<alias\>\s\+\(\w\+=\)\@=" skip="\\$" end="="
120 syn match shDoError "\<done\>"
121 syn match shIfError "\<fi\>"
122 syn match shInError "\<in\>"
123 syn match shCaseError ";;"
124 syn match shEsacError "\<esac\>"
125 syn match shCurlyError "}"
126 syn match shParenError ")"
127 syn match shOK '\.\(done\|fi\|in\|esac\)'
128 if exists("b:is_kornshell")
129 syn match shDTestError "]]"
131 syn match shTestError "]"
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<<-\="
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
155 syn region shExpr transparent matchgroup=shExprRegion start="{" end="}" contains=@shExprList2 nextgroup=shMoreSpecial
156 syn region shSubSh transparent matchgroup=shSubShRegion start="(" end=")" contains=@shSubShList nextgroup=shMoreSpecial
160 syn region shExpr matchgroup=shRange start="\[" skip=+\\\\\|\\$+ end="\]" contains=@shTestList,shSpecial
161 syn region shTest transparent matchgroup=shStatement start="\<test\s" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1
162 syn match shTestOpr contained "<=\|>=\|!=\|==\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]"
163 syn match shTestOpr contained '=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern
164 syn match shTestPattern contained '\w\+'
165 syn match shTestDoubleQuote contained '"[^"]*"'
166 syn match shTestSingleQuote contained '\\.'
167 syn match shTestSingleQuote contained "'[^']*'"
168 if exists("b:is_kornshell") || exists("b:is_bash")
169 syn region shDblBrace matchgroup=Delimiter start="\[\[" skip=+\\\\\|\\$+ end="\]\]" contains=@shTestList
170 syn region shDblParen matchgroup=Delimiter start="((" skip=+\\\\\|\\$+ end="))" contains=@shTestList
173 " Character Class In Range: {{{1
174 " =========================
175 syn match shCharClass contained "\[:\(backspace\|escape\|return\|xdigit\|alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|tab\):\]"
177 " Loops: do, if, while, until {{{1
179 if (g:sh_fold_enabled % (s:sh_fold_ifdofor * 2))/s:sh_fold_ifdofor
180 syn region shDo fold transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
181 syn region shIf fold transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>" contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
182 syn region shFor fold matchgroup=shLoop start="\<for\_s" end="\<in\_s" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
184 syn region shDo transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
185 syn region shIf transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional end="\<;\_s*then\>" end="\<fi\>" contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey
186 syn region shFor matchgroup=shLoop start="\<for\_s" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
188 if exists("b:is_kornshell") || exists("b:is_bash")
189 syn cluster shCaseList add=shRepeat
190 syn cluster shFunctionList add=shRepeat
191 syn region shRepeat matchgroup=shLoop start="\<while\_s" end="\<in\_s" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace
192 syn region shRepeat matchgroup=shLoop start="\<until\_s" end="\<in\_s" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen,shDblBrace
193 syn region shCaseEsac matchgroup=shConditional start="\<select\s" matchgroup=shConditional end="\<in\>" end="\<do\>" contains=@shLoopList
195 syn region shRepeat matchgroup=shLoop start="\<while\_s" end="\<do\>"me=e-2 contains=@shLoopList
196 syn region shRepeat matchgroup=shLoop start="\<until\_s" end="\<do\>"me=e-2 contains=@shLoopList
198 syn region shCurlyIn contained matchgroup=Delimiter start="{" end="}" contains=@shCurlyList
199 syn match shComma contained ","
201 " Case: case...esac {{{1
203 syn match shCaseBar contained skipwhite "\(^\|[^\\]\)\(\\\\\)*\zs|" nextgroup=shCase,shCaseStart,shCaseBar,shComment,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote
204 syn match shCaseStart contained skipwhite skipnl "(" nextgroup=shCase,shCaseBar
205 if (g:sh_fold_enabled % (s:sh_fold_ifdofor * 2))/s:sh_fold_ifdofor
206 syn region shCase fold contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)" end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment
207 syn region shCaseEsac fold matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList
209 syn region shCase contained skipwhite skipnl matchgroup=shSnglCase start="\%(\\.\|[^#$()'" \t]\)\{-}\zs)" end=";;" end="esac"me=s-1 contains=@shCaseList nextgroup=shCaseStart,shCase,shComment
210 syn region shCaseEsac matchgroup=shConditional start="\<case\>" end="\<esac\>" contains=@shCaseEsacList
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
216 syn region shCaseExSingleQuote matchgroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial skipwhite skipnl nextgroup=shCaseBar contained
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
221 syn region shCaseRange matchgroup=Delimiter start=+\[+ skip=+\\\\+ end=+]+ contained
225 syn match shWrapLineOperator "\\$"
226 syn region shCommandSub start="`" skip="\\\\\|\\." end="`" contains=@shCommandSubList
227 syn match shEscape contained '\\.'
229 " $() and $(()): {{{1
230 " $(..) is not supported by sh (Bourne shell). However, apparently
231 " some systems (HP?) have as their /bin/sh a (link to) Korn shell
232 " (ie. Posix compliant shell). /bin/ksh should work for those
233 " systems too, however, so the following syntax will flag $(..) as
234 " an Error under /bin/sh. By consensus of vimdev'ers!
235 if exists("b:is_kornshell") || exists("b:is_bash")
236 syn region shCommandSub matchgroup=shCmdSubRegion start="\$(" skip='\\\\\|\\.' end=")" contains=@shCommandSubList
237 syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList
238 syn match shSkipInitWS contained "^\s\+"
240 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList
243 if exists("b:is_bash")
244 syn cluster shCommandSubList add=bashSpecialVariables,bashStatement
245 syn cluster shCaseList add=bashAdminStatement,bashStatement
246 syn keyword bashSpecialVariables contained BASH BASH_ENV BASH_VERSINFO BASH_VERSION CDPATH DIRSTACK EUID FCEDIT FIGNORE GLOBIGNORE GROUPS HISTCMD HISTCONTROL HISTFILE HISTFILESIZE HISTIGNORE HISTSIZE HOME HOSTFILE HOSTNAME HOSTTYPE IFS IGNOREEOF INPUTRC LANG LC_ALL LC_COLLATE LC_MESSAGES LINENO MACHTYPE MAIL MAILCHECK MAILPATH OLDPWD OPTARG OPTERR OPTIND OSTYPE PATH PIPESTATUS PPID PROMPT_COMMAND PS1 PS2 PS3 PS4 PWD RANDOM REPLY SECONDS SHELLOPTS SHLVL TIMEFORMAT TIMEOUT UID auto_resume histchars
247 syn keyword bashStatement chmod clear complete du egrep expr fgrep find gnufind gnugrep grep install less ls mkdir mv rm rmdir rpm sed sleep sort strip tail touch
248 syn keyword bashAdminStatement daemon killall killproc nice reload restart start status stop
251 if exists("b:is_kornshell")
252 syn cluster shCommandSubList add=kshSpecialVariables,kshStatement
253 syn cluster shCaseList add=kshStatement
254 syn keyword kshSpecialVariables contained CDPATH COLUMNS EDITOR ENV ERRNO FCEDIT FPATH HISTFILE HISTSIZE HOME IFS LINENO LINES MAIL MAILCHECK MAILPATH OLDPWD OPTARG OPTIND PATH PPID PS1 PS2 PS3 PS4 PWD RANDOM REPLY SECONDS SHELL TMOUT VISUAL
255 syn keyword kshStatement cat chmod clear cp du egrep expr fgrep find grep install killall less ls mkdir mv nice printenv rm rmdir sed sort strip stty tail touch tput
258 syn match shSource "^\.\s"
259 syn match shSource "\s\.\s"
260 "syn region shColon start="^\s*:" end="$" end="\s#"me=e-2 contains=@shColonList
261 syn region shColon start="^\s*\zs:" end="$" end="\s#"me=e-2
263 " String And Character Constants: {{{1
264 "================================
265 syn match shNumber "-\=\<\d\+\>#\="
266 syn match shCtrlSeq "\\\d\d\d\|\\[abcfnrtv0]" contained
267 if exists("b:is_bash")
268 syn match shSpecial "\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[abefnrtv]" contained
270 if exists("b:is_bash")
271 syn region shExSingleQuote matchgroup=shOperator start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial,shSpecial
273 syn region shExSingleQuote matchGroup=Error start=+\$'+ skip=+\\\\\|\\.+ end=+'+ contains=shStringSpecial
275 syn region shSingleQuote matchgroup=shOperator start=+'+ end=+'+ contains=@Spell
276 syn region shDoubleQuote matchgroup=shOperator start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell
277 syn match shStringSpecial "[^[:print:] \t]" contained
278 syn match shStringSpecial "\%(\\\\\)*\\[\\"'`$()#]"
279 syn match shSpecial "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial
280 syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]"
281 syn match shMoreSpecial "\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial contained
285 syn cluster shCommentGroup contains=shTodo,@Spell
286 syn keyword shTodo contained COMBAK FIXME TODO XXX
287 syn match shComment "^\s*\zs#.*$" contains=@shCommentGroup
288 syn match shComment "\s\zs#.*$" contains=@shCommentGroup
289 syn match shQuickComment contained "#.*$"
291 " Here Documents: {{{1
292 " =========================================
294 syn region shHereDoc matchgroup=shRedir start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
295 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir end="^\s*END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
296 syn region shHereDoc matchgroup=shRedir start="<<\s*\**EOF\**" matchgroup=shRedir end="^EOF$" contains=@shDblQuoteList
297 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**EOF\**" matchgroup=shRedir end="^\s*EOF$" contains=@shDblQuoteList
298 syn region shHereDoc matchgroup=shRedir start="<<\s*\**\.\**" matchgroup=shRedir end="^\.$" contains=@shDblQuoteList
299 syn region shHereDoc matchgroup=shRedir start="<<-\s*\**\.\**" matchgroup=shRedir end="^\s*\.$" contains=@shDblQuoteList
301 elseif (g:sh_fold_enabled % (s:sh_fold_heredoc * 2))/s:sh_fold_heredoc
302 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList
303 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$"
304 syn region shHereDoc matchgroup=shRedir fold start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$"
305 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList
306 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$"
307 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$"
308 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
309 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$"
310 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$"
311 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$"
312 syn region shHereDoc matchgroup=shRedir fold start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$"
313 syn region shHereDoc matchgroup=shRedir fold start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$"
314 syn region shHereDoc matchgroup=shRedir fold start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
317 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\=\z(\S*\)" matchgroup=shRedir end="^\z1\s*$" contains=@shDblQuoteList
318 syn region shHereDoc matchgroup=shRedir start="<<\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$"
319 syn region shHereDoc matchgroup=shRedir start="<<-\s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$" contains=@shDblQuoteList
320 syn region shHereDoc matchgroup=shRedir start="<<-\s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$"
321 syn region shHereDoc matchgroup=shRedir start="<<\s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$"
322 syn region shHereDoc matchgroup=shRedir start="<<-\s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$"
323 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
324 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\z(\S*\)" matchgroup=shRedir end="^\s*\z1\s*$"
325 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\s*\z1\s*$"
326 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*'\z(\S*\)'" matchgroup=shRedir end="^\z1\s*$"
327 syn region shHereDoc matchgroup=shRedir start="<<\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\z1\s*$"
328 syn region shHereDoc matchgroup=shRedir start="<<-\s*\\\_$\_s*\"\z(\S*\)\"" matchgroup=shRedir end="^\s*\z1\s*$"
329 syn region shHereDoc matchgroup=shRedir start="<<\\\z(\S*\)" matchgroup=shRedir end="^\z1\s*$"
334 if exists("b:is_bash")
335 syn match shRedir "<<<"
340 syn match shSetOption "\s\zs[-+][a-zA-Z0-9]\+\>" contained
341 syn match shVariable "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze=" nextgroup=shSetIdentifier
342 syn match shSetIdentifier "=" contained nextgroup=shPattern,shDeref,shDerefSimple,shDoubleQuote,shSingleQuote,shExSingleQuote
343 if exists("b:is_bash")
344 syn region shSetList oneline matchgroup=shSet start="\<\(declare\|typeset\|local\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+#\|=" contains=@shIdList
345 syn region shSetList oneline matchgroup=shSet start="\<set\>\ze[^/]" end="\ze[;|)]\|$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList
346 elseif exists("b:is_kornshell")
347 syn region shSetList oneline matchgroup=shSet start="\<\(typeset\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList
348 syn region shSetList oneline matchgroup=shSet start="\<set\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList
350 syn region shSetList oneline matchgroup=shSet start="\<\(set\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shOperator end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+[#=]" contains=@shIdList
354 if !exists("g:is_posix")
355 syn keyword shFunctionKey function skipwhite skipnl nextgroup=shFunctionTwo
358 if exists("b:is_bash")
359 if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions
360 syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
361 syn region shFunctionTwo fold matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
363 syn region shFunctionOne matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList
364 syn region shFunctionTwo matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
367 if (g:sh_fold_enabled % (s:sh_fold_functions * 2))/s:sh_fold_functions
368 syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
369 syn region shFunctionTwo fold matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
371 syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList
372 syn region shFunctionTwo matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
376 " Parameter Dereferencing: {{{1
377 " ========================
378 syn match shDerefSimple "\$\%(\h\w*\|\d\)"
379 syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray
380 syn match shDerefWordError "[^}$[]" contained
381 syn match shDerefSimple "\$[-#*@!?]"
382 syn match shDerefSimple "\$\$"
383 if exists("b:is_bash") || exists("b:is_kornshell")
384 syn region shDeref matchgroup=PreProc start="\${##\=" end="}" contains=@shDerefList
385 syn region shDeref matchgroup=PreProc start="\${\$\$" end="}" contains=@shDerefList
388 " bash: ${!prefix*} and ${#parameter}: {{{1
389 " ====================================
390 if exists("b:is_bash")
391 syn region shDeref matchgroup=PreProc start="\${!" end="\*\=}" contains=@shDerefList,shDerefOp
392 syn match shDerefVar contained "{\@<=!\w\+" nextgroup=@shDerefVarList
395 syn match shDerefSpecial contained "{\@<=[-*@?0]" nextgroup=shDerefOp,shDerefOpError
396 syn match shDerefSpecial contained "\({[#!]\)\@<=[[:alnum:]*@_]\+" nextgroup=@shDerefVarList,shDerefOp
397 syn match shDerefVar contained "{\@<=\w\+" nextgroup=@shDerefVarList
399 " sh ksh bash : ${var[... ]...} array reference: {{{1
400 syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" contains=@shCommandSubList nextgroup=shDerefOp,shDerefOpError
402 " Special ${parameter OPERATOR word} handling: {{{1
403 " sh ksh bash : ${parameter:-word} word is default value
404 " sh ksh bash : ${parameter:=word} assign word as default value
405 " sh ksh bash : ${parameter:?word} display word if parameter is null
406 " sh ksh bash : ${parameter:+word} use word if parameter is not null, otherwise nothing
407 " ksh bash : ${parameter#pattern} remove small left pattern
408 " ksh bash : ${parameter##pattern} remove large left pattern
409 " ksh bash : ${parameter%pattern} remove small right pattern
410 " ksh bash : ${parameter%%pattern} remove large right pattern
411 syn cluster shDerefPatternList contains=shDerefPattern,shDerefString
412 syn match shDerefOpError contained ":[[:punct:]]"
413 syn match shDerefOp contained ":\=[-=?]" nextgroup=@shDerefPatternList
414 syn match shDerefOp contained ":\=+" nextgroup=@shDerefPatternList
415 if exists("b:is_bash") || exists("b:is_kornshell")
416 syn match shDerefOp contained "#\{1,2}" nextgroup=@shDerefPatternList
417 syn match shDerefOp contained "%\{1,2}" nextgroup=@shDerefPatternList
418 syn match shDerefPattern contained "[^{}]\+" contains=shDeref,shDerefSimple,shDerefPattern,shDerefString,shCommandSub,shDerefEscape nextgroup=shDerefPattern
419 syn region shDerefPattern contained start="{" end="}" contains=shDeref,shDerefSimple,shDerefString,shCommandSub nextgroup=shDerefPattern
420 syn match shDerefEscape contained '\%(\\\\\)*\\.'
422 syn region shDerefString contained matchgroup=shOperator start=+\%(\\\)\@<!'+ end=+'+ contains=shStringSpecial
423 syn region shDerefString contained matchgroup=shOperator start=+\%(\\\)\@<!"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial
424 syn match shDerefString contained "\\["']" nextgroup=shDerefPattern
426 if exists("b:is_bash")
427 " bash : ${parameter:offset}
428 " bash : ${parameter:offset:length}
429 syn region shDerefOp contained start=":[$[:alnum:]_]"me=e-1 end=":"me=e-1 end="}"me=e-1 contains=@shCommandSubList nextgroup=shDerefPOL
430 syn match shDerefPOL contained ":[^}]\+" contains=@shCommandSubList
432 " bash : ${parameter//pattern/string}
433 " bash : ${parameter//pattern}
434 syn match shDerefPPS contained '/\{1,2}' nextgroup=shDerefPPSleft
435 syn region shDerefPPSleft contained start='.' skip=@\%(\\\)\/@ matchgroup=shDerefOp end='/' end='\ze}' nextgroup=shDerefPPSright contains=@shCommandSubList
436 syn region shDerefPPSright contained start='.' end='\ze}' contains=@shCommandSubList
439 " Arithmetic Parenthesized Expressions: {{{1
440 syn region shParen matchgroup=shArithRegion start='(\ze[^(]' end=')' contains=@shArithParenList
442 " Useful sh Keywords: {{{1
443 " ===================
444 syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait
445 syn keyword shConditional contained elif else then
446 syn keyword shCondError elif else then
448 " Useful ksh Keywords: {{{1
449 " ====================
450 if exists("b:is_kornshell") || exists("b:is_bash")
451 syn keyword shStatement autoload bg false fc fg functions getopts hash history integer jobs let nohup print printf r stop suspend times true type unalias whence
452 if exists("g:is_posix")
453 syn keyword shStatement command
455 syn keyword shStatement time
458 " Useful bash Keywords: {{{1
459 " =====================
460 if exists("b:is_bash")
461 syn keyword shStatement bind builtin dirs disown enable help local logout popd pushd shopt source
463 syn keyword shStatement login newgrp
467 " Synchronization: {{{1
469 if !exists("sh_minlines")
470 let sh_minlines = 200
472 if !exists("sh_maxlines")
473 let sh_maxlines = 2 * sh_minlines
475 exec "syn sync minlines=" . sh_minlines . " maxlines=" . sh_maxlines
476 syn sync match shCaseEsacSync grouphere shCaseEsac "\<case\>"
477 syn sync match shCaseEsacSync groupthere shCaseEsac "\<esac\>"
478 syn sync match shDoSync grouphere shDo "\<do\>"
479 syn sync match shDoSync groupthere shDo "\<done\>"
480 syn sync match shForSync grouphere shFor "\<for\>"
481 syn sync match shForSync groupthere shFor "\<in\>"
482 syn sync match shIfSync grouphere shIf "\<if\>"
483 syn sync match shIfSync groupthere shIf "\<fi\>"
484 syn sync match shUntilSync grouphere shRepeat "\<until\>"
485 syn sync match shWhileSync grouphere shRepeat "\<while\>"
487 " Default Highlighting: {{{1
488 " =====================
489 hi def link shArithRegion shShellVariables
490 hi def link shBeginHere shRedir
491 hi def link shCaseBar shConditional
492 hi def link shCaseCommandSub shCommandSub
493 hi def link shCaseDoubleQuote shDoubleQuote
494 hi def link shCaseIn shConditional
495 hi def link shCaseSingleQuote shSingleQuote
496 hi def link shCaseStart shConditional
497 hi def link shCmdSubRegion shShellVariables
498 hi def link shColon shComment
499 hi def link shDerefOp shOperator
500 hi def link shDerefPOL shDerefOp
501 hi def link shDerefPPS shDerefOp
502 hi def link shDeref shShellVariables
503 hi def link shDerefSimple shDeref
504 hi def link shDerefSpecial shDeref
505 hi def link shDerefString shDoubleQuote
506 hi def link shDerefVar shDeref
507 hi def link shDoubleQuote shString
508 hi def link shEcho shString
509 hi def link shEchoQuote shString
510 hi def link shEmbeddedEcho shString
511 hi def link shEscape shCommandSub
512 hi def link shExSingleQuote shSingleQuote
513 hi def link shFunction Function
514 hi def link shHereDoc shString
515 hi def link shHerePayload shHereDoc
516 hi def link shLoop shStatement
517 hi def link shMoreSpecial shSpecial
518 hi def link shOption shCommandSub
519 hi def link shPattern shString
520 hi def link shParen shArithmetic
521 hi def link shPosnParm shShellVariables
522 hi def link shQuickComment shComment
523 hi def link shRange shOperator
524 hi def link shRedir shOperator
525 hi def link shSetOption shOption
526 hi def link shSingleQuote shString
527 hi def link shSource shOperator
528 hi def link shStringSpecial shSpecial
529 hi def link shSubShRegion shOperator
530 hi def link shTestOpr shConditional
531 hi def link shTestPattern shString
532 hi def link shTestDoubleQuote shString
533 hi def link shTestSingleQuote shString
534 hi def link shVariable shSetList
535 hi def link shWrapLineOperator shOperator
537 if exists("b:is_bash")
538 hi def link bashAdminStatement shStatement
539 hi def link bashSpecialVariables shShellVariables
540 hi def link bashStatement shStatement
541 hi def link shFunctionParen Delimiter
542 hi def link shFunctionDelim Delimiter
544 if exists("b:is_kornshell")
545 hi def link kshSpecialVariables shShellVariables
546 hi def link kshStatement shStatement
547 hi def link shFunctionParen Delimiter
550 hi def link shCaseError Error
551 hi def link shCondError Error
552 hi def link shCurlyError Error
553 hi def link shDerefError Error
554 hi def link shDerefOpError Error
555 hi def link shDerefWordError Error
556 hi def link shDoError Error
557 hi def link shEsacError Error
558 hi def link shIfError Error
559 hi def link shInError Error
560 hi def link shParenError Error
561 hi def link shTestError Error
562 if exists("b:is_kornshell")
563 hi def link shDTestError Error
566 hi def link shArithmetic Special
567 hi def link shCharClass Identifier
568 hi def link shSnglCase Statement
569 hi def link shCommandSub Special
570 hi def link shComment Comment
571 hi def link shConditional Conditional
572 hi def link shCtrlSeq Special
573 hi def link shExprRegion Delimiter
574 hi def link shFunctionKey Function
575 hi def link shFunctionName Function
576 hi def link shNumber Number
577 hi def link shOperator Operator
578 hi def link shRepeat Repeat
579 hi def link shSet Statement
580 hi def link shSetList Identifier
581 hi def link shShellVariables PreProc
582 hi def link shSpecial Special
583 hi def link shStatement Statement
584 hi def link shString String
585 hi def link shTodo Todo
586 hi def link shAlias Identifier
588 " Set Current Syntax: {{{1
589 " ===================
590 if exists("b:is_bash")
591 let b:current_syntax = "bash"
592 elseif exists("b:is_kornshell")
593 let b:current_syntax = "ksh"
595 let b:current_syntax = "sh"
598 " vim: ts=16 fdm=marker