blob: cf76e69cc84ee2e5a3c5f2972f145cb00e90928b [file] [log] [blame]
Bram Moolenaarf75a9632005-09-13 21:20:47 +00001" Vim completion script
2" Language: XHTML 1.0 Strict
3" Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl )
Bram Moolenaarb8a7b562006-02-01 21:47:16 +00004" Last Change: 2006 Jan 30
Bram Moolenaarf75a9632005-09-13 21:20:47 +00005
6function! htmlcomplete#CompleteTags(findstart, base)
7 if a:findstart
8 " locate the start of the word
9 let line = getline('.')
10 let start = col('.') - 1
Bram Moolenaar28c258f2006-01-25 22:02:51 +000011 let curline = line('.')
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000012 let compl_begin = col('.') - 2
13 while start >= 0 && line[start - 1] =~ '\(\k\|[:.-]\)'
14 let start -= 1
Bram Moolenaarf75a9632005-09-13 21:20:47 +000015 endwhile
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000016 if start >= 0 && line[start - 1] =~ '&'
17 let b:entitiescompl = 1
18 let b:compl_context = ''
19 return start
20 endif
21 let stylestart = searchpair('<style\>', '', '<\/style\>', "bnW")
22 let styleend = searchpair('<style\>', '', '<\/style\>', "nW")
23 if stylestart != 0 && styleend != 0
Bram Moolenaar28c258f2006-01-25 22:02:51 +000024 if stylestart <= curline && styleend >= curline
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000025 let start = col('.') - 1
26 let b:csscompl = 1
27 while start >= 0 && line[start - 1] =~ '\(\k\|-\)'
28 let start -= 1
29 endwhile
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000030 endif
31 endif
Bram Moolenaarb8a7b562006-02-01 21:47:16 +000032 let scriptstart = searchpair('<script\>', '', '<\/script\>', "bnW")
33 let scriptend = searchpair('<script\>', '', '<\/script\>', "nW")
34 if scriptstart != 0 && scriptend != 0
35 if scriptstart <= curline && scriptend >= curline
36 let start = col('.') - 1
37 let b:jscompl = 1
38 let b:jsrange = [scriptstart, scriptend]
39 while start >= 0 && line[start - 1] =~ '\(\k\|-\)'
40 let start -= 1
41 endwhile
42 endif
43 endif
44 if !exists("b:csscompl") && !exists("b:jscompl")
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000045 let b:compl_context = getline('.')[0:(compl_begin)]
Bram Moolenaar28c258f2006-01-25 22:02:51 +000046 if b:compl_context !~ '<[^>]*$'
47 " Look like we may have broken tag. Check previous lines. Up to
48 " 10?
49 let i = 1
50 while 1
51 let context_line = getline(curline-i)
52 if context_line =~ '<[^>]*$'
53 " Yep, this is this line
54 let context_lines = getline(curline-i, curline)
55 let b:compl_context = join(context_lines, ' ')
56 break
57 elseif context_line =~ '>[^<]*$'
58 " Normal tag line, no need for completion at all
59 let b:compl_context = ''
60 break
61 endif
62 let i += 1
63 endwhile
64 " Make sure we don't have counter
65 unlet! i
66 endif
Bram Moolenaar09df3122006-01-23 22:23:09 +000067 let b:compl_context = matchstr(b:compl_context, '.*\zs<.*')
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000068 else
69 let b:compl_context = getline('.')[0:compl_begin]
70 endif
Bram Moolenaarf75a9632005-09-13 21:20:47 +000071 return start
72 else
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000073 " Initialize base return lists
74 let res = []
75 let res2 = []
76 " a:base is very short - we need context
77 let context = b:compl_context
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000078 " Check if we should do CSS completion inside of <style> tag
79 if exists("b:csscompl")
80 unlet! b:csscompl
Bram Moolenaar09df3122006-01-23 22:23:09 +000081 let context = b:compl_context
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000082 return csscomplete#CompleteCSS(0, context)
Bram Moolenaarb8a7b562006-02-01 21:47:16 +000083 elseif exists("b:jscompl")
84 unlet! b:jscompl
85 let context = b:compl_context
86 return javascriptcomplete#CompleteJS(0, context)
Bram Moolenaar09df3122006-01-23 22:23:09 +000087 else
88 if len(b:compl_context) == 0 && !exists("b:entitiescompl")
89 return []
90 endif
91 let context = matchstr(b:compl_context, '.\zs.*')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000092 endif
Bram Moolenaar09df3122006-01-23 22:23:09 +000093 unlet! b:compl_context
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000094 " Make entities completion
95 if exists("b:entitiescompl")
96 unlet! b:entitiescompl
97
Bram Moolenaara5792f52005-11-23 21:25:05 +000098 if !exists("g:xmldata_xhtml10s")
99 runtime! autoload/xml/xhtml10s.vim
100 endif
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000101
Bram Moolenaara5792f52005-11-23 21:25:05 +0000102 let entities = g:xmldata_xhtml10s['vimxmlentities']
103
Bram Moolenaar09df3122006-01-23 22:23:09 +0000104 if len(a:base) == 1
105 for m in entities
106 if m =~ '^'.a:base
107 call add(res, m.';')
108 endif
109 endfor
110 return res
111 else
112 for m in entities
113 if m =~? '^'.a:base
114 call add(res, m.';')
115 elseif m =~? a:base
116 call add(res2, m.';')
117 endif
118 endfor
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000119
Bram Moolenaar09df3122006-01-23 22:23:09 +0000120 return res + res2
121 endif
122
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000123
124 endif
125 if context =~ '>'
126 " Generally if context contains > it means we are outside of tag and
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000127 " should abandon action - with one exception: <style> span { bo
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000128 if context =~ 'style[^>]\{-}>[^<]\{-}$'
129 return csscomplete#CompleteCSS(0, context)
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000130 elseif context =~ 'script[^>]\{-}>[^<]\{-}$'
131 let b:jsrange = [line('.'), search('<\/script\>', 'nW')]
132 return javascriptcomplete#CompleteJS(0, context)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000133 else
134 return []
135 endif
136 endif
137
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000138 " Set attribute groups
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000139 let coreattrs = ["id", "class", "style", "title"]
140 let i18n = ["lang", "xml:lang", "dir=\"ltr\" ", "dir=\"rtl\" "]
141 let events = ["onclick", "ondblclick", "onmousedown", "onmouseup", "onmousemove",
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000142 \ "onmouseover", "onmouseout", "onkeypress", "onkeydown", "onkeyup"]
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000143 let focus = ["accesskey", "tabindex", "onfocus", "onblur"]
144 let coregroup = coreattrs + i18n + events
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000145 " find tags matching with "context"
146 " If context contains > it means we are already outside of tag and we
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000147 " should abandon action
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000148 " If context contains white space it is attribute.
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000149 " It could be also value of attribute...
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000150 " We have to get first word to offer
151 " proper completions
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000152 if context == ''
153 let tag = ''
154 else
155 let tag = split(context)[0]
156 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000157 " Get last word, it should be attr name
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000158 let attr = matchstr(context, '.*\s\zs.*')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000159 " Possible situations where any prediction would be difficult:
160 " 1. Events attributes
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000161 if context =~ '\s'
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000162 " Sort out style, class, and on* cases
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000163 if context =~ "\\(on[a-z]*\\|id\\|style\\|class\\)\\s*=\\s*[\"']"
164 if context =~ "\\(id\\|class\\)\\s*=\\s*[\"'][a-zA-Z0-9_ -]*$"
165 if context =~ "class\\s*=\\s*[\"'][a-zA-Z0-9_ -]*$"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000166 let search_for = "class"
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000167 elseif context =~ "id\\s*=\\s*[\"'][a-zA-Z0-9_ -]*$"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000168 let search_for = "id"
169 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000170 " Handle class name completion
171 " 1. Find lines of <link stylesheet>
172 " 1a. Check file for @import
173 " 2. Extract filename(s?) of stylesheet,
174 call cursor(1,1)
175 let head = getline(search('<head\>'), search('<\/head>'))
176 let headjoined = join(copy(head), ' ')
177 if headjoined =~ '<style'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000178 " Remove possibly confusing CSS operators
Bram Moolenaar1e015462005-09-25 22:16:38 +0000179 let stylehead = substitute(headjoined, '+>\*[,', ' ', 'g')
180 if search_for == 'class'
181 let styleheadlines = split(stylehead)
182 let headclasslines = filter(copy(styleheadlines), "v:val =~ '\\([a-zA-Z0-9:]\\+\\)\\?\\.[a-zA-Z0-9_-]\\+'")
183 else
184 let stylesheet = split(headjoined, '[{}]')
185 " Get all lines which fit id syntax
186 let classlines = filter(copy(stylesheet), "v:val =~ '#[a-zA-Z0-9_-]\\+'")
187 " Filter out possible color definitions
188 call filter(classlines, "v:val !~ ':\\s*#[a-zA-Z0-9_-]\\+'")
189 " Filter out complex border definitions
190 call filter(classlines, "v:val !~ '\\(none\\|hidden\\|dotted\\|dashed\\|solid\\|double\\|groove\\|ridge\\|inset\\|outset\\)\\s*#[a-zA-Z0-9_-]\\+'")
191 let templines = join(classlines, ' ')
192 let headclasslines = split(templines)
193 call filter(headclasslines, "v:val =~ '#[a-zA-Z0-9_-]\\+'")
194 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000195 let internal = 1
196 else
197 let internal = 0
198 endif
199 let styletable = []
200 let secimportfiles = []
201 let filestable = filter(copy(head), "v:val =~ '\\(@import\\|link.*stylesheet\\)'")
202 for line in filestable
203 if line =~ "@import"
204 let styletable += [matchstr(line, "import\\s\\+\\(url(\\)\\?[\"']\\?\\zs\\f\\+\\ze")]
205 elseif line =~ "<link"
206 let styletable += [matchstr(line, "href\\s*=\\s*[\"']\\zs\\f\\+\\ze")]
207 endif
208 endfor
Bram Moolenaar1e015462005-09-25 22:16:38 +0000209 for file in styletable
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000210 if filereadable(file)
211 let stylesheet = readfile(file)
212 let secimport = filter(copy(stylesheet), "v:val =~ '@import'")
213 if len(secimport) > 0
214 for line in secimport
Bram Moolenaar1e015462005-09-25 22:16:38 +0000215 let secfile = matchstr(line, "import\\s\\+\\(url(\\)\\?[\"']\\?\\zs\\f\\+\\ze")
216 let secfile = fnamemodify(file, ":p:h").'/'.secfile
217 let secimportfiles += [secfile]
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000218 endfor
219 endif
220 endif
221 endfor
222 let cssfiles = styletable + secimportfiles
223 let classes = []
224 for file in cssfiles
225 if filereadable(file)
226 let stylesheet = readfile(file)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000227 let stylefile = join(stylesheet, ' ')
228 let stylefile = substitute(stylefile, '+>\*[,', ' ', 'g')
229 if search_for == 'class'
230 let stylesheet = split(stylefile)
231 let classlines = filter(copy(stylesheet), "v:val =~ '\\([a-zA-Z0-9:]\\+\\)\\?\\.[a-zA-Z0-9_-]\\+'")
232 else
233 let stylesheet = split(stylefile, '[{}]')
234 " Get all lines which fit id syntax
235 let classlines = filter(copy(stylesheet), "v:val =~ '#[a-zA-Z0-9_-]\\+'")
236 " Filter out possible color definitions
237 call filter(classlines, "v:val !~ ':\\s*#[a-zA-Z0-9_-]\\+'")
238 " Filter out complex border definitions
239 call filter(classlines, "v:val !~ '\\(none\\|hidden\\|dotted\\|dashed\\|solid\\|double\\|groove\\|ridge\\|inset\\|outset\\)\\s*#[a-zA-Z0-9_-]\\+'")
240 let templines = join(classlines, ' ')
241 let stylelines = split(templines)
242 let classlines = filter(stylelines, "v:val =~ '#[a-zA-Z0-9_-]\\+'")
243
244 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000245 endif
246 " We gathered classes definitions from all external files
247 let classes += classlines
248 endfor
249 if internal == 1
250 let classes += headclasslines
251 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000252
253 if search_for == 'class'
254 let elements = {}
255 for element in classes
256 if element =~ '^\.'
257 let class = matchstr(element, '^\.\zs[a-zA-Z][a-zA-Z0-9_-]*\ze')
258 let class = substitute(class, ':.*', '', '')
259 if has_key(elements, 'common')
260 let elements['common'] .= ' '.class
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000261 else
Bram Moolenaar1e015462005-09-25 22:16:38 +0000262 let elements['common'] = class
263 endif
264 else
265 let class = matchstr(element, '[a-zA-Z1-6]*\.\zs[a-zA-Z][a-zA-Z0-9_-]*\ze')
266 let tagname = tolower(matchstr(element, '[a-zA-Z1-6]*\ze.'))
267 if tagname != ''
268 if has_key(elements, tagname)
269 let elements[tagname] .= ' '.class
270 else
271 let elements[tagname] = class
272 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000273 endif
274 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000275 endfor
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000276
Bram Moolenaar1e015462005-09-25 22:16:38 +0000277 if has_key(elements, tag) && has_key(elements, 'common')
278 let values = split(elements[tag]." ".elements['common'])
279 elseif has_key(elements, tag) && !has_key(elements, 'common')
280 let values = split(elements[tag])
281 elseif !has_key(elements, tag) && has_key(elements, 'common')
282 let values = split(elements['common'])
283 else
284 return []
285 endif
286
287 elseif search_for == 'id'
288 " Find used IDs
289 " 1. Catch whole file
290 let filelines = getline(1, line('$'))
291 " 2. Find lines with possible id
292 let used_id_lines = filter(filelines, 'v:val =~ "id\\s*=\\s*[\"''][a-zA-Z0-9_-]\\+"')
293 " 3a. Join all filtered lines
294 let id_string = join(used_id_lines, ' ')
295 " 3b. And split them to be sure each id is in separate item
296 let id_list = split(id_string, 'id\s*=\s*')
297 " 4. Extract id values
298 let used_id = map(id_list, 'matchstr(v:val, "[\"'']\\zs[a-zA-Z0-9_-]\\+\\ze")')
299 let joined_used_id = ','.join(used_id, ',').','
300
301 let allvalues = map(classes, 'matchstr(v:val, ".*#\\zs[a-zA-Z0-9_-]\\+")')
302
303 let values = []
304
305 for element in classes
306 if joined_used_id !~ ','.element.','
307 let values += [element]
308 endif
309
310 endfor
311
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000312 endif
313
314 " We need special version of sbase
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000315 let classbase = matchstr(context, ".*[\"']")
Bram Moolenaar1e015462005-09-25 22:16:38 +0000316 let classquote = matchstr(classbase, '.$')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000317
318 let entered_class = matchstr(attr, ".*=\\s*[\"']\\zs.*")
319
320 for m in sort(values)
321 if m =~? '^'.entered_class
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000322 call add(res, m . classquote)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000323 elseif m =~? entered_class
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000324 call add(res2, m . classquote)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000325 endif
326 endfor
327
328 return res + res2
329
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000330 elseif context =~ "style\\s*=\\s*[\"'][^\"']*$"
331 return csscomplete#CompleteCSS(0, context)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000332
333 endif
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000334 let stripbase = matchstr(context, ".*\\(on[a-z]*\\|style\\|class\\)\\s*=\\s*[\"']\\zs.*")
335 " Now we have context stripped from all chars up to style/class.
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000336 " It may fail with some strange style value combinations.
337 if stripbase !~ "[\"']"
338 return []
339 endif
340 endif
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000341 " If attr contains =\s*[\"'] we catched value of attribute
342 if attr =~ "=\s*[\"']"
343 " Let do attribute specific completion
344 let attrname = matchstr(attr, '.*\ze\s*=')
345 let entered_value = matchstr(attr, ".*=\\s*[\"']\\zs.*")
346 let values = []
347 if attrname == 'media'
348 let values = ["screen", "tty", "tv", "projection", "handheld", "print", "braille", "aural", "all"]
349 elseif attrname == 'xml:space'
350 let values = ["preserve"]
351 elseif attrname == 'shape'
Bram Moolenaar8349fd72005-10-12 20:52:20 +0000352 let values = ["rect", "circle", "poly", "default"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000353 elseif attrname == 'valuetype'
354 let values = ["data", "ref", "object"]
355 elseif attrname == 'method'
356 let values = ["get", "post"]
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000357 elseif attrname == 'dir'
358 let values = ["ltr", "rtl"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000359 elseif attrname == 'frame'
360 let values = ["void", "above", "below", "hsides", "lhs", "rhs", "vsides", "box", "border"]
361 elseif attrname == 'rules'
362 let values = ["none", "groups", "rows", "all"]
363 elseif attrname == 'align'
364 let values = ["left", "center", "right", "justify", "char"]
365 elseif attrname == 'valign'
366 let values = ["top", "middle", "bottom", "baseline"]
367 elseif attrname == 'scope'
368 let values = ["row", "col", "rowgroup", "colgroup"]
369 elseif attrname == 'href'
370 " Now we are looking for local anchors defined by name or id
371 if entered_value =~ '^#'
372 let file = join(getline(1, line('$')), ' ')
373 " Split it be sure there will be one id/name element in
374 " item, it will be also first word [a-zA-Z0-9_-] in element
375 let oneelement = split(file, "\\(meta \\)\\@<!\\(name\\|id\\)\\s*=\\s*[\"']")
376 for i in oneelement
377 let values += ['#'.matchstr(i, "^[a-zA-Z][a-zA-Z0-9%_-]*")]
378 endfor
379 endif
380 elseif attrname == 'type'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000381 if context =~ '^input'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000382 let values = ["text", "password", "checkbox", "radio", "submit", "reset", "file", "hidden", "image", "button"]
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000383 elseif context =~ '^button'
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000384 let values = ["button", "submit", "reset"]
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000385 elseif context =~ '^style'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000386 let values = ["text/css"]
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000387 elseif context =~ '^script'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000388 let values = ["text/javascript"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000389 endif
390 else
391 return []
392 endif
393
394 if len(values) == 0
395 return []
396 endif
397
398 " We need special version of sbase
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000399 let attrbase = matchstr(context, ".*[\"']")
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000400 let attrquote = matchstr(attrbase, '.$')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000401
402 for m in values
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000403 " This if is needed to not offer all completions as-is
404 " alphabetically but sort them. Those beginning with entered
405 " part will be as first choices
406 if m =~ '^'.entered_value
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000407 call add(res, m . attrquote.' ')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000408 elseif m =~ entered_value
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000409 call add(res2, m . attrquote.' ')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000410 endif
411 endfor
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000412
413 return res + res2
414
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000415 endif
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000416 " Shorten context to not include last word
417 let sbase = matchstr(context, '.*\ze\s.*')
418 if tag =~ '^\(abbr\|acronym\|address\|b\|bdo\|big\|caption\|cite\|code\|dd\|dfn\|div\|dl\|dt\|em\|fieldset\|h\d\|hr\|i\|kbd\|li\|noscript\|ol\|p\|samp\|small\|span\|strong\|sub\|sup\|tt\|ul\|var\)$'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000419 let attrs = coregroup
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000420 elseif tag == 'a'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000421 let attrs = coregroup + focus + ["charset", "type", "name", "href", "hreflang", "rel", "rev", "shape", "coords"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000422 elseif tag == 'area'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000423 let attrs = coregroup + focus + ["shape", "coords", "href", "nohref", "alt"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000424 elseif tag == 'base'
425 let attrs = ["href", "id"]
426 elseif tag == 'blockquote'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000427 let attrs = coregroup + ["cite"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000428 elseif tag == 'body'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000429 let attrs = coregroup + ["onload", "onunload"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000430 elseif tag == 'br'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000431 let attrs = coreattrs
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000432 elseif tag == 'button'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000433 let attrs = coregroup + focus + ["name", "value", "type"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000434 elseif tag == '^\(col\|colgroup\)$'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000435 let attrs = coregroup + ["span", "width", "align", "char", "charoff", "valign"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000436 elseif tag =~ '^\(del\|ins\)$'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000437 let attrs = coregroup + ["cite", "datetime"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000438 elseif tag == 'form'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000439 let attrs = coregroup + ["action", "method=\"get\" ", "method=\"post\" ", "enctype", "onsubmit", "onreset", "accept", "accept-charset"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000440 elseif tag == 'head'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000441 let attrs = i18n + ["id", "profile"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000442 elseif tag == 'html'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000443 let attrs = i18n + ["id", "xmlns"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000444 elseif tag == 'img'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000445 let attrs = coregroup + ["src", "alt", "longdesc", "height", "width", "usemap", "ismap"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000446 elseif tag == 'input'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000447 let attrs = coregroup + ["type", "name", "value", "checked", "disabled", "readonly", "size", "maxlength", "src", "alt", "usemap", "onselect", "onchange", "accept"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000448 elseif tag == 'label'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000449 let attrs = coregroup + ["for", "accesskey", "onfocus", "onblur"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000450 elseif tag == 'legend'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000451 let attrs = coregroup + ["accesskey"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000452 elseif tag == 'link'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000453 let attrs = coregroup + ["charset", "href", "hreflang", "type", "rel", "rev", "media"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000454 elseif tag == 'map'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000455 let attrs = i18n + events + ["id", "class", "style", "title", "name"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000456 elseif tag == 'meta'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000457 let attrs = i18n + ["id", "http-equiv", "content", "scheme", "name"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000458 elseif tag == 'title'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000459 let attrs = i18n + ["id"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000460 elseif tag == 'object'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000461 let attrs = coregroup + ["declare", "classid", "codebase", "data", "type", "codetype", "archive", "standby", "height", "width", "usemap", "name", "tabindex"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000462 elseif tag == 'optgroup'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000463 let attrs = coregroup + ["disbled", "label"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000464 elseif tag == 'option'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000465 let attrs = coregroup + ["disbled", "selected", "value", "label"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000466 elseif tag == 'param'
467 let attrs = ["id", "name", "value", "valuetype", "type"]
468 elseif tag == 'pre'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000469 let attrs = coregroup + ["xml:space"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000470 elseif tag == 'q'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000471 let attrs = coregroup + ["cite"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000472 elseif tag == 'script'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000473 let attrs = ["id", "charset", "type=\"text/javascript\"", "type", "src", "defer", "xml:space"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000474 elseif tag == 'select'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000475 let attrs = coregroup + ["name", "size", "multiple", "disabled", "tabindex", "onfocus", "onblur", "onchange"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000476 elseif tag == 'style'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000477 let attrs = coreattrs + ["id", "type=\"text/css\"", "type", "media", "title", "xml:space"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000478 elseif tag == 'table'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000479 let attrs = coregroup + ["summary", "width", "border", "frame", "rules", "cellspacing", "cellpadding"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000480 elseif tag =~ '^\(thead\|tfoot\|tbody\|tr\)$'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000481 let attrs = coregroup + ["align", "char", "charoff", "valign"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000482 elseif tag == 'textarea'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000483 let attrs = coregroup + ["name", "rows", "cols", "disabled", "readonly", "onselect", "onchange"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000484 elseif tag =~ '^\(th\|td\)$'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000485 let attrs = coregroup + ["abbr", "headers", "scope", "rowspan", "colspan", "align", "char", "charoff", "valign"]
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000486 else
487 return []
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000488 endif
489
490 for m in sort(attrs)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000491 if m =~ '^'.attr
492 if m =~ '^\(ismap\|defer\|declare\|nohref\|checked\|disabled\|selected\|readonly\)$' || m =~ '='
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000493 call add(res, m)
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000494 else
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000495 call add(res, m.'="')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000496 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000497 elseif m =~ attr
498 if m =~ '^\(ismap\|defer\|declare\|nohref\|checked\|disabled\|selected\|readonly\)$' || m =~ '='
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000499 call add(res2, m)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000500 else
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000501 call add(res2, m.'="')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000502 endif
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000503 endif
504 endfor
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000505
506 return res + res2
507
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000508 endif
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000509 " Close tag
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000510 let b:unaryTagsStack = "base meta link hr br param img area input col"
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000511 if context =~ '^\/'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000512 let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack")
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000513 return [opentag.">"]
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000514 endif
515 " Deal with tag completion.
Bram Moolenaara5792f52005-11-23 21:25:05 +0000516 let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack")
Bram Moolenaar09df3122006-01-23 22:23:09 +0000517 if opentag == ''
518 " Hack for sometimes failing GetLastOpenTag.
519 " As far as I tested fail isn't GLOT fault but problem
520 " of invalid document - not properly closed tags and other mish-mash.
521 " If returns empty string assume <body>. Safe bet.
522 let opentag = 'body'
523 endif
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000524
Bram Moolenaara5792f52005-11-23 21:25:05 +0000525 if !exists("g:xmldata_xhtml10s")
526 runtime! autoload/xml/xhtml10s.vim
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000527 endif
528
Bram Moolenaara5792f52005-11-23 21:25:05 +0000529 let tags = g:xmldata_xhtml10s[opentag][0]
530
Bram Moolenaarcef9dcc2005-12-06 19:50:41 +0000531 for m in sort(tags)
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000532 if m =~ '^'.context
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000533 call add(res, m)
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000534 elseif m =~ context
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000535 call add(res2, m)
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000536 endif
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000537 endfor
538
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000539 return res + res2
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000540
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000541 endif
542endfunction