diff --git a/ftplugin/xml.vim b/ftplugin/xml.vim index 59bb03d..707c23d 100644 --- a/ftplugin/xml.vim +++ b/ftplugin/xml.vim @@ -556,6 +556,59 @@ if !exists("*s:MoveCursor") endfunction endif +" XML formatter +if !exists("*s:FormatXML") + function! s:FormatXML() range + " Save the file type + let l:origft = &ft + + " Clean the file type + set ft= + + " Add fake initial tag (so we can process multiple top-level elements) + exe ":let l:beforeFirstLine=" . a:firstline . "-1" + if l:beforeFirstLine < 0 + let l:beforeFirstLine=0 + endif + exe a:lastline . "put =''" + exe l:beforeFirstLine . "put =''" + exe ":let l:newLastLine=" . a:lastline . "+2" + if l:newLastLine > line('$') + let l:newLastLine=line('$') + endif + + " Remove XML header + exe ":" . a:firstline . "," . a:lastline . "s/<\?xml\\_.*\?>\\_s*//e" + + " Recalculate last line of the edited code + let l:newLastLine=search('') + + " Execute external formatter + exe ":silent " . a:firstline . "," . l:newLastLine . "!xmllint --noblanks --format --recover -" + + " Recalculate first and last lines of the edited code + let l:newFirstLine=search('') + let l:newLastLine=search('') + + " Get inner range + let l:innerFirstLine=l:newFirstLine+1 + let l:innerLastLine=l:newLastLine-1 + + " Remove extra unnecessary indentation + exe ":silent " . l:innerFirstLine . "," . l:innerLastLine "s/^ //e" + + " Remove fake tag + exe l:newLastLine . "d" + exe l:newFirstLine . "d" + + " Put the cursor at the first line of the edited code + exe ":" . l:newFirstLine + + " Restore the file type + exe "set ft=" . l:origft + endfunction +endif + " Mappings and Settings. {{{1 " This makes the '%' jump between the start and end of a single tag. setlocal matchpairs+=<:> @@ -599,6 +652,10 @@ nnoremap w :call ClearJumpMarks() " The syntax files clear out any predefined syntax definitions. Recreate " this when ever a xml_jump_string is created. (in ParseTag) +" Format XML +nnoremap x :call FormatXML() +vnoremap x :call FormatXML() + augroup xml au! au BufNewFile * call NewFileXML()