diff options
Diffstat (limited to 'indent/html.vim')
-rw-r--r-- | indent/html.vim | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/indent/html.vim b/indent/html.vim new file mode 100644 index 00000000..a4cd0c49 --- /dev/null +++ b/indent/html.vim @@ -0,0 +1,344 @@ +" Description: HTML5 and inline SVG indenter +" Changed By: HT de Beer <H.T.de.Beer@gmail.com> +" Last Change: 20121013 +" Added the SVG elements to the list of indenting element. SVG elements +" taken from http://www.w3.org/TR/SVG/eltindex.html +" +" Description: html5 (and html4) indenter +" Changed By: Brian Gershon <brian.five@gmail.com> +" Last Change: 30 Jan 2011 +" +" 1. Started with vim72 html indent file authored by Johannes Zellner (below) +" 2. Added html5 list as described here: +" http://stackoverflow.com/questions/3232518/how-to-update-vim-to-color-code-new-html-elements +" 3. Added this to a fork of https://github.com/othree/html5.vim +" which already provides nice html5 syntax highlighting. +" +" Description: html indenter +" Author: Johannes Zellner <johannes@zellner.org> +" Last Change: Mo, 05 Jun 2006 22:32:41 CEST +" Restoring 'cpo' and 'ic' added by Bram 2006 May 5 +" Globals: +" let g:html_indent_tags = 'html\|p\|time' +" let g:html_exclude_tags = ['html', 'style', 'script', 'body'] + + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +runtime! indent/javascript.vim +let s:jsindent = &indentexpr +unlet b:did_indent +runtime! indent/css.vim +let s:cssindent = &indentexpr +let b:did_indent = 1 + +" [-- local settings (must come before aborting the script) --] +setlocal indentexpr=HtmlIndentGet(v:lnum) +setlocal indentkeys=o,O,*<Return>,<>>,{,} + + +let s:tags = [] + +" [-- <ELEMENT ? - - ...> --] +call add(s:tags, 'a') +call add(s:tags, 'abbr') +call add(s:tags, 'acronym') +call add(s:tags, 'address') +call add(s:tags, 'b') +call add(s:tags, 'bdo') +call add(s:tags, 'big') +call add(s:tags, 'blockquote') +call add(s:tags, 'button') +call add(s:tags, 'caption') +call add(s:tags, 'center') +call add(s:tags, 'cite') +call add(s:tags, 'code') +call add(s:tags, 'colgroup') +call add(s:tags, 'del') +call add(s:tags, 'dfn') +call add(s:tags, 'dir') +call add(s:tags, 'div') +call add(s:tags, 'dl') +call add(s:tags, 'em') +call add(s:tags, 'fieldset') +call add(s:tags, 'font') +call add(s:tags, 'form') +call add(s:tags, 'frameset') +call add(s:tags, 'h1') +call add(s:tags, 'h2') +call add(s:tags, 'h3') +call add(s:tags, 'h4') +call add(s:tags, 'h5') +call add(s:tags, 'h6') +call add(s:tags, 'i') +call add(s:tags, 'iframe') +call add(s:tags, 'ins') +call add(s:tags, 'kbd') +call add(s:tags, 'label') +call add(s:tags, 'legend') +call add(s:tags, 'li') +call add(s:tags, 'map') +call add(s:tags, 'menu') +call add(s:tags, 'noframes') +call add(s:tags, 'noscript') +call add(s:tags, 'object') +call add(s:tags, 'ol') +call add(s:tags, 'optgroup') +call add(s:tags, 'p') +" call add(s:tags, 'pre') +call add(s:tags, 'q') +call add(s:tags, 's') +call add(s:tags, 'samp') +call add(s:tags, 'script') +call add(s:tags, 'select') +call add(s:tags, 'small') +call add(s:tags, 'span') +call add(s:tags, 'strong') +call add(s:tags, 'style') +call add(s:tags, 'sub') +call add(s:tags, 'sup') +call add(s:tags, 'table') +call add(s:tags, 'textarea') +call add(s:tags, 'title') +call add(s:tags, 'tt') +call add(s:tags, 'u') +call add(s:tags, 'ul') +call add(s:tags, 'var') + +" New HTML 5 elements +call add(s:tags, 'article') +call add(s:tags, 'aside') +call add(s:tags, 'audio') +call add(s:tags, 'canvas') +call add(s:tags, 'datalist') +call add(s:tags, 'details') +call add(s:tags, 'figcaption') +call add(s:tags, 'figure') +call add(s:tags, 'footer') +call add(s:tags, 'header') +call add(s:tags, 'hgroup') +call add(s:tags, 'main') +call add(s:tags, 'mark') +call add(s:tags, 'meter') +call add(s:tags, 'nav') +call add(s:tags, 'output') +call add(s:tags, 'progress') +call add(s:tags, 'rp') +call add(s:tags, 'rt') +call add(s:tags, 'ruby') +call add(s:tags, 'section') +call add(s:tags, 'summary') +call add(s:tags, 'template') +call add(s:tags, 'time') +call add(s:tags, 'video') +call add(s:tags, 'bdi') +call add(s:tags, 'data') + +" Common inline used SVG elements +call add(s:tags, 'clipPath') +call add(s:tags, 'defs') +call add(s:tags, 'desc') +call add(s:tags, 'filter') +call add(s:tags, 'foreignObject') +call add(s:tags, 'g') +call add(s:tags, 'linearGradient') +call add(s:tags, 'marker') +call add(s:tags, 'mask') +call add(s:tags, 'pattern') +call add(s:tags, 'radialGradient') +call add(s:tags, 'svg') +call add(s:tags, 'switch') +call add(s:tags, 'symbol') +call add(s:tags, 'text') +call add(s:tags, 'textPath') +call add(s:tags, 'tref') +call add(s:tags, 'tspan') + +call add(s:tags, 'html') +call add(s:tags, 'head') +call add(s:tags, 'body') + +call add(s:tags, 'thead') +call add(s:tags, 'tbody') +call add(s:tags, 'tfoot') +call add(s:tags, 'tr') +call add(s:tags, 'th') +call add(s:tags, 'td') + +if exists('g:html_exclude_tags') + for tag in g:html_exclude_tags + call remove(s:tags, index(s:tags, tag)) + endfor +endif +let s:html_indent_tags = join(s:tags, '\|') +if exists('g:html_indent_tags') + let s:html_indent_tags = s:html_indent_tags.'\|'.g:html_indent_tags +endif + +let s:cpo_save = &cpo +set cpo-=C + +" [-- count indent-increasing tags of line a:lnum --] +fun! <SID>HtmlIndentOpen(lnum, pattern) + let s = substitute('x'.getline(a:lnum), + \ '.\{-}\(\(<\)\('.a:pattern.'\)\>\)', "\1", 'g') + let s = substitute(s, "[^\1].*$", '', '') + return strlen(s) +endfun + +" [-- count indent-decreasing tags of line a:lnum --] +fun! <SID>HtmlIndentClose(lnum, pattern) + let s = substitute('x'.getline(a:lnum), + \ '.\{-}\(\(<\)/\('.a:pattern.'\)\>>\)', "\1", 'g') + let s = substitute(s, "[^\1].*$", '', '') + return strlen(s) +endfun + +" [-- count indent-increasing '{' of (java|css) line a:lnum --] +fun! <SID>HtmlIndentOpenAlt(lnum) + return strlen(substitute(getline(a:lnum), '[^{]\+', '', 'g')) +endfun + +" [-- count indent-decreasing '}' of (java|css) line a:lnum --] +fun! <SID>HtmlIndentCloseAlt(lnum) + return strlen(substitute(getline(a:lnum), '[^}]\+', '', 'g')) +endfun + +" [-- return the sum of indents respecting the syntax of a:lnum --] +fun! <SID>HtmlIndentSum(lnum, style) + if a:style == match(getline(a:lnum), '^\s*</') + if a:style == match(getline(a:lnum), '^\s*</\<\('.s:html_indent_tags.'\)\>') + let open = <SID>HtmlIndentOpen(a:lnum, s:html_indent_tags) + let close = <SID>HtmlIndentClose(a:lnum, s:html_indent_tags) + if 0 != open || 0 != close + return open - close + endif + endif + endif + + if '' != &syntax && + \ synIDattr(synID(a:lnum, 1, 1), 'name') =~ '\(css\|java\).*' && + \ synIDattr(synID(a:lnum, strlen(getline(a:lnum)), 1), 'name') + \ =~ '\(css\|java\).*' + if a:style == match(getline(a:lnum), '^\s*}') + return <SID>HtmlIndentOpenAlt(a:lnum) - <SID>HtmlIndentCloseAlt(a:lnum) + endif + endif + return 0 +endfun + +fun! HtmlIndentGet(lnum) + " Find a non-empty line above the current line. + let lnum = prevnonblank(a:lnum - 1) + + " Hit the start of the file, use zero indent. + if lnum == 0 + return 0 + endif + + let restore_ic = &ic + setlocal ic " ignore case + + " [-- special handling for <pre>: no indenting --] + if getline(a:lnum) =~ '\c</pre>' + \ || 0 < searchpair('\c<pre>', '', '\c</pre>', 'nWb') + \ || 0 < searchpair('\c<pre>', '', '\c</pre>', 'nW') + " we're in a line with </pre> or inside <pre> ... </pre> + if restore_ic == 0 + setlocal noic + endif + return -1 + endif + + " [-- special handling for <javascript>: use cindent --] + let js = '<script' + let jse = '</script>' + + """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + " by Tye Zdrojewski <zdro@yahoo.com>, 05 Jun 2006 + " ZDR: This needs to be an AND (we are 'after the start of the pair' AND + " we are 'before the end of the pair'). Otherwise, indentation + " before the start of the script block will be affected; the end of + " the pair will still match if we are before the beginning of the + " pair. + " + if 0 < searchpair(js, '', jse, 'nWb') + \ && 0 < searchpair(js, '', jse, 'nW') + " we're inside javascript + if getline(searchpair(js, '', '</script>', 'nWb')) !~ '<script [^>]*type=["'']\?text\/\(html\|template\)' + \ && getline(lnum) !~ js && getline(a:lnum) !~ jse + if restore_ic == 0 + setlocal noic + endif + if s:jsindent == '' + return cindent(a:lnum) + else + execute 'let ind = ' . s:jsindent + return ind + endif + endif + if getline(a:lnum) =~ jse + return indent(searchpair(js, '', jse, 'nWb')) + endif + endif + + let css = '<style' + let csse = '</style>' + if 0 < searchpair(css, '', csse, 'nWb') + \ && 0 < searchpair(css, '', csse, 'nW') + " we're inside style + if getline(lnum) !~ css && getline(a:lnum) !~ csse + if restore_ic == 0 + setlocal noic + endif + if s:cssindent == '' + return cindent(a:lnum) + else + execute 'let ind = ' . s:cssindent + return ind + endif + endif + if getline(a:lnum) =~ csse + return indent(searchpair(css, '', csse, 'nWb')) + endif + endif + + if getline(lnum) =~ '\c</pre>' + " line before the current line a:lnum contains + " a closing </pre>. --> search for line before + " starting <pre> to restore the indent. + let preline = prevnonblank(search('\c<pre>', 'bW') - 1) + if preline > 0 + if restore_ic == 0 + setlocal noic + endif + + if 0 == match(getline(a:lnum), '^\s*</') + return indent(preline) - (1*&sw) + else + return indent(preline) + endif + endif + endif + + let ind = <SID>HtmlIndentSum(lnum, -1) + let ind = ind + <SID>HtmlIndentSum(a:lnum, 0) + + " Fix for conditional comment + if getline(a:lnum) =~ '\c<!--.*<\(html\|body\).*-->' + let ind = ind - 1 + endif + + if restore_ic == 0 + setlocal noic + endif + + return indent(lnum) + (&sw * ind) +endfun + +let &cpo = s:cpo_save +unlet s:cpo_save + +" [-- EOF <runtime>/indent/html.vim --] |