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