Mercurial > vim
annotate runtime/indent/xml.vim @ 34625:ad1b0609b2f8 v9.1.0201
patch 9.1.0201: gM not working correctly with virt text
Commit: https://github.com/vim/vim/commit/366c81a2005370ac738618d889ec0337397a9f96
Author: Dylan Thacker-Smith <dylan.ah.smith@gmail.com>
Date: Sun Mar 24 09:46:56 2024 +0100
patch 9.1.0201: gM not working correctly with virt text
Problem: `gM` would include outer virtual text and its padding when
getting the line length used to calculate the middle of the
line, putting the cursor much closer to virtual text lines.
Solution: Exclude outer virtual text in getting the line length for
`gM`, so that virtual text doesn't influence where the cursor
is moved to (Dylan Thacker-Smith).
closes: #14262
Signed-off-by: Dylan Thacker-Smith <dylan.ah.smith@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 24 Mar 2024 10:00:07 +0100 |
parents | f0d7cb510ce3 |
children |
rev | line source |
---|---|
18456 | 1 " Language: XML |
2 " Maintainer: Christian Brabandt <cb@256bit.org> | |
3 " Repository: https://github.com/chrisbra/vim-xml-ftplugin | |
4 " Previous Maintainer: Johannes Zellner <johannes@zellner.org> | |
23047 | 5 " Last Changed: 2020 Nov 4th |
15194 | 6 " Last Change: |
23047 | 7 " 20200529 - Handle empty closing tags correctly |
18790 | 8 " 20191202 - Handle docbk filetype |
17571 | 9 " 20190726 - Correctly handle non-tagged data |
16086 | 10 " 20190204 - correctly handle wrap tags |
11 " https://github.com/chrisbra/vim-xml-ftplugin/issues/5 | |
15729 | 12 " 20190128 - Make sure to find previous tag |
13 " https://github.com/chrisbra/vim-xml-ftplugin/issues/4 | |
15194 | 14 " 20181116 - Fix indentation when tags start with a colon or an underscore |
15 " https://github.com/vim/vim/pull/926 | |
16 " 20181022 - Do not overwrite indentkeys setting | |
17 " https://github.com/chrisbra/vim-xml-ftplugin/issues/1 | |
18 " 20180724 - Correctly indent xml comments https://github.com/vim/vim/issues/3200 | |
19 " | |
20 " Notes: | |
21 " 1) does not indent pure non-xml code (e.g. embedded scripts) | |
22 " 2) will be confused by unbalanced tags in comments | |
23 " or CDATA sections. | |
24 " 2009-05-26 patch by Nikolai Weibull | |
25 " TODO: implement pre-like tags, see xml_indent_open / xml_indent_close | |
7 | 26 |
27 " Only load this indent file when no other was loaded. | |
28 if exists("b:did_indent") | |
29 finish | |
30 endif | |
31 let b:did_indent = 1 | |
3526
dd6c2497c997
Fix more 'cpo' issues in runtime files.
Bram Moolenaar <bram@vim.org>
parents:
2034
diff
changeset
|
32 let s:keepcpo= &cpo |
dd6c2497c997
Fix more 'cpo' issues in runtime files.
Bram Moolenaar <bram@vim.org>
parents:
2034
diff
changeset
|
33 set cpo&vim |
7 | 34 |
35 " [-- local settings (must come before aborting the script) --] | |
15194 | 36 " Attention: Parameter use_syntax_check is used by the docbk.vim indent script |
7 | 37 setlocal indentexpr=XmlIndentGet(v:lnum,1) |
14999 | 38 setlocal indentkeys=o,O,*<Return>,<>>,<<>,/,{,},!^F |
17571 | 39 " autoindent: used when the indentexpr returns -1 |
40 setlocal autoindent | |
7 | 41 |
26708 | 42 let b:undo_indent = "setl ai< inde< indk<" |
43 | |
7 | 44 if !exists('b:xml_indent_open') |
15194 | 45 let b:xml_indent_open = '.\{-}<[:A-Z_a-z]' |
7 | 46 " pre tag, e.g. <address> |
47 " let b:xml_indent_open = '.\{-}<[/]\@!\(address\)\@!' | |
48 endif | |
49 | |
50 if !exists('b:xml_indent_close') | |
23047 | 51 let b:xml_indent_close = '.\{-}</\|/>.\{-}' |
7 | 52 " end pre tag, e.g. </address> |
53 " let b:xml_indent_close = '.\{-}</\(address\)\@!' | |
54 endif | |
55 | |
26708 | 56 if !exists('b:xml_indent_continuation_filetype') |
57 let b:xml_indent_continuation_filetype = 'xml' | |
58 endif | |
59 | |
3713 | 60 let &cpo = s:keepcpo |
61 unlet s:keepcpo | |
62 | |
7 | 63 " [-- finish, if the function already exists --] |
3713 | 64 if exists('*XmlIndentGet') |
15194 | 65 finish |
3713 | 66 endif |
67 | |
68 let s:keepcpo= &cpo | |
69 set cpo&vim | |
7 | 70 |
71 fun! <SID>XmlIndentWithPattern(line, pat) | |
72 let s = substitute('x'.a:line, a:pat, "\1", 'g') | |
73 return strlen(substitute(s, "[^\1].*$", '', '')) | |
74 endfun | |
75 | |
76 " [-- check if it's xml --] | |
77 fun! <SID>XmlIndentSynCheck(lnum) | |
15194 | 78 if &syntax != '' |
79 let syn1 = synIDattr(synID(a:lnum, 1, 1), 'name') | |
80 let syn2 = synIDattr(synID(a:lnum, strlen(getline(a:lnum)) - 1, 1), 'name') | |
81 if syn1 != '' && syn1 !~ 'xml' && syn2 != '' && syn2 !~ 'xml' | |
82 " don't indent pure non-xml code | |
83 return 0 | |
84 endif | |
7 | 85 endif |
86 return 1 | |
87 endfun | |
88 | |
89 " [-- return the sum of indents of a:lnum --] | |
16086 | 90 fun! <SID>XmlIndentSum(line, style, add) |
23047 | 91 if <SID>IsXMLContinuation(a:line) && a:style == 0 && !<SID>IsXMLEmptyClosingTag(a:line) |
16086 | 92 " no complete tag, add one additional indent level |
93 " but only for the current line | |
94 return a:add + shiftwidth() | |
95 elseif <SID>HasNoTagEnd(a:line) | |
96 " no complete tag, return initial indent | |
97 return a:add | |
98 endif | |
99 if a:style == match(a:line, '^\s*</') | |
15194 | 100 return (shiftwidth() * |
16086 | 101 \ (<SID>XmlIndentWithPattern(a:line, b:xml_indent_open) |
102 \ - <SID>XmlIndentWithPattern(a:line, b:xml_indent_close) | |
103 \ - <SID>XmlIndentWithPattern(a:line, '.\{-}/>'))) + a:add | |
7 | 104 else |
15194 | 105 return a:add |
7 | 106 endif |
107 endfun | |
108 | |
15194 | 109 " Main indent function |
7 | 110 fun! XmlIndentGet(lnum, use_syntax_check) |
111 " Find a non-empty line above the current line. | |
16086 | 112 if prevnonblank(a:lnum - 1) == 0 |
113 " Hit the start of the file, use zero indent. | |
15194 | 114 return 0 |
7 | 115 endif |
15729 | 116 " Find previous line with a tag (regardless whether open or closed, |
17571 | 117 " but always restrict the match to a line before the current one |
16086 | 118 " Note: xml declaration: <?xml version="1.0"?> |
119 " won't be found, as it is not a legal tag name | |
17571 | 120 let ptag_pattern = '\%(.\{-}<[/:A-Z_a-z]\)'. '\%(\&\%<'. a:lnum .'l\)' |
16086 | 121 let ptag = search(ptag_pattern, 'bnW') |
122 " no previous tag | |
123 if ptag == 0 | |
124 return 0 | |
125 endif | |
15729 | 126 |
17571 | 127 let pline = getline(ptag) |
128 let pind = indent(ptag) | |
129 | |
130 let syn_name_start = '' " Syntax element at start of line (excluding whitespace) | |
131 let syn_name_end = '' " Syntax element at end of line | |
132 let curline = getline(a:lnum) | |
7 | 133 if a:use_syntax_check |
16086 | 134 let check_lnum = <SID>XmlIndentSynCheck(ptag) |
15194 | 135 let check_alnum = <SID>XmlIndentSynCheck(a:lnum) |
136 if check_lnum == 0 || check_alnum == 0 | |
137 return indent(a:lnum) | |
138 endif | |
17571 | 139 let syn_name_end = synIDattr(synID(a:lnum, strlen(curline) - 1, 1), 'name') |
140 let syn_name_start = synIDattr(synID(a:lnum, match(curline, '\S') + 1, 1), 'name') | |
23047 | 141 let prev_syn_name_end = synIDattr(synID(ptag, strlen(pline) - 1, 1), 'name') |
142 " not needed (yet?) | |
143 " let prev_syn_name_start = synIDattr(synID(ptag, match(pline, '\S') + 1, 1), 'name') | |
7 | 144 endif |
145 | |
17571 | 146 if syn_name_end =~ 'Comment' && syn_name_start =~ 'Comment' |
147 return <SID>XmlIndentComment(a:lnum) | |
18790 | 148 elseif empty(syn_name_start) && empty(syn_name_end) && a:use_syntax_check |
17571 | 149 " non-xml tag content: use indent from 'autoindent' |
23047 | 150 if pline =~ b:xml_indent_close |
151 return pind | |
152 elseif !empty(prev_syn_name_end) | |
153 " only indent by an extra shiftwidth, if the previous line ends | |
154 " with an XML like tag | |
155 return pind + shiftwidth() | |
156 else | |
157 " no extra indent, looks like a text continuation line | |
158 return pind | |
159 endif | |
17571 | 160 endif |
161 | |
15194 | 162 " Get indent from previous tag line |
16086 | 163 let ind = <SID>XmlIndentSum(pline, -1, pind) |
15194 | 164 " Determine indent from current line |
17571 | 165 let ind = <SID>XmlIndentSum(curline, 0, ind) |
7 | 166 return ind |
167 endfun | |
168 | |
16086 | 169 func! <SID>IsXMLContinuation(line) |
170 " Checks, whether or not the line matches a start-of-tag | |
26708 | 171 return a:line !~ '^\s*<' && &ft =~# b:xml_indent_continuation_filetype |
16086 | 172 endfunc |
173 | |
174 func! <SID>HasNoTagEnd(line) | |
175 " Checks whether or not the line matches '>' (so finishes a tag) | |
176 return a:line !~ '>\s*$' | |
177 endfunc | |
178 | |
23047 | 179 func! <SID>IsXMLEmptyClosingTag(line) |
180 " Checks whether the line ends with an empty closing tag such as <lb/> | |
181 return a:line =~? '<[^>]*/>\s*$' | |
182 endfunc | |
183 | |
15194 | 184 " return indent for a commented line, |
17571 | 185 " the middle part might be indented one additional level |
15194 | 186 func! <SID>XmlIndentComment(lnum) |
23047 | 187 let ptagopen = search('.\{-}<[:A-Z_a-z]\_[^/]\{-}>.\{-}', 'bnW') |
16086 | 188 let ptagclose = search(b:xml_indent_close, 'bnW') |
15194 | 189 if getline(a:lnum) =~ '<!--' |
190 " if previous tag was a closing tag, do not add | |
191 " one additional level of indent | |
192 if ptagclose > ptagopen && a:lnum > ptagclose | |
23047 | 193 " If the previous tag was closed on the same line as it was |
194 " declared, we should indent with its indent level. | |
195 if !<SID>IsXMLContinuation(getline(ptagclose)) | |
196 return indent(ptagclose) | |
197 else | |
198 return indent(ptagclose) - shiftwidth() | |
199 endif | |
200 elseif ptagclose == ptagopen | |
15194 | 201 return indent(ptagclose) |
202 else | |
203 " start of comment, add one indentation level | |
204 return indent(ptagopen) + shiftwidth() | |
205 endif | |
206 elseif getline(a:lnum) =~ '-->' | |
207 " end of comment, same as start of comment | |
16086 | 208 return indent(search('<!--', 'bnW')) |
15194 | 209 else |
210 " middle part of comment, add one additional level | |
16086 | 211 return indent(search('<!--', 'bnW')) + shiftwidth() |
15194 | 212 endif |
213 endfunc | |
214 | |
3526
dd6c2497c997
Fix more 'cpo' issues in runtime files.
Bram Moolenaar <bram@vim.org>
parents:
2034
diff
changeset
|
215 let &cpo = s:keepcpo |
dd6c2497c997
Fix more 'cpo' issues in runtime files.
Bram Moolenaar <bram@vim.org>
parents:
2034
diff
changeset
|
216 unlet s:keepcpo |
dd6c2497c997
Fix more 'cpo' issues in runtime files.
Bram Moolenaar <bram@vim.org>
parents:
2034
diff
changeset
|
217 |
15194 | 218 " vim:ts=4 et sts=-1 sw=0 |