1" Description: html indenter 2" Author: Johannes Zellner <johannes@zellner.org> 3" Last Change: Mo, 05 Jun 2006 22:32:41 CEST 4" Restoring 'cpo' and 'ic' added by Bram 2006 May 5 5" Globals: g:html_indent_tags -- indenting tags 6" g:html_indent_strict -- inhibit 'O O' elements 7" g:html_indent_strict_table -- inhibit 'O -' elements 8 9" Only load this indent file when no other was loaded. 10if exists("b:did_indent") 11 finish 12endif 13let b:did_indent = 1 14 15 16" [-- local settings (must come before aborting the script) --] 17setlocal indentexpr=HtmlIndentGet(v:lnum) 18setlocal indentkeys=o,O,*<Return>,<>>,{,} 19 20 21if exists('g:html_indent_tags') 22 unlet g:html_indent_tags 23endif 24 25" [-- helper function to assemble tag list --] 26fun! <SID>HtmlIndentPush(tag) 27 if exists('g:html_indent_tags') 28 let g:html_indent_tags = g:html_indent_tags.'\|'.a:tag 29 else 30 let g:html_indent_tags = a:tag 31 endif 32endfun 33 34 35" [-- <ELEMENT ? - - ...> --] 36call <SID>HtmlIndentPush('a') 37call <SID>HtmlIndentPush('abbr') 38call <SID>HtmlIndentPush('acronym') 39call <SID>HtmlIndentPush('address') 40call <SID>HtmlIndentPush('b') 41call <SID>HtmlIndentPush('bdo') 42call <SID>HtmlIndentPush('big') 43call <SID>HtmlIndentPush('blockquote') 44call <SID>HtmlIndentPush('button') 45call <SID>HtmlIndentPush('caption') 46call <SID>HtmlIndentPush('center') 47call <SID>HtmlIndentPush('cite') 48call <SID>HtmlIndentPush('code') 49call <SID>HtmlIndentPush('colgroup') 50call <SID>HtmlIndentPush('del') 51call <SID>HtmlIndentPush('dfn') 52call <SID>HtmlIndentPush('dir') 53call <SID>HtmlIndentPush('div') 54call <SID>HtmlIndentPush('dl') 55call <SID>HtmlIndentPush('em') 56call <SID>HtmlIndentPush('fieldset') 57call <SID>HtmlIndentPush('font') 58call <SID>HtmlIndentPush('form') 59call <SID>HtmlIndentPush('frameset') 60call <SID>HtmlIndentPush('h1') 61call <SID>HtmlIndentPush('h2') 62call <SID>HtmlIndentPush('h3') 63call <SID>HtmlIndentPush('h4') 64call <SID>HtmlIndentPush('h5') 65call <SID>HtmlIndentPush('h6') 66call <SID>HtmlIndentPush('i') 67call <SID>HtmlIndentPush('iframe') 68call <SID>HtmlIndentPush('ins') 69call <SID>HtmlIndentPush('kbd') 70call <SID>HtmlIndentPush('label') 71call <SID>HtmlIndentPush('legend') 72call <SID>HtmlIndentPush('map') 73call <SID>HtmlIndentPush('menu') 74call <SID>HtmlIndentPush('noframes') 75call <SID>HtmlIndentPush('noscript') 76call <SID>HtmlIndentPush('object') 77call <SID>HtmlIndentPush('ol') 78call <SID>HtmlIndentPush('optgroup') 79" call <SID>HtmlIndentPush('pre') 80call <SID>HtmlIndentPush('q') 81call <SID>HtmlIndentPush('s') 82call <SID>HtmlIndentPush('samp') 83call <SID>HtmlIndentPush('script') 84call <SID>HtmlIndentPush('select') 85call <SID>HtmlIndentPush('small') 86call <SID>HtmlIndentPush('span') 87call <SID>HtmlIndentPush('strong') 88call <SID>HtmlIndentPush('style') 89call <SID>HtmlIndentPush('sub') 90call <SID>HtmlIndentPush('sup') 91call <SID>HtmlIndentPush('table') 92call <SID>HtmlIndentPush('textarea') 93call <SID>HtmlIndentPush('title') 94call <SID>HtmlIndentPush('tt') 95call <SID>HtmlIndentPush('u') 96call <SID>HtmlIndentPush('ul') 97call <SID>HtmlIndentPush('var') 98 99 100" [-- <ELEMENT ? O O ...> --] 101if !exists('g:html_indent_strict') 102 call <SID>HtmlIndentPush('body') 103 call <SID>HtmlIndentPush('head') 104 call <SID>HtmlIndentPush('html') 105 call <SID>HtmlIndentPush('tbody') 106endif 107 108 109" [-- <ELEMENT ? O - ...> --] 110if !exists('g:html_indent_strict_table') 111 call <SID>HtmlIndentPush('th') 112 call <SID>HtmlIndentPush('td') 113 call <SID>HtmlIndentPush('tr') 114 call <SID>HtmlIndentPush('tfoot') 115 call <SID>HtmlIndentPush('thead') 116endif 117 118delfun <SID>HtmlIndentPush 119 120let s:cpo_save = &cpo 121set cpo-=C 122 123" [-- count indent-increasing tags of line a:lnum --] 124fun! <SID>HtmlIndentOpen(lnum, pattern) 125 let s = substitute('x'.getline(a:lnum), 126 \ '.\{-}\(\(<\)\('.a:pattern.'\)\>\)', "\1", 'g') 127 let s = substitute(s, "[^\1].*$", '', '') 128 return strlen(s) 129endfun 130 131" [-- count indent-decreasing tags of line a:lnum --] 132fun! <SID>HtmlIndentClose(lnum, pattern) 133 let s = substitute('x'.getline(a:lnum), 134 \ '.\{-}\(\(<\)/\('.a:pattern.'\)\>>\)', "\1", 'g') 135 let s = substitute(s, "[^\1].*$", '', '') 136 return strlen(s) 137endfun 138 139" [-- count indent-increasing '{' of (java|css) line a:lnum --] 140fun! <SID>HtmlIndentOpenAlt(lnum) 141 return strlen(substitute(getline(a:lnum), '[^{]\+', '', 'g')) 142endfun 143 144" [-- count indent-decreasing '}' of (java|css) line a:lnum --] 145fun! <SID>HtmlIndentCloseAlt(lnum) 146 return strlen(substitute(getline(a:lnum), '[^}]\+', '', 'g')) 147endfun 148 149" [-- return the sum of indents respecting the syntax of a:lnum --] 150fun! <SID>HtmlIndentSum(lnum, style) 151 if a:style == match(getline(a:lnum), '^\s*</') 152 if a:style == match(getline(a:lnum), '^\s*</\<\('.g:html_indent_tags.'\)\>') 153 let open = <SID>HtmlIndentOpen(a:lnum, g:html_indent_tags) 154 let close = <SID>HtmlIndentClose(a:lnum, g:html_indent_tags) 155 if 0 != open || 0 != close 156 return open - close 157 endif 158 endif 159 endif 160 if '' != &syntax && 161 \ synIDattr(synID(a:lnum, 1, 1), 'name') =~ '\(css\|java\).*' && 162 \ synIDattr(synID(a:lnum, strlen(getline(a:lnum)), 1), 'name') 163 \ =~ '\(css\|java\).*' 164 if a:style == match(getline(a:lnum), '^\s*}') 165 return <SID>HtmlIndentOpenAlt(a:lnum) - <SID>HtmlIndentCloseAlt(a:lnum) 166 endif 167 endif 168 return 0 169endfun 170 171fun! HtmlIndentGet(lnum) 172 " Find a non-empty line above the current line. 173 let lnum = prevnonblank(a:lnum - 1) 174 175 " Hit the start of the file, use zero indent. 176 if lnum == 0 177 return 0 178 endif 179 180 let restore_ic = &ic 181 setlocal ic " ignore case 182 183 " [-- special handling for <pre>: no indenting --] 184 if getline(a:lnum) =~ '\c</pre>' 185 \ || 0 < searchpair('\c<pre>', '', '\c</pre>', 'nWb') 186 \ || 0 < searchpair('\c<pre>', '', '\c</pre>', 'nW') 187 " we're in a line with </pre> or inside <pre> ... </pre> 188 if restore_ic == 0 189 setlocal noic 190 endif 191 return -1 192 endif 193 194 " [-- special handling for <javascript>: use cindent --] 195 let js = '<script.*type\s*=\s*.*java' 196 197 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 198 " by Tye Zdrojewski <zdro@yahoo.com>, 05 Jun 2006 199 " ZDR: This needs to be an AND (we are 'after the start of the pair' AND 200 " we are 'before the end of the pair'). Otherwise, indentation 201 " before the start of the script block will be affected; the end of 202 " the pair will still match if we are before the beginning of the 203 " pair. 204 " 205 if 0 < searchpair(js, '', '</script>', 'nWb') 206 \ && 0 < searchpair(js, '', '</script>', 'nW') 207 " we're inside javascript 208 if getline(lnum) !~ js && getline(a:lnum) != '</script>' 209 if restore_ic == 0 210 setlocal noic 211 endif 212 return cindent(a:lnum) 213 endif 214 endif 215 216 if getline(lnum) =~ '\c</pre>' 217 " line before the current line a:lnum contains 218 " a closing </pre>. --> search for line before 219 " starting <pre> to restore the indent. 220 let preline = prevnonblank(search('\c<pre>', 'bW') - 1) 221 if preline > 0 222 if restore_ic == 0 223 setlocal noic 224 endif 225 return indent(preline) 226 endif 227 endif 228 229 let ind = <SID>HtmlIndentSum(lnum, -1) 230 let ind = ind + <SID>HtmlIndentSum(a:lnum, 0) 231 232 if restore_ic == 0 233 setlocal noic 234 endif 235 236 return indent(lnum) + (&sw * ind) 237endfun 238 239let &cpo = s:cpo_save 240unlet s:cpo_save 241 242" [-- EOF <runtime>/indent/html.vim --] 243