Mercurial > vim
comparison runtime/autoload/xmlformat.vim @ 18456:6d11fc4aa683
Update runtime files
Commit: https://github.com/vim/vim/commit/96f45c0b6fc9e9d404e6805593ed1e0e6795e470
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Oct 26 19:53:45 2019 +0200
Update runtime files
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 26 Oct 2019 20:00:04 +0200 |
parents | bc1a8d21c811 |
children | d4deb2e50667 |
comparison
equal
deleted
inserted
replaced
18455:3c98dfd2380c | 18456:6d11fc4aa683 |
---|---|
1 " Vim plugin for formatting XML | 1 " Vim plugin for formatting XML |
2 " Last Change: Thu, 07 Dec 2018 | 2 " Last Change: 2019 Oct 24 |
3 " Version: 0.1 | 3 " Version: 0.2 |
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 " --------------------------------------------------------------------- |
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 |
24 endif | 24 endif |
25 let count_orig = v:count | |
25 let sw = shiftwidth() | 26 let sw = shiftwidth() |
26 let prev = prevnonblank(v:lnum-1) | 27 let prev = prevnonblank(v:lnum-1) |
27 let s:indent = indent(prev)/sw | 28 let s:indent = indent(prev)/sw |
28 let result = [] | 29 let result = [] |
29 let lastitem = prev ? getline(prev) : '' | 30 let lastitem = prev ? getline(prev) : '' |
30 let is_xml_decl = 0 | 31 let is_xml_decl = 0 |
31 " split on `<`, but don't split on very first opening < | 32 " go through every line, but don't join all content together and join it |
32 for item in split(join(getline(v:lnum, (v:lnum + v:count - 1))), '.\@<=[>]\zs') | 33 " back. We might lose empty lines |
33 if s:EndTag(item) | 34 let list = getline(v:lnum, (v:lnum + count_orig - 1)) |
34 let s:indent = s:DecreaseIndent() | 35 let current = 0 |
35 call add(result, s:Indent(item)) | 36 for line in list |
36 elseif s:EmptyTag(lastitem) | 37 " Keep empty input lines? |
37 call add(result, s:Indent(item)) | 38 if empty(line) |
38 elseif s:StartTag(lastitem) && s:IsTag(item) | 39 call add(result, '') |
39 let s:indent += 1 | 40 continue |
40 call add(result, s:Indent(item)) | 41 elseif line !~# '<[/]\?[^>]*>' |
41 else | 42 let nextmatch = match(list, '<[/]\?[^>]*>', current) |
42 if !s:IsTag(item) | 43 let line .= join(list[(current + 1):(nextmatch-1)], "\n") |
43 " Simply split on '<' | 44 call remove(list, current+1, nextmatch-1) |
44 let t=split(item, '.<\@=\zs') | 45 endif |
45 let s:indent+=1 | 46 " split on `>`, but don't split on very first opening < |
46 call add(result, s:Indent(t[0])) | 47 " this means, items can be like ['<tag>', 'tag content</tag>'] |
47 let s:indent = s:DecreaseIndent() | 48 for item in split(line, '.\@<=[>]\zs') |
48 call add(result, s:Indent(t[1])) | 49 if s:EndTag(item) |
49 else | 50 let s:indent = s:DecreaseIndent() |
50 call add(result, s:Indent(item)) | 51 call add(result, s:Indent(item)) |
52 elseif s:EmptyTag(lastitem) | |
53 call add(result, s:Indent(item)) | |
54 elseif s:StartTag(lastitem) && s:IsTag(item) | |
55 let s:indent += 1 | |
56 call add(result, s:Indent(item)) | |
57 else | |
58 if !s:IsTag(item) | |
59 " Simply split on '<', if there is one, | |
60 " but reformat according to &textwidth | |
61 let t=split(item, '.<\@=\zs') | |
62 " t should only contain 2 items, but just be safe here | |
63 if s:IsTag(lastitem) | |
64 let s:indent+=1 | |
65 endif | |
66 let result+=s:FormatContent([t[0]]) | |
67 if s:EndTag(t[1]) | |
68 let s:indent = s:DecreaseIndent() | |
69 endif | |
70 "for y in t[1:] | |
71 let result+=s:FormatContent(t[1:]) | |
72 "endfor | |
73 else | |
74 call add(result, s:Indent(item)) | |
75 endif | |
51 endif | 76 endif |
52 endif | 77 let lastitem = item |
53 let lastitem = item | 78 endfor |
54 endfor | 79 let current += 1 |
80 endfor | |
55 | 81 |
56 if !empty(result) | 82 if !empty(result) |
57 exe v:lnum. ",". (v:lnum + v:count - 1). 'd' | 83 let lastprevline = getline(v:lnum + count_orig) |
84 let delete_lastline = v:lnum + count_orig - 1 == line('$') | |
85 exe v:lnum. ",". (v:lnum + count_orig - 1). 'd' | |
58 call append(v:lnum - 1, result) | 86 call append(v:lnum - 1, result) |
59 " Might need to remove the last line, if it became empty because of the | 87 " Might need to remove the last line, if it became empty because of the |
60 " append() call | 88 " append() call |
61 let last = v:lnum + len(result) | 89 let last = v:lnum + len(result) |
62 if getline(last) is '' | 90 " do not use empty(), it returns true for `empty(0)` |
91 if getline(last) is '' && lastprevline is '' && delete_lastline | |
63 exe last. 'd' | 92 exe last. 'd' |
64 endif | 93 endif |
65 endif | 94 endif |
66 | 95 |
67 " do not run internal formatter! | 96 " do not run internal formatter! |
86 " Check if tag is a new opening tag <tag> {{{1 | 115 " Check if tag is a new opening tag <tag> {{{1 |
87 func! s:StartTag(tag) | 116 func! s:StartTag(tag) |
88 let is_comment = s:IsComment(a:tag) | 117 let is_comment = s:IsComment(a:tag) |
89 return a:tag =~? '^\s*<[^/?]' && !is_comment | 118 return a:tag =~? '^\s*<[^/?]' && !is_comment |
90 endfunc | 119 endfunc |
120 " Check if tag is a Comment start {{{1 | |
91 func! s:IsComment(tag) | 121 func! s:IsComment(tag) |
92 return a:tag =~? '<!--' | 122 return a:tag =~? '<!--' |
93 endfunc | 123 endfunc |
94 " Remove one level of indentation {{{1 | 124 " Remove one level of indentation {{{1 |
95 func! s:DecreaseIndent() | 125 func! s:DecreaseIndent() |
106 endfunc | 136 endfunc |
107 " Check if tag is empty <tag/> {{{1 | 137 " Check if tag is empty <tag/> {{{1 |
108 func! s:EmptyTag(tag) | 138 func! s:EmptyTag(tag) |
109 return a:tag =~ '/>\s*$' | 139 return a:tag =~ '/>\s*$' |
110 endfunc | 140 endfunc |
141 " Format input line according to textwidth {{{1 | |
142 func! s:FormatContent(list) | |
143 let result=[] | |
144 let limit = 80 | |
145 if &textwidth > 0 | |
146 let limit = &textwidth | |
147 endif | |
148 let column=0 | |
149 let idx = -1 | |
150 let add_indent = 0 | |
151 let cnt = 0 | |
152 for item in a:list | |
153 for word in split(item, '\s\+\S\+\zs') | |
154 let column += strdisplaywidth(word, column) | |
155 if match(word, "^\\s*\n\\+\\s*$") > -1 | |
156 call add(result, '') | |
157 let idx += 1 | |
158 let column = 0 | |
159 let add_indent = 1 | |
160 elseif column > limit || cnt == 0 | |
161 let add = s:Indent(s:Trim(word)) | |
162 call add(result, add) | |
163 let column = strdisplaywidth(add) | |
164 let idx += 1 | |
165 else | |
166 if add_indent | |
167 let result[idx] = s:Indent(s:Trim(word)) | |
168 else | |
169 let result[idx] .= ' '. s:Trim(word) | |
170 endif | |
171 let add_indent = 0 | |
172 endif | |
173 let cnt += 1 | |
174 endfor | |
175 endfor | |
176 return result | |
177 endfunc | |
111 " Restoration And Modelines: {{{1 | 178 " Restoration And Modelines: {{{1 |
112 let &cpo= s:keepcpo | 179 let &cpo= s:keepcpo |
113 unlet s:keepcpo | 180 unlet s:keepcpo |
114 " Modeline {{{1 | 181 " Modeline {{{1 |
115 " vim: fdm=marker fdl=0 ts=2 et sw=0 sts=-1 | 182 " vim: fdm=marker fdl=0 ts=2 et sw=0 sts=-1 |