comparison runtime/autoload/xmlformat.vim @ 19574:d4deb2e50667

Update runtime files Commit: https://github.com/vim/vim/commit/eab6dff19f387469a200011bc6cf3508f5e43a4a Author: Bram Moolenaar <Bram@vim.org> Date: Sun Mar 1 19:06:45 2020 +0100 Update runtime files
author Bram Moolenaar <Bram@vim.org>
date Sun, 01 Mar 2020 19:15:04 +0100
parents 6d11fc4aa683
children
comparison
equal deleted inserted replaced
19573:9d0db06b6ad2 19574:d4deb2e50667
1 " Vim plugin for formatting XML 1 " Vim plugin for formatting XML
2 " Last Change: 2019 Oct 24 2 " Last Change: 2020 Jan 06
3 " Version: 0.2 3 " Version: 0.3
4 " Author: Christian Brabandt <cb@256bit.org> 4 " Author: Christian Brabandt <cb@256bit.org>
5 " Repository: https://github.com/chrisbra/vim-xml-ftplugin 5 " Repository: https://github.com/chrisbra/vim-xml-ftplugin
6 " License: VIM License 6 " License: VIM License
7 " Documentation: see :h xmlformat.txt (TODO!) 7 " Documentation: see :h xmlformat.txt (TODO!)
8 " --------------------------------------------------------------------- 8 " ---------------------------------------------------------------------
13 let g:loaded_xmlformat = 1 13 let g:loaded_xmlformat = 1
14 let s:keepcpo = &cpo 14 let s:keepcpo = &cpo
15 set cpo&vim 15 set cpo&vim
16 16
17 " Main function: Format the input {{{1 17 " Main function: Format the input {{{1
18 func! xmlformat#Format() 18 func! xmlformat#Format() abort
19 " only allow reformatting through the gq command 19 " only allow reformatting through the gq command
20 " (e.g. Vim is in normal mode) 20 " (e.g. Vim is in normal mode)
21 if mode() != 'n' 21 if mode() != 'n'
22 " do not fall back to internal formatting 22 " do not fall back to internal formatting
23 return 0 23 return 0
38 if empty(line) 38 if empty(line)
39 call add(result, '') 39 call add(result, '')
40 continue 40 continue
41 elseif line !~# '<[/]\?[^>]*>' 41 elseif line !~# '<[/]\?[^>]*>'
42 let nextmatch = match(list, '<[/]\?[^>]*>', current) 42 let nextmatch = match(list, '<[/]\?[^>]*>', current)
43 let line .= join(list[(current + 1):(nextmatch-1)], "\n") 43 if nextmatch > -1
44 call remove(list, current+1, nextmatch-1) 44 let line .= ' '. join(list[(current + 1):(nextmatch-1)], " ")
45 call remove(list, current+1, nextmatch-1)
46 endif
45 endif 47 endif
46 " split on `>`, but don't split on very first opening < 48 " split on `>`, but don't split on very first opening <
47 " this means, items can be like ['<tag>', 'tag content</tag>'] 49 " this means, items can be like ['<tag>', 'tag content</tag>']
48 for item in split(line, '.\@<=[>]\zs') 50 for item in split(line, '.\@<=[>]\zs')
49 if s:EndTag(item) 51 if s:EndTag(item)
50 let s:indent = s:DecreaseIndent() 52 call s:DecreaseIndent()
51 call add(result, s:Indent(item)) 53 call add(result, s:Indent(item))
52 elseif s:EmptyTag(lastitem) 54 elseif s:EmptyTag(lastitem)
53 call add(result, s:Indent(item)) 55 call add(result, s:Indent(item))
54 elseif s:StartTag(lastitem) && s:IsTag(item) 56 elseif s:StartTag(lastitem) && s:IsTag(item)
55 let s:indent += 1 57 let s:indent += 1
57 else 59 else
58 if !s:IsTag(item) 60 if !s:IsTag(item)
59 " Simply split on '<', if there is one, 61 " Simply split on '<', if there is one,
60 " but reformat according to &textwidth 62 " but reformat according to &textwidth
61 let t=split(item, '.<\@=\zs') 63 let t=split(item, '.<\@=\zs')
64
65 " if the content fits well within a single line, add it there
66 " so that the output looks like this:
67 "
68 " <foobar>1</foobar>
69 if s:TagContent(lastitem) is# s:TagContent(t[1]) && strlen(result[-1]) + strlen(item) <= s:Textwidth()
70 let result[-1] .= item
71 let lastitem = t[1]
72 continue
73 endif
62 " t should only contain 2 items, but just be safe here 74 " t should only contain 2 items, but just be safe here
63 if s:IsTag(lastitem) 75 if s:IsTag(lastitem)
64 let s:indent+=1 76 let s:indent+=1
65 endif 77 endif
66 let result+=s:FormatContent([t[0]]) 78 let result+=s:FormatContent([t[0]])
67 if s:EndTag(t[1]) 79 if s:EndTag(t[1])
68 let s:indent = s:DecreaseIndent() 80 call s:DecreaseIndent()
69 endif 81 endif
70 "for y in t[1:] 82 "for y in t[1:]
71 let result+=s:FormatContent(t[1:]) 83 let result+=s:FormatContent(t[1:])
72 "endfor 84 "endfor
73 else 85 else
95 107
96 " do not run internal formatter! 108 " do not run internal formatter!
97 return 0 109 return 0
98 endfunc 110 endfunc
99 " Check if given tag is XML Declaration header {{{1 111 " Check if given tag is XML Declaration header {{{1
100 func! s:IsXMLDecl(tag) 112 func! s:IsXMLDecl(tag) abort
101 return a:tag =~? '^\s*<?xml\s\?\%(version="[^"]*"\)\?\s\?\%(encoding="[^"]*"\)\? ?>\s*$' 113 return a:tag =~? '^\s*<?xml\s\?\%(version="[^"]*"\)\?\s\?\%(encoding="[^"]*"\)\? ?>\s*$'
102 endfunc 114 endfunc
103 " Return tag indented by current level {{{1 115 " Return tag indented by current level {{{1
104 func! s:Indent(item) 116 func! s:Indent(item) abort
105 return repeat(' ', shiftwidth()*s:indent). s:Trim(a:item) 117 return repeat(' ', shiftwidth()*s:indent). s:Trim(a:item)
106 endfu 118 endfu
107 " Return item trimmed from leading whitespace {{{1 119 " Return item trimmed from leading whitespace {{{1
108 func! s:Trim(item) 120 func! s:Trim(item) abort
109 if exists('*trim') 121 if exists('*trim')
110 return trim(a:item) 122 return trim(a:item)
111 else 123 else
112 return matchstr(a:item, '\S\+.*') 124 return matchstr(a:item, '\S\+.*')
113 endif 125 endif
114 endfunc 126 endfunc
115 " Check if tag is a new opening tag <tag> {{{1 127 " Check if tag is a new opening tag <tag> {{{1
116 func! s:StartTag(tag) 128 func! s:StartTag(tag) abort
117 let is_comment = s:IsComment(a:tag) 129 let is_comment = s:IsComment(a:tag)
118 return a:tag =~? '^\s*<[^/?]' && !is_comment 130 return a:tag =~? '^\s*<[^/?]' && !is_comment
119 endfunc 131 endfunc
120 " Check if tag is a Comment start {{{1 132 " Check if tag is a Comment start {{{1
121 func! s:IsComment(tag) 133 func! s:IsComment(tag) abort
122 return a:tag =~? '<!--' 134 return a:tag =~? '<!--'
123 endfunc 135 endfunc
124 " Remove one level of indentation {{{1 136 " Remove one level of indentation {{{1
125 func! s:DecreaseIndent() 137 func! s:DecreaseIndent() abort
126 return (s:indent > 0 ? s:indent - 1 : 0) 138 let s:indent = (s:indent > 0 ? s:indent - 1 : 0)
127 endfunc 139 endfunc
128 " Check if tag is a closing tag </tag> {{{1 140 " Check if tag is a closing tag </tag> {{{1
129 func! s:EndTag(tag) 141 func! s:EndTag(tag) abort
130 return a:tag =~? '^\s*</' 142 return a:tag =~? '^\s*</'
131 endfunc 143 endfunc
132 " Check that the tag is actually a tag and not {{{1 144 " Check that the tag is actually a tag and not {{{1
133 " something like "foobar</foobar>" 145 " something like "foobar</foobar>"
134 func! s:IsTag(tag) 146 func! s:IsTag(tag) abort
135 return s:Trim(a:tag)[0] == '<' 147 return s:Trim(a:tag)[0] == '<'
136 endfunc 148 endfunc
137 " Check if tag is empty <tag/> {{{1 149 " Check if tag is empty <tag/> {{{1
138 func! s:EmptyTag(tag) 150 func! s:EmptyTag(tag) abort
139 return a:tag =~ '/>\s*$' 151 return a:tag =~ '/>\s*$'
140 endfunc 152 endfunc
153 func! s:TagContent(tag) abort "{{{1
154 " Return content of a tag
155 return substitute(a:tag, '^\s*<[/]\?\([^>]*\)>\s*$', '\1', '')
156 endfunc
157 func! s:Textwidth() abort "{{{1
158 " return textwidth (or 80 if not set)
159 return &textwidth == 0 ? 80 : &textwidth
160 endfunc
141 " Format input line according to textwidth {{{1 161 " Format input line according to textwidth {{{1
142 func! s:FormatContent(list) 162 func! s:FormatContent(list) abort
143 let result=[] 163 let result=[]
144 let limit = 80 164 let limit = s:Textwidth()
145 if &textwidth > 0
146 let limit = &textwidth
147 endif
148 let column=0 165 let column=0
149 let idx = -1 166 let idx = -1
150 let add_indent = 0 167 let add_indent = 0
151 let cnt = 0 168 let cnt = 0
152 for item in a:list 169 for item in a:list
153 for word in split(item, '\s\+\S\+\zs') 170 for word in split(item, '\s\+\S\+\zs')
171 if match(word, '^\s\+$') > -1
172 " skip empty words
173 continue
174 endif
154 let column += strdisplaywidth(word, column) 175 let column += strdisplaywidth(word, column)
155 if match(word, "^\\s*\n\\+\\s*$") > -1 176 if match(word, "^\\s*\n\\+\\s*$") > -1
156 call add(result, '') 177 call add(result, '')
157 let idx += 1 178 let idx += 1
158 let column = 0 179 let column = 0