diff options
Diffstat (limited to 'runtime/indent/html.vim')
-rw-r--r-- | runtime/indent/html.vim | 133 |
1 files changed, 70 insertions, 63 deletions
diff --git a/runtime/indent/html.vim b/runtime/indent/html.vim index 8aaf82e21f..6c866594c5 100644 --- a/runtime/indent/html.vim +++ b/runtime/indent/html.vim @@ -2,7 +2,7 @@ " Header: "{{{ " Maintainer: Bram Moolenaar " Original Author: Andy Wokula <anwoku@yahoo.de> -" Last Change: 2015 Sep 25 +" Last Change: 2018 Mar 28 " Version: 1.0 " Description: HTML indent script with cached state for faster indenting on a " range of lines. @@ -25,27 +25,22 @@ if exists("b:did_indent") "{{{ finish endif + +" Load the Javascript indent script first, it defines GetJavascriptIndent(). +" Undo the rest. +" Load base python indent. +if !exists('*GetJavascriptIndent') + runtime! indent/javascript.vim +endif let b:did_indent = 1 setlocal indentexpr=HtmlIndent() setlocal indentkeys=o,O,<Return>,<>>,{,},!^F -" "j1" is included to make cindent() work better with Javascript. -setlocal cino=j1 -" "J1" should be included, but it doen't work properly before 7.4.355. -if has("patch-7.4.355") - setlocal cino+=J1 -endif -" Before patch 7.4.355 indenting after "(function() {" does not work well, add -" )2 to limit paren search. -if !has("patch-7.4.355") - setlocal cino+=)2 -endif - " Needed for % to work when finding start/end of a tag. setlocal matchpairs+=<:> -let b:undo_indent = "setlocal inde< indk< cino<" +let b:undo_indent = "setlocal inde< indk<" " b:hi_indent keeps state to speed up indenting consecutive lines. let b:hi_indent = {"lnum": -1} @@ -56,20 +51,14 @@ if exists("*HtmlIndent") && !exists('g:force_reload_html') finish endif -" shiftwidth() exists since patch 7.3.694 -if exists('*shiftwidth') - let s:ShiftWidth = function('shiftwidth') -else - func! s:ShiftWidth() - return &shiftwidth - endfunc -endif - " Allow for line continuation below. let s:cpo_save = &cpo set cpo-=C "}}} +" Pattern to match the name of a tag, including custom elements. +let s:tagname = '\w\+\(-\w\+\)*' + " Check and process settings from b:html_indent and g:html_indent... variables. " Prefer using buffer-local settings over global settings, so that there can " be defaults for all HTML files and exceptions for specific types of HTML @@ -128,7 +117,7 @@ func! HtmlIndent_CheckUserSettings() let indone = {"zero": 0 \,"auto": "indent(prevnonblank(v:lnum-1))" - \,"inc": "b:hi_indent.blocktagind + s:ShiftWidth()"} + \,"inc": "b:hi_indent.blocktagind + shiftwidth()"} let script1 = '' if exists("b:html_indent_script1") @@ -227,7 +216,8 @@ endfunc "}}} " Add known tag pairs. " Self-closing tags and tags that are sometimes {{{ " self-closing (e.g., <p>) are not here (when encountering </p> we can find -" the matching <p>, but not the other way around). +" the matching <p>, but not the other way around). Known self-closing tags: +" 'p', 'img', 'source'. " Old HTML tags: call s:AddITags(s:indent_tags, [ \ 'a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', @@ -240,13 +230,13 @@ call s:AddITags(s:indent_tags, [ \ 'sup', 'table', 'textarea', 'title', 'tt', 'u', 'ul', 'var', 'th', 'td', \ 'tr', 'tbody', 'tfoot', 'thead']) -" Tags added 2011 Sep 09 (especially HTML5 tags): +" New HTML5 elements: call s:AddITags(s:indent_tags, [ \ 'area', 'article', 'aside', 'audio', 'bdi', 'canvas', - \ 'command', 'datalist', 'details', 'embed', 'figure', 'footer', - \ 'header', 'group', 'keygen', 'mark', 'math', 'meter', 'nav', 'output', - \ 'progress', 'ruby', 'section', 'svg', 'texture', 'time', 'video', - \ 'wbr', 'text']) + \ 'command', 'data', 'datalist', 'details', 'embed', 'figcaption', + \ 'figure', 'footer', 'header', 'keygen', 'main', 'mark', 'meter', + \ 'nav', 'output', 'picture', 'progress', 'rp', 'rt', 'ruby', 'section', + \ 'summary', 'svg', 'time', 'track', 'video', 'wbr']) " Tags added for web components: call s:AddITags(s:indent_tags, [ @@ -294,7 +284,7 @@ func! s:CountITags(text) let s:nextrel = 0 " relative indent steps for next line [unit &sw]: let s:block = 0 " assume starting outside of a block let s:countonly = 1 " don't change state - call substitute(a:text, '<\zs/\=\w\+\(-\w\+\)*\>\|<!--\[\|\[endif\]-->\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g') + call substitute(a:text, '<\zs/\=' . s:tagname . '\>\|<!--\[\|\[endif\]-->\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g') let s:countonly = 0 endfunc "}}} @@ -306,7 +296,7 @@ func! s:CountTagsAndState(text) let s:nextrel = 0 " relative indent steps for next line [unit &sw]: let s:block = b:hi_newstate.block - let tmp = substitute(a:text, '<\zs/\=\w\+\(-\w\+\)*\>\|<!--\[\|\[endif\]-->\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g') + let tmp = substitute(a:text, '<\zs/\=' . s:tagname . '\>\|<!--\[\|\[endif\]-->\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g') if s:block == 3 let b:hi_newstate.scripttype = s:GetScriptType(matchstr(tmp, '\C.*<SCRIPT\>\zs[^>]*')) endif @@ -363,7 +353,7 @@ func! s:CheckBlockTag(blocktag, ind) endif let b:hi_newstate.blocklnr = v:lnum " save allover indent for the endtag - let b:hi_newstate.blocktagind = b:hi_indent.baseindent + (s:nextrel + s:curind) * s:ShiftWidth() + let b:hi_newstate.blocktagind = b:hi_indent.baseindent + (s:nextrel + s:curind) * shiftwidth() if a:ind == 3 return "SCRIPT" " all except this must be lowercase " line is to be checked again for the type attribute @@ -485,7 +475,7 @@ func! s:FreshState(lnum) let state.blocklnr = stopline " check preceding tags in the line: call s:CountITags(tagline[: stopcol-2]) - let state.blocktagind = indent(stopline) + (s:curind + s:nextrel) * s:ShiftWidth() + let state.blocktagind = indent(stopline) + (s:curind + s:nextrel) * shiftwidth() return state elseif stopline == state.lnum " handle special case: previous line (= state.lnum) contains a @@ -495,7 +485,7 @@ func! s:FreshState(lnum) if !swendtag let [bline, bcol] = searchpos('<'.blocktag[1:].'\>', "bnW") call s:CountITags(tolower(getline(bline)[: bcol-2])) - let state.baseindent = indent(bline) + (s:curind + s:nextrel) * s:ShiftWidth() + let state.baseindent = indent(bline) + (s:curind + s:nextrel) * shiftwidth() return state endif endif @@ -516,7 +506,7 @@ func! s:FreshState(lnum) if found == 2 let state.baseindent = b:hi_indent.baseindent endif - let state.blocktagind = indent(comlnum) + (s:curind + s:nextrel) * s:ShiftWidth() + let state.blocktagind = indent(comlnum) + (s:curind + s:nextrel) * shiftwidth() return state endif @@ -535,7 +525,7 @@ func! s:FreshState(lnum) let text = tolower(getline(comlnum)[: comcol-2]) endif call s:CountITags(text) - let state.baseindent = indent(comlnum) + (s:curind + s:nextrel) * s:ShiftWidth() + let state.baseindent = indent(comlnum) + (s:curind + s:nextrel) * shiftwidth() " TODO check tags that follow "-->" return state endif @@ -544,7 +534,7 @@ func! s:FreshState(lnum) let swendtag = match(text, '^\s*</') >= 0 " If previous line ended in a closing tag, line up with the opening tag. - if !swendtag && text =~ '</\w\+\s*>\s*$' + if !swendtag && text =~ '</' . s:tagname . '\s*>\s*$' call cursor(state.lnum, 99999) normal! F< let start_lnum = HtmlIndent_FindStartTag() @@ -555,9 +545,9 @@ func! s:FreshState(lnum) let text = getline(start_lnum) let swendtag = match(text, '^\s*</') >= 0 call s:CountITags(text[: col('.') - 2]) - let state.baseindent += s:nextrel * s:ShiftWidth() + let state.baseindent += s:nextrel * shiftwidth() if !swendtag - let state.baseindent += s:curind * s:ShiftWidth() + let state.baseindent += s:curind * shiftwidth() endif endif return state @@ -570,9 +560,9 @@ func! s:FreshState(lnum) let text = getline(state.lnum) let swendtag = match(text, '^\s*</') >= 0 call s:CountITags(tolower(text)) - let state.baseindent = indent(state.lnum) + s:nextrel * s:ShiftWidth() + let state.baseindent = indent(state.lnum) + s:nextrel * shiftwidth() if !swendtag - let state.baseindent += s:curind * s:ShiftWidth() + let state.baseindent += s:curind * shiftwidth() endif return state endfunc "}}} @@ -596,7 +586,7 @@ func! s:Alien3() return eval(b:hi_js1indent) endif if b:hi_indent.scripttype == "javascript" - return cindent(v:lnum) + return GetJavascriptIndent() else return -1 endif @@ -651,7 +641,7 @@ func! s:CSSIndent() " add indent after { let brace_counts = HtmlIndent_CountBraces(prev_lnum) - let extra = brace_counts.c_open * s:ShiftWidth() + let extra = brace_counts.c_open * shiftwidth() let prev_text = getline(prev_lnum) let below_end_brace = prev_text =~ '}\s*$' @@ -668,22 +658,22 @@ func! s:CSSIndent() " if the current line is not a comment or starts with @ (used by template " systems) reduce indent if previous line is a continuation line if !prev_hasfield && !prev_special - let extra = -s:ShiftWidth() + let extra = -shiftwidth() endif else let cur_hasfield = curtext =~ '^\s*[a-zA-Z0-9-]\+:' let prev_unfinished = s:CssUnfinished(prev_text) - if !cur_hasfield && (prev_hasfield || prev_unfinished) + if prev_unfinished " Continuation line has extra indent if the previous line was not a " continuation line. - let extra = s:ShiftWidth() + let extra = shiftwidth() " Align with @if if prev_text =~ '^\s*@if ' let extra = 4 endif elseif cur_hasfield && !prev_hasfield && !prev_special " less indent below a continuation line - let extra = -s:ShiftWidth() + let extra = -shiftwidth() endif endif endif @@ -704,10 +694,10 @@ func! s:CSSIndent() if special " do not reduce indent below @{ ... } if extra < 0 - let extra += s:ShiftWidth() + let extra += shiftwidth() endif else - let extra -= (brace_counts.c_close - (prev_text =~ '^\s*}')) * s:ShiftWidth() + let extra -= (brace_counts.c_close - (prev_text =~ '^\s*}')) * shiftwidth() endif endif @@ -715,10 +705,10 @@ func! s:CSSIndent() if extra == 0 if brace_counts.p_open > brace_counts.p_close " previous line has more ( than ): add a shiftwidth - let extra = s:ShiftWidth() + let extra = shiftwidth() elseif brace_counts.p_open < brace_counts.p_close " previous line has more ) than (: subtract a shiftwidth - let extra = -s:ShiftWidth() + let extra = -shiftwidth() endif endif @@ -726,9 +716,13 @@ func! s:CSSIndent() endfunc "}}} " Inside <style>: Whether a line is unfinished. +" tag: +" tag: blah +" tag: blah && +" tag: blah || func! s:CssUnfinished(text) "{{{ - return a:text =~ '\s\(||\|&&\|:\)\s*$' + return a:text =~ '\(||\|&&\|:\|\k\)\s*$' endfunc "}}} " Search back for the first unfinished line above "lnum". @@ -749,7 +743,7 @@ func! s:CssPrevNonComment(lnum, stopline) while 1 let ccol = match(getline(lnum), '\*/') if ccol < 0 - " No comment end thus its something else. + " No comment end thus it's something else. return lnum endif call cursor(lnum, ccol + 1) @@ -821,7 +815,7 @@ func! s:Alien5() let idx = match(prevtext, '^\s*\zs<!--') if idx >= 0 " just below comment start, add a shiftwidth - return idx + s:ShiftWidth() + return idx + shiftwidth() endif " Some files add 4 spaces just below a TODO line. It's difficult to detect @@ -842,7 +836,7 @@ func! s:Alien6() return indent(lnum) endif endif - return b:hi_indent.baseindent + s:ShiftWidth() + return b:hi_indent.baseindent + shiftwidth() endfunc "}}} " When the "lnum" line ends in ">" find the line containing the matching "<". @@ -874,7 +868,7 @@ func! HtmlIndent_FindStartTag() " The cursor must be on or before a closing tag. " If found, positions the cursor at the match and returns the line number. " Otherwise returns 0. - let tagname = matchstr(getline('.')[col('.') - 1:], '</\zs\w\+\ze') + let tagname = matchstr(getline('.')[col('.') - 1:], '</\zs' . s:tagname . '\ze') let start_lnum = searchpair('<' . tagname . '\>', '', '</' . tagname . '\>', 'bW') if start_lnum > 0 return start_lnum @@ -890,7 +884,7 @@ func! HtmlIndent_FindTagEnd() " a self-closing tag, to the matching ">". " Limited to look up to b:html_indent_line_limit lines away. let text = getline('.') - let tagname = matchstr(text, '\w\+\|!--', col('.')) + let tagname = matchstr(text, s:tagname . '\|!--', col('.')) if tagname == '!--' call search('--\zs>') elseif s:get_tag('/' . tagname) != 0 @@ -935,9 +929,22 @@ func! s:InsideTag(foundHtmlString) else let idx = match(text, '\s\zs[_a-zA-Z0-9-]\+="') endif + if idx == -1 + " try <tag attr + let idx = match(text, '<' . s:tagname . '\s\+\zs\w') + endif + if idx == -1 + " after just <tag indent one level more + let idx = match(text, '<' . s:tagname . '$') + if idx >= 0 + call cursor(lnum, idx) + return virtcol('.') + shiftwidth() + endif + endif if idx > 0 - " Found the attribute. TODO: assumes spaces, no Tabs. - return idx + " Found the attribute to align with. + call cursor(lnum, idx) + return virtcol('.') endif endwhile return -1 @@ -952,7 +959,7 @@ func! HtmlIndent() endif let curtext = tolower(getline(v:lnum)) - let indentunit = s:ShiftWidth() + let indentunit = shiftwidth() let b:hi_newstate = {} let b:hi_newstate.lnum = v:lnum @@ -1035,9 +1042,9 @@ func! HtmlIndent() if col('.') > 2 let swendtag = match(text, '^\s*</') >= 0 call s:CountITags(text[: col('.') - 2]) - let indent += s:nextrel * s:ShiftWidth() + let indent += s:nextrel * shiftwidth() if !swendtag - let indent += s:curind * s:ShiftWidth() + let indent += s:curind * shiftwidth() endif endif else |