let s:bx = '{\%("[^"]*"\|''[^'']*''\|\$#\|\${\w\+}\|\$\+\|{[^{]\+\|[^{}]\)\{-}}' let s:mx = '\([+>]\|[<^]\+\)\{-}' \ .'\((*\)\{-}' \ .'\([@#.]\{-}[a-zA-Z_\!][a-zA-Z0-9:_\!\-$]*\|' . s:bx . '\|\[[^\]]\+\]\)' \ .'\(' \ .'\%(' \ .'\%(#{[{}a-zA-Z0-9_\-\$]\+\|#[a-zA-Z0-9_\-\$]\+\)' \ .'\|\%(\[\%(\[[^\]]*\]\|"[^"]*"\|[^"\[\]]*\)\+\]\)' \ .'\|\%(\.{[{}a-zA-Z0-9_\-\$\.]\+\|\.[a-zA-Z0-9_\-\$]\+\)' \ .'\)*' \ .'\)' \ .'\%(\(' . s:bx . '\+\)\)\{0,1}' \ .'\%(\(@-\{0,1}[0-9]*\)\{0,1}\*\([0-9]\+\)\)\{0,1}' \ .'\(\%()\%(\(@-\{0,1}[0-9]*\)\{0,1}\*[0-9]\+\)\{0,1}\)*\)' function! emmet#lang#html#findTokens(str) abort let str = a:str let [pos, last_pos] = [0, 0] while 1 let tag = matchstr(str, '<[a-zA-Z].\{-}>', pos) if len(tag) == 0 break endif let pos = stridx(str, tag, pos) + len(tag) endwhile while 1 let tag = matchstr(str, '{%[^%]\{-}%}', pos) if len(tag) == 0 break endif let pos = stridx(str, tag, pos) + len(tag) endwhile let last_pos = pos while len(str) > 0 let white = matchstr(str, '^\s\+', pos) if white != '' let last_pos = pos + len(white) let pos = last_pos endif let token = matchstr(str, s:mx, pos) if token ==# '' break endif let pos = stridx(str, token, pos) + len(token) endwhile let str = a:str[last_pos :-1] if str =~# '^\w\+="[^"]*$' return '' endif return str endfunction function! emmet#lang#html#parseIntoTree(abbr, type) abort let abbr = a:abbr let type = a:type let settings = emmet#getSettings() if !has_key(settings, type) let type = 'html' endif if len(type) == 0 | let type = 'html' | endif let indent = emmet#getIndentation(type) let pmap = { \'p': 'span', \'ul': 'li', \'ol': 'li', \'table': 'tr', \'tr': 'td', \'tbody': 'tr', \'thead': 'tr', \'tfoot': 'tr', \'colgroup': 'col', \'select': 'option', \'optgroup': 'option', \'audio': 'source', \'video': 'source', \'object': 'param', \'map': 'area' \} let inlineLevel = split('a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var',',') let custom_expands = emmet#getResource(type, 'custom_expands', {}) if empty(custom_expands) && has_key(settings, 'custom_expands') let custom_expands = settings['custom_expands'] endif " try 'foo' to (foo-x) let rabbr = emmet#getExpandos(type, abbr) if rabbr == abbr " try 'foo+(' to (foo-x) let rabbr = substitute(abbr, '\%(+\|^\)\([a-zA-Z][a-zA-Z0-9+]\+\)+\([(){}>]\|$\)', '\="(".emmet#getExpandos(type, submatch(1)).")".submatch(2)', 'i') endif let abbr = rabbr let root = emmet#newNode() let root['variables'] = {} let parent = root let last = root let pos = [] while len(abbr) " parse line let match = matchstr(abbr, s:mx) let str = substitute(match, s:mx, '\0', 'ig') let operator = substitute(match, s:mx, '\1', 'ig') let block_start = substitute(match, s:mx, '\2', 'ig') let tag_name = substitute(match, s:mx, '\3', 'ig') let attributes = substitute(match, s:mx, '\4', 'ig') let value = substitute(match, s:mx, '\5', 'ig') let basevalue = substitute(match, s:mx, '\6', 'ig') let multiplier = 0 + substitute(match, s:mx, '\7', 'ig') let block_end = substitute(match, s:mx, '\8', 'ig') let custom = '' let important = 0 if len(str) == 0 break endif if tag_name =~# '^#' let attributes = tag_name . attributes let tag_name = '' endif if tag_name =~# '[^!]!$' let tag_name = tag_name[:-2] let important = 1 endif if tag_name =~# '^\.' let attributes = tag_name . attributes let tag_name = '' endif if tag_name =~# '^\[.*\]$' let attributes = tag_name . attributes let tag_name = '' endif for k in keys(custom_expands) if tag_name =~ k let custom = tag_name let tag_name = '' break endif endfor if empty(tag_name) let pname = len(parent.child) > 0 ? parent.child[0].name : '' if !empty(pname) && has_key(pmap, pname) && custom == '' let tag_name = pmap[pname] elseif !empty(pname) && index(inlineLevel, pname) > -1 let tag_name = 'span' elseif len(custom) == 0 let tag_name = 'div' elseif len(custom) != 0 && multiplier > 1 let tag_name = 'div' else let tag_name = custom endif endif let basedirect = basevalue[1] ==# '-' ? -1 : 1 if basevalue != '' let basevalue = 0 + abs(basevalue[1:]) else let basevalue = 1 endif if multiplier <= 0 | let multiplier = 1 | endif " make default node let current = emmet#newNode() let current.name = tag_name let current.important = important " aliases let aliases = emmet#getResource(type, 'aliases', {}) if has_key(aliases, tag_name) let current.name = aliases[tag_name] endif let use_pipe_for_cursor = emmet#getResource(type, 'use_pipe_for_cursor', 1) " snippets let snippets = emmet#getResource(type, 'snippets', {}) if !empty(snippets) let snippet_name = tag_name if has_key(snippets, snippet_name) let snippet = snippet_name while has_key(snippets, snippet) let snippet = snippets[snippet] endwhile if use_pipe_for_cursor let snippet = substitute(snippet, '|', '${cursor}', 'g') endif " just redirect to expanding if type == 'html' && snippet !~ '^\s*[{\[<]' return emmet#lang#html#parseIntoTree(snippet, a:type) endif let lines = split(snippet, "\n", 1) call map(lines, 'substitute(v:val, "\\( \\|\\t\\)", escape(indent, "\\\\"), "g")') let current.snippet = join(lines, "\n") let current.name = '' endif endif for k in keys(custom_expands) if tag_name =~# k let snippet = '${' . (empty(custom) ? tag_name : custom) . '}' let current.name = '' let current.snippet = snippet break elseif custom =~# k let snippet = '${' . custom . '}' let current.snippet = '${' . custom . '}' if current.name != '' let snode = emmet#newNode() let snode.snippet = snippet let snode.parent = current call add(current.child, snode) else let current.snippet = snippet endif break endif endfor " default_attributes let default_attributes = emmet#getResource(type, 'default_attributes', {}) if !empty(default_attributes) for pat in [current.name, tag_name] if has_key(default_attributes, pat) if type(default_attributes[pat]) == 4 let a = default_attributes[pat] let current.attrs_order += keys(a) if use_pipe_for_cursor for k in keys(a) if type(a[k]) == 7 call remove(current.attr, k) continue endif let current.attr[k] = len(a[k]) ? substitute(a[k], '|', '${cursor}', 'g') : '${cursor}' endfor else for k in keys(a) if type(a[k]) == 7 call remove(current.attr, k) continue endif let current.attr[k] = a[k] endfor endif else for a in default_attributes[pat] let current.attrs_order += keys(a) if use_pipe_for_cursor for k in keys(a) if type(a[k]) == 7 call remove(current.attr, k) continue endif let current.attr[k] = len(a[k]) ? substitute(a[k], '|', '${cursor}', 'g') : '${cursor}' endfor else for k in keys(a) if type(a[k]) == 7 call remove(current.attr, k) continue endif let current.attr[k] = a[k] endfor endif endfor endif if has_key(settings.html.default_attributes, current.name) let current.name = substitute(current.name, ':.*$', '', '') endif break endif endfor endif " parse attributes if len(attributes) let attr = attributes while len(attr) let item = matchstr(attr, '\(\%(\%(#[{}a-zA-Z0-9_\-\$]\+\)\|\%(\[\%(\[[^\]]*\]\|"[^"]*"\|[^"\[\]]*\)\+\]\)\|\%(\.[{}a-zA-Z0-9_\-\$]\+\)*\)\)') if g:emmet_debug > 1 echomsg 'attr=' . item endif if len(item) == 0 break endif if item[0] ==# '#' let current.attr.id = item[1:] let root['variables']['id'] = current.attr.id endif if item[0] ==# '.' let current.attr.class = substitute(item[1:], '\.', ' ', 'g') let root['variables']['class'] = current.attr.class endif if item[0] ==# '[' let atts = item[1:-2] if matchstr(atts, '^\s*\zs[0-9a-zA-Z_\-:]\+\(="[^"]*"\|=''[^'']*''\|=[^ ''"]\+\)') ==# '' let ks = [] if has_key(default_attributes, current.name) let dfa = default_attributes[current.name] let ks = type(dfa) == 3 ? len(dfa) > 0 ? keys(dfa[0]) : [] : keys(dfa) endif if len(ks) == 0 && has_key(default_attributes, current.name . ':src') let dfa = default_attributes[current.name . ':src'] let ks = type(dfa) == 3 ? len(dfa) > 0 ? keys(dfa[0]) : [] : keys(dfa) endif if len(ks) > 0 let current.attr[ks[0]] = atts elseif atts =~# '\.$' let current.attr[atts[:-2]] = function('emmet#types#true') else let current.attr[atts] = '' endif else while len(atts) let amat = matchstr(atts, '^\s*\zs\([0-9a-zA-Z-:]\+\%(={{.\{-}}}\|="[^"]*"\|=''[^'']*''\|=[^ ''"]\+\|[^ ''"\]]*\)\{0,1}\)') if len(amat) == 0 break endif let key = split(amat, '=')[0] let Val = amat[len(key)+1:] if key =~# '\.$' && Val ==# '' let key = key[:-2] unlet Val let Val = function('emmet#types#true') elseif Val =~# '^["'']' let Val = Val[1:-2] endif let current.attr[key] = Val if index(current.attrs_order, key) == -1 let current.attrs_order += [key] endif let atts = atts[stridx(atts, amat) + len(amat):] unlet Val endwhile endif endif let attr = substitute(strpart(attr, len(item)), '^\s*', '', '') endwhile endif " parse text if tag_name =~# '^{.*}$' let current.name = '' let current.value = tag_name else let current.value = value endif let current.basedirect = basedirect let current.basevalue = basevalue let current.multiplier = multiplier " parse step inside/outside if !empty(last) if operator =~# '>' unlet! parent let parent = last let current.parent = last let current.pos = last.pos + 1 else let current.parent = parent let current.pos = last.pos endif else let current.parent = parent let current.pos = 1 endif if operator =~# '[<^]' for c in range(len(operator)) let tmp = parent.parent if empty(tmp) break endif let parent = tmp let current.parent = tmp endfor endif call add(parent.child, current) let last = current " parse block if block_start =~# '(' if operator =~# '>' let last.pos += 1 endif let last.block = 1 for n in range(len(block_start)) let pos += [last.pos] endfor endif if block_end =~# ')' for n in split(substitute(substitute(block_end, ' ', '', 'g'), ')', ',),', 'g'), ',') if n ==# ')' if len(pos) > 0 && last.pos >= pos[-1] for c in range(last.pos - pos[-1]) let tmp = parent.parent if !has_key(tmp, 'parent') break endif let parent = tmp endfor if len(pos) > 0 call remove(pos, -1) endif let last = parent let last.pos += 1 endif elseif len(n) let st = 0 for nc in range(len(last.child)) if last.child[nc].block let st = nc break endif endfor let cl = last.child[st :] let cls = [] for c in range(n[1:]) for cc in cl if cc.multiplier > 1 let cc.basedirect = c + 1 else let cc.basevalue = c + 1 endif endfor let cls += deepcopy(cl) endfor if st > 0 let last.child = last.child[:st-1] + cls else let last.child = cls endif endif endfor endif let abbr = abbr[stridx(abbr, match) + len(match):] if abbr == '/' let current.empty = 1 endif if g:emmet_debug > 1 echomsg 'str='.str echomsg 'block_start='.block_start echomsg 'tag_name='.tag_name echomsg 'operator='.operator echomsg 'attributes='.attributes echomsg 'value='.value echomsg 'basevalue='.basevalue echomsg 'multiplier='.multiplier echomsg 'block_end='.block_end echomsg 'abbr='.abbr echomsg 'pos='.string(pos) echomsg '---' endif endwhile return root endfunction function! s:dollar_add(base,no) abort if a:base > 0 return a:base + a:no - 1 elseif a:base < 0 return a:base - a:no + 1 else return a:no endif endfunction function! emmet#lang#html#toString(settings, current, type, inline, filters, itemno, indent) abort let settings = a:settings let current = a:current let type = a:type let inline = a:inline let filters = a:filters let itemno = a:itemno let indent = a:indent let dollar_expr = emmet#getResource(type, 'dollar_expr', 1) let q = emmet#getResource(type, 'quote_char', '"') let ct = emmet#getResource(type, 'comment_type', 'both') let an = emmet#getResource(type, 'attribute_name', {}) let empty_elements = emmet#getResource(type, 'empty_elements', settings.html.empty_elements) let empty_element_suffix = emmet#getResource(type, 'empty_element_suffix', settings.html.empty_element_suffix) if emmet#useFilter(filters, 'haml') return emmet#lang#haml#toString(settings, current, type, inline, filters, itemno, indent) endif if emmet#useFilter(filters, 'slim') return emmet#lang#slim#toString(settings, current, type, inline, filters, itemno, indent) endif let comment = '' let current_name = current.name if dollar_expr let current_name = substitute(current_name, '\$$', itemno+1, '') endif let str = '' if len(current_name) == 0 let text = current.value[1:-2] if dollar_expr " TODO: regexp engine specified let nr = itemno + 1 if exists('®expengine') let text = substitute(text, '\%#=1\%(\\\)\@\ 0 let str .= '<' . current_name endif for attr in emmet#util#unique(current.attrs_order + keys(current.attr)) if !has_key(current.attr, attr) continue endif let Val = current.attr[attr] if type(Val) == 2 && Val == function('emmet#types#true') unlet Val let Val = 'true' if g:emmet_html5 let str .= ' ' . attr else let str .= ' ' . attr . '=' . q . attr . q endif if emmet#useFilter(filters, 'c') if attr ==# 'id' | let comment .= '#' . Val | endif if attr ==# 'class' | let comment .= '.' . Val | endif endif else if dollar_expr while Val =~# '\$\([^#{]\|$\)' " TODO: regexp engine specified if exists('®expengine') let Val = substitute(Val, '\%#=1\(\$\+\)\([^{#]\|$\)', '\=printf("%0".len(submatch(1))."d", itemno+1).submatch(2)', 'g') else let Val = substitute(Val, '\(\$\+\)\([^{#]\|$\)', '\=printf("%0".len(submatch(1))."d", itemno+1).submatch(2)', 'g') endif endwhile let attr = substitute(attr, '\$$', itemno+1, '') endif if attr ==# 'class' && emmet#useFilter(filters, 'bem') let vals = split(Val, '\s\+') let Val = '' let lead = '' for _val in vals if len(Val) > 0 let Val .= ' ' endif if _val =~# '^_' if has_key(current.parent.attr, 'class') let lead = current.parent.attr["class"] if _val =~# '^__' let Val .= lead . _val else let Val .= lead . ' ' . lead . _val endif else let lead = split(vals[0], '_')[0] let Val .= lead . _val endif elseif _val =~# '^-' for l in split(_val, '_') if len(Val) > 0 let Val .= ' ' endif let l = substitute(l, '^-', '__', '') if len(lead) == 0 let pattr = current.parent.attr if has_key(pattr, 'class') let lead = split(pattr['class'], '\s\+')[0] endif endif let Val .= lead . l let lead .= l . '_' endfor else let Val .= _val endif endfor endif if has_key(an, attr) let attr = an[attr] endif if emmet#isExtends(type, 'jsx') && Val =~ '^{.*}$' let str .= ' ' . attr . '=' . Val else let str .= ' ' . attr . '=' . q . Val . q endif if emmet#useFilter(filters, 'c') if attr ==# 'id' | let comment .= '#' . Val | endif if attr ==# 'class' | let comment .= '.' . Val | endif endif endif unlet Val endfor if len(comment) > 0 && ct ==# 'both' let str = '\n" . str endif if current.empty let str .= ' />' elseif stridx(','.empty_elements.',', ','.current_name.',') != -1 let str .= empty_element_suffix else let str .= '>' let text = current.value[1:-2] if dollar_expr " TODO: regexp engine specified let nr = itemno + 1 if exists('®expengine') let text = substitute(text, '\%#=1\%(\\\)\@\ 0 for n in range(nc) let child = current.child[n] if child.multiplier > 1 || (child.multiplier == 1 && len(child.child) > 0 && stridx(','.settings.html.inline_elements.',', ','.current_name.',') == -1) || settings.html.block_all_childless let str .= "\n" . indent let dr = 1 elseif len(current_name) > 0 && stridx(','.settings.html.inline_elements.',', ','.current_name.',') == -1 if nc > 1 || (len(child.name) > 0 && stridx(','.settings.html.inline_elements.',', ','.child.name.',') == -1) let str .= "\n" . indent let dr = 1 elseif current.multiplier == 1 && nc == 1 && len(child.name) == 0 let str .= "\n" . indent let dr = 1 endif endif let inner = emmet#toString(child, type, 0, filters, itemno, indent) let inner = substitute(inner, "^\n", '', 'g') let inner = substitute(inner, "\n", "\n" . escape(indent, '\'), 'g') let inner = substitute(inner, "\n" . escape(indent, '\') . '$', '', 'g') let str .= inner endfor else if settings.html.indent_blockelement && len(current_name) > 0 && stridx(','.settings.html.inline_elements.',', ','.current_name.',') == -1 || settings.html.block_all_childless let str .= "\n" . indent . '${cursor}' . "\n" else let str .= '${cursor}' endif endif if dr let str .= "\n" endif let str .= '' endif if len(comment) > 0 if ct ==# 'lastonly' let str .= '' else let str .= "\n' endif endif if len(current_name) > 0 && current.multiplier > 0 || stridx(','.settings.html.block_elements.',', ','.current_name.',') != -1 let str .= "\n" endif return str endfunction function! emmet#lang#html#imageSize() abort let img_region = emmet#util#searchRegion('') if !emmet#util#regionIsValid(img_region) || !emmet#util#cursorInRegion(img_region) return endif let content = emmet#util#getContent(img_region) if content !~# '^<]\+>$' return endif let current = emmet#lang#html#parseTag(content) if empty(current) || !has_key(current.attr, 'src') return endif let fn = current.attr.src if fn =~# '^\s*$' return elseif fn !~# '^\(/\|http\)' let fn = simplify(expand('%:h') . '/' . fn) endif let [width, height] = emmet#util#getImageSize(fn) if width == -1 && height == -1 return endif let current.attr.width = width let current.attr.height = height let current.attrs_order += ['width', 'height'] let html = substitute(emmet#toString(current, 'html', 1), '\n', '', '') let html = substitute(html, '\${cursor}', '', '') call emmet#util#setContent(img_region, html) endfunction function! emmet#lang#html#imageEncode() abort let img_region = emmet#util#searchRegion('') if !emmet#util#regionIsValid(img_region) || !emmet#util#cursorInRegion(img_region) return endif let content = emmet#util#getContent(img_region) if content !~# '^<]\+>$' return endif let current = emmet#lang#html#parseTag(content) if empty(current) || !has_key(current.attr, 'src') return endif let fn = current.attr.src if fn =~# '^\s*$' return elseif fn !~# '^\(/\|http\)' let fn = simplify(expand('%:h') . '/' . fn) endif let encoded = emmet#util#imageEncodeDecode(fn, 0) let current.attr.src = encoded let content = substitute(emmet#toString(current, 'html', 1), '\n', '', '') let content = substitute(content, '\${cursor}', '', '') call emmet#util#setContent(img_region, content) endfunction function! emmet#lang#html#parseTag(tag) abort let current = emmet#newNode() let mx = '<\([a-zA-Z][a-zA-Z0-9]*\)\(\%(\s[a-zA-Z][a-zA-Z0-9]\+=\?\%([^"'' \t]\+\|"[^"]\{-}"\|''[^'']\{-}''\)\s*\)*\)\(/\{0,1}\)>' let match = matchstr(a:tag, mx) let current.name = substitute(match, mx, '\1', 'i') let attrs = substitute(match, mx, '\2', 'i') let mx = '\([a-zA-Z0-9]\+\)\(\(=[^"'' \t]\+\)\|="\([^"]\{-}\)"\|=''\([^'']\{-}\)''\)\?' while len(attrs) > 0 let match = matchstr(attrs, mx) if len(match) == 0 break endif let attr_match = matchlist(match, mx) let name = attr_match[1] if len(attr_match[2]) let Val = len(attr_match[3]) ? attr_match[3] : attr_match[4] else let Val = function('emmet#types#true') endif let current.attr[name] = Val let current.attrs_order += [name] let attrs = attrs[stridx(attrs, match) + len(match):] endwhile return current endfunction function! emmet#lang#html#toggleComment() abort let orgpos = getpos('.') let curpos = getpos('.') let mx = '<\%#[^>]*>' while 1 let block = emmet#util#searchRegion('') if emmet#util#regionIsValid(block) let block[1][1] += 2 let content = emmet#util#getContent(block) let content = substitute(content, '^$', '\1', '') call emmet#util#setContent(block, content) silent! call setpos('.', orgpos) return endif let block = emmet#util#searchRegion('<[^>]', '>') if !emmet#util#regionIsValid(block) let pos1 = searchpos('<', 'bcW') if pos1[0] == 0 && pos1[1] == 0 return endif let curpos = getpos('.') continue endif let pos1 = block[0] let pos2 = block[1] let content = emmet#util#getContent(block) let tag_name = matchstr(content, '^<\zs/\{0,1}[^ \r\n>]\+') if tag_name[0] ==# '/' call setpos('.', [0, pos1[0], pos1[1], 0]) let pos2 = searchpairpos('<'. tag_name[1:] . '\>[^/>]*>', '', '', 'bnW') let pos1 = searchpos('>', 'cneW') let block = [pos2, pos1] elseif tag_name =~# '/$' if !emmet#util#pointInRegion(orgpos[1:2], block) " it's broken tree call setpos('.', orgpos) let block = emmet#util#searchRegion('>', '<') let content = '><' call emmet#util#setContent(block, content) silent! call setpos('.', orgpos) return endif else call setpos('.', [0, pos2[0], pos2[1], 0]) let pos3 = searchpairpos('<'. tag_name . '\>[^/>]*>', '', '', 'nW') if pos3 == [0, 0] let block = [pos1, pos2] else call setpos('.', [0, pos3[0], pos3[1], 0]) let pos2 = searchpos('>', 'neW') let block = [pos1, pos2] endif endif if !emmet#util#regionIsValid(block) silent! call setpos('.', orgpos) return endif if emmet#util#pointInRegion(curpos[1:2], block) let content = '' call emmet#util#setContent(block, content) silent! call setpos('.', orgpos) return endif endwhile endfunction function! emmet#lang#html#balanceTag(flag) range abort let vblock = emmet#util#getVisualBlock() let curpos = emmet#util#getcurpos() let settings = emmet#getSettings() if a:flag > 0 let mx = '<\([a-zA-Z][a-zA-Z0-9:_\-]*\)[^>]*' let last = curpos[1:2] while 1 let pos1 = searchpos(mx, 'bW') let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx) let tag_name = matchstr(content, '^<\zs[a-zA-Z0-9:_\-]*\ze') if stridx(','.settings.html.empty_elements.',', ','.tag_name.',') != -1 let pos2 = searchpos('>', 'nW') else let pos2 = searchpairpos('<' . tag_name . '[^>]*>', '', '', 'nW') endif let block = [pos1, pos2] if pos1 == [0, 0] break endif if emmet#util#pointInRegion(last, block) && emmet#util#regionIsValid(block) call emmet#util#selectRegion(block) return endif if pos1 == last break endif let last = pos1 endwhile else let mx = '<\([a-zA-Z][a-zA-Z0-9:_\-]*\)[^>]*>' while 1 let pos1 = searchpos(mx, 'W') if pos1 == [0, 0] || pos1 == curpos[1:2] let pos1 = searchpos('>\zs', 'W') let pos2 = searchpos('.\ze<', 'W') let block = [pos1, pos2] if emmet#util#regionIsValid(block) call emmet#util#selectRegion(block) return endif endif let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx) let tag_name = matchstr(content, '^<\zs[a-zA-Z0-9:_\-]*\ze') if stridx(','.settings.html.empty_elements.',', ','.tag_name.',') != -1 let pos2 = searchpos('>', 'nW') else let pos2 = searchpairpos('<' . tag_name . '[^>]*>', '', '', 'nW') endif let block = [pos1, pos2] if pos1 == [0, 0] break endif if emmet#util#regionIsValid(block) call emmet#util#selectRegion(block) return endif endwhile endif call setpos('.', curpos) endfunction function! emmet#lang#html#moveNextPrevItem(flag) abort silent! exe "normal \" let mx = '\%([0-9a-zA-Z-:]\+\%(="[^"]*"\|=''[^'']*''\|[^ ''">\]]*\)\{0,1}\)' let pos = searchpos('\s'.mx.'\zs', '') if pos != [0,0] call feedkeys('v?\s\zs'.mx."\", '') endif return '' endfunction function! emmet#lang#html#moveNextPrev(flag) abort let pos = search('\%(<\/\|\(""\)\|^\(\s*\)$', a:flag ? 'Wpb' : 'Wp') if pos == 3 startinsert! elseif pos != 0 silent! normal! l startinsert endif return '' endfunction function! emmet#lang#html#splitJoinTag() abort let curpos = emmet#util#getcurpos() let mx = '<\(/\{0,1}[a-zA-Z][-a-zA-Z0-9:_\-]*\)\%(\%(\s[a-zA-Z][a-zA-Z0-9]\+=\%([^"'' \t]\+\|"[^"]\{-}"\|''[^'']\{-}''\)\s*\)*\)\s*\%(/\{0,1}\)>' while 1 let old = getpos('.')[1:2] let pos1 = searchpos(mx, 'bcnW') let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx) let tag_name = substitute(content, '^<\(/\{0,1}[a-zA-Z][a-zA-Z0-9:_\-]*\).*$', '\1', '') let block = [pos1, [pos1[0], pos1[1] + len(content) - 1]] if content[-2:] ==# '/>' && emmet#util#cursorInRegion(block) let content = substitute(content[:-3], '\s*$', '', '') . '>' call emmet#util#setContent(block, content) call setpos('.', [0, block[0][0], block[0][1], 0]) return endif if tag_name[0] ==# '/' let pos1 = searchpos('<' . tag_name[1:] . '[^a-zA-Z0-9]', 'bcnW') call setpos('.', [0, pos1[0], pos1[1], 0]) let pos2 = searchpairpos('<'. tag_name[1:] . '\>[^/>]*>', '', '', 'W') else let pos2 = searchpairpos('<'. tag_name . '[^/>]*>', '', '', 'W') endif if pos2 == [0, 0] return endif let pos2 = searchpos('>', 'neW') let block = [pos1, pos2] if emmet#util#pointInRegion(curpos[1:2], block) let content = matchstr(content, mx)[:-2] . ' />' call emmet#util#setContent(block, content) call setpos('.', [0, block[0][0], block[0][1], 0]) return endif if block[0][0] > 0 call setpos('.', [0, block[0][0]-1, block[0][1], 0]) else call setpos('.', curpos) return endif if pos1 == old call setpos('.', curpos) return endif endwhile endfunction function! emmet#lang#html#removeTag() abort let curpos = emmet#util#getcurpos() let mx = '<\(/\{0,1}[a-zA-Z][-a-zA-Z0-9:_\-]*\)\%(\%(\s[a-zA-Z][a-zA-Z0-9]\+=\%([^"'' \t]\+\|"[^"]\{-}"\|''[^'']\{-}''\)\s*\)*\)\s*\%(/\{0,1}\)>' let pos1 = searchpos(mx, 'bcnW') let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx) let tag_name = substitute(content, '^<\(/\{0,1}[a-zA-Z][a-zA-Z0-9:_\-]*\).*$', '\1', '') let block = [pos1, [pos1[0], pos1[1] + len(content) - 1]] if content[-2:] ==# '/>' && emmet#util#cursorInRegion(block) call emmet#util#setContent(block, '') call setpos('.', [0, block[0][0], block[0][1], 0]) return endif if tag_name[0] ==# '/' let pos1 = searchpos('<' . tag_name[1:] . '[^a-zA-Z0-9]', 'bcnW') call setpos('.', [0, pos1[0], pos1[1], 0]) let pos2 = searchpairpos('<'. tag_name[1:] . '\>[^/>]*>', '', '', 'W') else let pos2 = searchpairpos('<'. tag_name . '[^/>]*>', '', '', 'W') endif if pos2 == [0, 0] return endif let pos2 = searchpos('>', 'neW') let block = [pos1, pos2] if emmet#util#pointInRegion(curpos[1:2], block) call emmet#util#setContent(block, '') call setpos('.', [0, block[0][0], block[0][1], 0]) return endif if block[0][0] > 0 call setpos('.', [0, block[0][0]-1, block[0][1], 0]) else call setpos('.', curpos) endif endfunction function! emmet#lang#html#mergeLines() abort let curpos = emmet#util#getcurpos() let settings = emmet#getSettings() let mx = '<\([a-zA-Z][a-zA-Z0-9:_\-]*\)[^>]*>' let last = curpos[1:2] while 1 let pos1 = searchpos(mx, 'bcW') let content = matchstr(getline(pos1[0])[pos1[1]-1:], mx) echomsg string(content) let tag_name = matchstr(content, '^<\zs[a-zA-Z0-9:_\-]*\ze') if stridx(','.settings.html.empty_elements.',', ','.tag_name.',') != -1 let pos2 = searchpos('>', 'nW') else let pos2 = searchpairpos('<' . tag_name . '[^>]*>', '', '', 'nW') endif if pos1 == [0, 0] || pos2 == [0, 0] call setpos('.', curpos) return endif let block = [pos1, pos2] if emmet#util#pointInRegion(last, block) && emmet#util#regionIsValid(block) break endif if pos1 == last call setpos('.', curpos) return endif let last = pos1 endwhile let content = emmet#util#getContent(block) let mx = '<\(/\{0,1}[a-zA-Z][-a-zA-Z0-9:_\-]*\)\%(\%(\s[a-zA-Z][a-zA-Z0-9]\+=\%([^"'' \t]\+\|"[^"]\{-}"\|''[^'']\{-}''\)\s*\)*\)\s*\%(/\{0,1}\)>' let content = join(map(split(content, mx . '\zs\s*'), 'trim(v:val)'), '') call emmet#util#setContent(block, content) if block[0][0] > 0 call setpos('.', [0, block[0][0], block[0][1], 0]) else call setpos('.', curpos) endif endfunction