blob: c7a43c3049c822845caab8317dd4ba545b49f6e9 [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 Moolenaar28c258f2006-01-25 22:02:51 +00004" Last Change: 2006 Jan 24
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 Moolenaard5cdbeb2005-10-10 20:59:28 +000032 if !exists("b:csscompl")
33 let b:compl_context = getline('.')[0:(compl_begin)]
Bram Moolenaar28c258f2006-01-25 22:02:51 +000034 if b:compl_context !~ '<[^>]*$'
35 " Look like we may have broken tag. Check previous lines. Up to
36 " 10?
37 let i = 1
38 while 1
39 let context_line = getline(curline-i)
40 if context_line =~ '<[^>]*$'
41 " Yep, this is this line
42 let context_lines = getline(curline-i, curline)
43 let b:compl_context = join(context_lines, ' ')
44 break
45 elseif context_line =~ '>[^<]*$'
46 " Normal tag line, no need for completion at all
47 let b:compl_context = ''
48 break
49 endif
50 let i += 1
51 endwhile
52 " Make sure we don't have counter
53 unlet! i
54 endif
Bram Moolenaar09df3122006-01-23 22:23:09 +000055 let b:compl_context = matchstr(b:compl_context, '.*\zs<.*')
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000056 else
57 let b:compl_context = getline('.')[0:compl_begin]
58 endif
Bram Moolenaarf75a9632005-09-13 21:20:47 +000059 return start
60 else
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000061 " Initialize base return lists
62 let res = []
63 let res2 = []
64 " a:base is very short - we need context
65 let context = b:compl_context
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000066 " Check if we should do CSS completion inside of <style> tag
67 if exists("b:csscompl")
68 unlet! b:csscompl
Bram Moolenaar09df3122006-01-23 22:23:09 +000069 let context = b:compl_context
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000070 return csscomplete#CompleteCSS(0, context)
Bram Moolenaar09df3122006-01-23 22:23:09 +000071 else
72 if len(b:compl_context) == 0 && !exists("b:entitiescompl")
73 return []
74 endif
75 let context = matchstr(b:compl_context, '.\zs.*')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000076 endif
Bram Moolenaar09df3122006-01-23 22:23:09 +000077 unlet! b:compl_context
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000078 " Make entities completion
79 if exists("b:entitiescompl")
80 unlet! b:entitiescompl
81
Bram Moolenaara5792f52005-11-23 21:25:05 +000082 if !exists("g:xmldata_xhtml10s")
83 runtime! autoload/xml/xhtml10s.vim
84 endif
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000085
Bram Moolenaara5792f52005-11-23 21:25:05 +000086 let entities = g:xmldata_xhtml10s['vimxmlentities']
87
Bram Moolenaar09df3122006-01-23 22:23:09 +000088 if len(a:base) == 1
89 for m in entities
90 if m =~ '^'.a:base
91 call add(res, m.';')
92 endif
93 endfor
94 return res
95 else
96 for m in entities
97 if m =~? '^'.a:base
98 call add(res, m.';')
99 elseif m =~? a:base
100 call add(res2, m.';')
101 endif
102 endfor
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000103
Bram Moolenaar09df3122006-01-23 22:23:09 +0000104 return res + res2
105 endif
106
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000107
108 endif
109 if context =~ '>'
110 " Generally if context contains > it means we are outside of tag and
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000111 " should abandon action - with one exception: <style> span { bo
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000112 if context =~ 'style[^>]\{-}>[^<]\{-}$'
113 return csscomplete#CompleteCSS(0, context)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000114 else
115 return []
116 endif
117 endif
118
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000119 " Set attribute groups
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000120 let coreattrs = ["id", "class", "style", "title"]
121 let i18n = ["lang", "xml:lang", "dir=\"ltr\" ", "dir=\"rtl\" "]
122 let events = ["onclick", "ondblclick", "onmousedown", "onmouseup", "onmousemove",
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000123 \ "onmouseover", "onmouseout", "onkeypress", "onkeydown", "onkeyup"]
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000124 let focus = ["accesskey", "tabindex", "onfocus", "onblur"]
125 let coregroup = coreattrs + i18n + events
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000126 " find tags matching with "context"
127 " If context contains > it means we are already outside of tag and we
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000128 " should abandon action
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000129 " If context contains white space it is attribute.
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000130 " It could be also value of attribute...
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000131 " We have to get first word to offer
132 " proper completions
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000133 if context == ''
134 let tag = ''
135 else
136 let tag = split(context)[0]
137 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000138 " Get last word, it should be attr name
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000139 let attr = matchstr(context, '.*\s\zs.*')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000140 " Possible situations where any prediction would be difficult:
141 " 1. Events attributes
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000142 if context =~ '\s'
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000143 " Sort out style, class, and on* cases
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000144 if context =~ "\\(on[a-z]*\\|id\\|style\\|class\\)\\s*=\\s*[\"']"
145 if context =~ "\\(id\\|class\\)\\s*=\\s*[\"'][a-zA-Z0-9_ -]*$"
146 if context =~ "class\\s*=\\s*[\"'][a-zA-Z0-9_ -]*$"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000147 let search_for = "class"
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000148 elseif context =~ "id\\s*=\\s*[\"'][a-zA-Z0-9_ -]*$"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000149 let search_for = "id"
150 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000151 " Handle class name completion
152 " 1. Find lines of <link stylesheet>
153 " 1a. Check file for @import
154 " 2. Extract filename(s?) of stylesheet,
155 call cursor(1,1)
156 let head = getline(search('<head\>'), search('<\/head>'))
157 let headjoined = join(copy(head), ' ')
158 if headjoined =~ '<style'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000159 " Remove possibly confusing CSS operators
Bram Moolenaar1e015462005-09-25 22:16:38 +0000160 let stylehead = substitute(headjoined, '+>\*[,', ' ', 'g')
161 if search_for == 'class'
162 let styleheadlines = split(stylehead)
163 let headclasslines = filter(copy(styleheadlines), "v:val =~ '\\([a-zA-Z0-9:]\\+\\)\\?\\.[a-zA-Z0-9_-]\\+'")
164 else
165 let stylesheet = split(headjoined, '[{}]')
166 " Get all lines which fit id syntax
167 let classlines = filter(copy(stylesheet), "v:val =~ '#[a-zA-Z0-9_-]\\+'")
168 " Filter out possible color definitions
169 call filter(classlines, "v:val !~ ':\\s*#[a-zA-Z0-9_-]\\+'")
170 " Filter out complex border definitions
171 call filter(classlines, "v:val !~ '\\(none\\|hidden\\|dotted\\|dashed\\|solid\\|double\\|groove\\|ridge\\|inset\\|outset\\)\\s*#[a-zA-Z0-9_-]\\+'")
172 let templines = join(classlines, ' ')
173 let headclasslines = split(templines)
174 call filter(headclasslines, "v:val =~ '#[a-zA-Z0-9_-]\\+'")
175 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000176 let internal = 1
177 else
178 let internal = 0
179 endif
180 let styletable = []
181 let secimportfiles = []
182 let filestable = filter(copy(head), "v:val =~ '\\(@import\\|link.*stylesheet\\)'")
183 for line in filestable
184 if line =~ "@import"
185 let styletable += [matchstr(line, "import\\s\\+\\(url(\\)\\?[\"']\\?\\zs\\f\\+\\ze")]
186 elseif line =~ "<link"
187 let styletable += [matchstr(line, "href\\s*=\\s*[\"']\\zs\\f\\+\\ze")]
188 endif
189 endfor
Bram Moolenaar1e015462005-09-25 22:16:38 +0000190 for file in styletable
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000191 if filereadable(file)
192 let stylesheet = readfile(file)
193 let secimport = filter(copy(stylesheet), "v:val =~ '@import'")
194 if len(secimport) > 0
195 for line in secimport
Bram Moolenaar1e015462005-09-25 22:16:38 +0000196 let secfile = matchstr(line, "import\\s\\+\\(url(\\)\\?[\"']\\?\\zs\\f\\+\\ze")
197 let secfile = fnamemodify(file, ":p:h").'/'.secfile
198 let secimportfiles += [secfile]
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000199 endfor
200 endif
201 endif
202 endfor
203 let cssfiles = styletable + secimportfiles
204 let classes = []
205 for file in cssfiles
206 if filereadable(file)
207 let stylesheet = readfile(file)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000208 let stylefile = join(stylesheet, ' ')
209 let stylefile = substitute(stylefile, '+>\*[,', ' ', 'g')
210 if search_for == 'class'
211 let stylesheet = split(stylefile)
212 let classlines = filter(copy(stylesheet), "v:val =~ '\\([a-zA-Z0-9:]\\+\\)\\?\\.[a-zA-Z0-9_-]\\+'")
213 else
214 let stylesheet = split(stylefile, '[{}]')
215 " Get all lines which fit id syntax
216 let classlines = filter(copy(stylesheet), "v:val =~ '#[a-zA-Z0-9_-]\\+'")
217 " Filter out possible color definitions
218 call filter(classlines, "v:val !~ ':\\s*#[a-zA-Z0-9_-]\\+'")
219 " Filter out complex border definitions
220 call filter(classlines, "v:val !~ '\\(none\\|hidden\\|dotted\\|dashed\\|solid\\|double\\|groove\\|ridge\\|inset\\|outset\\)\\s*#[a-zA-Z0-9_-]\\+'")
221 let templines = join(classlines, ' ')
222 let stylelines = split(templines)
223 let classlines = filter(stylelines, "v:val =~ '#[a-zA-Z0-9_-]\\+'")
224
225 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000226 endif
227 " We gathered classes definitions from all external files
228 let classes += classlines
229 endfor
230 if internal == 1
231 let classes += headclasslines
232 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000233
234 if search_for == 'class'
235 let elements = {}
236 for element in classes
237 if element =~ '^\.'
238 let class = matchstr(element, '^\.\zs[a-zA-Z][a-zA-Z0-9_-]*\ze')
239 let class = substitute(class, ':.*', '', '')
240 if has_key(elements, 'common')
241 let elements['common'] .= ' '.class
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000242 else
Bram Moolenaar1e015462005-09-25 22:16:38 +0000243 let elements['common'] = class
244 endif
245 else
246 let class = matchstr(element, '[a-zA-Z1-6]*\.\zs[a-zA-Z][a-zA-Z0-9_-]*\ze')
247 let tagname = tolower(matchstr(element, '[a-zA-Z1-6]*\ze.'))
248 if tagname != ''
249 if has_key(elements, tagname)
250 let elements[tagname] .= ' '.class
251 else
252 let elements[tagname] = class
253 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000254 endif
255 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000256 endfor
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000257
Bram Moolenaar1e015462005-09-25 22:16:38 +0000258 if has_key(elements, tag) && has_key(elements, 'common')
259 let values = split(elements[tag]." ".elements['common'])
260 elseif has_key(elements, tag) && !has_key(elements, 'common')
261 let values = split(elements[tag])
262 elseif !has_key(elements, tag) && has_key(elements, 'common')
263 let values = split(elements['common'])
264 else
265 return []
266 endif
267
268 elseif search_for == 'id'
269 " Find used IDs
270 " 1. Catch whole file
271 let filelines = getline(1, line('$'))
272 " 2. Find lines with possible id
273 let used_id_lines = filter(filelines, 'v:val =~ "id\\s*=\\s*[\"''][a-zA-Z0-9_-]\\+"')
274 " 3a. Join all filtered lines
275 let id_string = join(used_id_lines, ' ')
276 " 3b. And split them to be sure each id is in separate item
277 let id_list = split(id_string, 'id\s*=\s*')
278 " 4. Extract id values
279 let used_id = map(id_list, 'matchstr(v:val, "[\"'']\\zs[a-zA-Z0-9_-]\\+\\ze")')
280 let joined_used_id = ','.join(used_id, ',').','
281
282 let allvalues = map(classes, 'matchstr(v:val, ".*#\\zs[a-zA-Z0-9_-]\\+")')
283
284 let values = []
285
286 for element in classes
287 if joined_used_id !~ ','.element.','
288 let values += [element]
289 endif
290
291 endfor
292
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000293 endif
294
295 " We need special version of sbase
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000296 let classbase = matchstr(context, ".*[\"']")
Bram Moolenaar1e015462005-09-25 22:16:38 +0000297 let classquote = matchstr(classbase, '.$')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000298
299 let entered_class = matchstr(attr, ".*=\\s*[\"']\\zs.*")
300
301 for m in sort(values)
302 if m =~? '^'.entered_class
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000303 call add(res, m . classquote)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000304 elseif m =~? entered_class
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000305 call add(res2, m . classquote)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000306 endif
307 endfor
308
309 return res + res2
310
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000311 elseif context =~ "style\\s*=\\s*[\"'][^\"']*$"
312 return csscomplete#CompleteCSS(0, context)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000313
314 endif
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000315 let stripbase = matchstr(context, ".*\\(on[a-z]*\\|style\\|class\\)\\s*=\\s*[\"']\\zs.*")
316 " Now we have context stripped from all chars up to style/class.
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000317 " It may fail with some strange style value combinations.
318 if stripbase !~ "[\"']"
319 return []
320 endif
321 endif
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000322 " If attr contains =\s*[\"'] we catched value of attribute
323 if attr =~ "=\s*[\"']"
324 " Let do attribute specific completion
325 let attrname = matchstr(attr, '.*\ze\s*=')
326 let entered_value = matchstr(attr, ".*=\\s*[\"']\\zs.*")
327 let values = []
328 if attrname == 'media'
329 let values = ["screen", "tty", "tv", "projection", "handheld", "print", "braille", "aural", "all"]
330 elseif attrname == 'xml:space'
331 let values = ["preserve"]
332 elseif attrname == 'shape'
Bram Moolenaar8349fd72005-10-12 20:52:20 +0000333 let values = ["rect", "circle", "poly", "default"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000334 elseif attrname == 'valuetype'
335 let values = ["data", "ref", "object"]
336 elseif attrname == 'method'
337 let values = ["get", "post"]
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000338 elseif attrname == 'dir'
339 let values = ["ltr", "rtl"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000340 elseif attrname == 'frame'
341 let values = ["void", "above", "below", "hsides", "lhs", "rhs", "vsides", "box", "border"]
342 elseif attrname == 'rules'
343 let values = ["none", "groups", "rows", "all"]
344 elseif attrname == 'align'
345 let values = ["left", "center", "right", "justify", "char"]
346 elseif attrname == 'valign'
347 let values = ["top", "middle", "bottom", "baseline"]
348 elseif attrname == 'scope'
349 let values = ["row", "col", "rowgroup", "colgroup"]
350 elseif attrname == 'href'
351 " Now we are looking for local anchors defined by name or id
352 if entered_value =~ '^#'
353 let file = join(getline(1, line('$')), ' ')
354 " Split it be sure there will be one id/name element in
355 " item, it will be also first word [a-zA-Z0-9_-] in element
356 let oneelement = split(file, "\\(meta \\)\\@<!\\(name\\|id\\)\\s*=\\s*[\"']")
357 for i in oneelement
358 let values += ['#'.matchstr(i, "^[a-zA-Z][a-zA-Z0-9%_-]*")]
359 endfor
360 endif
361 elseif attrname == 'type'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000362 if context =~ '^input'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000363 let values = ["text", "password", "checkbox", "radio", "submit", "reset", "file", "hidden", "image", "button"]
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000364 elseif context =~ '^button'
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000365 let values = ["button", "submit", "reset"]
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000366 elseif context =~ '^style'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000367 let values = ["text/css"]
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000368 elseif context =~ '^script'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000369 let values = ["text/javascript"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000370 endif
371 else
372 return []
373 endif
374
375 if len(values) == 0
376 return []
377 endif
378
379 " We need special version of sbase
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000380 let attrbase = matchstr(context, ".*[\"']")
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000381 let attrquote = matchstr(attrbase, '.$')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000382
383 for m in values
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000384 " This if is needed to not offer all completions as-is
385 " alphabetically but sort them. Those beginning with entered
386 " part will be as first choices
387 if m =~ '^'.entered_value
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000388 call add(res, m . attrquote.' ')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000389 elseif m =~ entered_value
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000390 call add(res2, m . attrquote.' ')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000391 endif
392 endfor
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000393
394 return res + res2
395
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000396 endif
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000397 " Shorten context to not include last word
398 let sbase = matchstr(context, '.*\ze\s.*')
399 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 +0000400 let attrs = coregroup
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000401 elseif tag == 'a'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000402 let attrs = coregroup + focus + ["charset", "type", "name", "href", "hreflang", "rel", "rev", "shape", "coords"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000403 elseif tag == 'area'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000404 let attrs = coregroup + focus + ["shape", "coords", "href", "nohref", "alt"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000405 elseif tag == 'base'
406 let attrs = ["href", "id"]
407 elseif tag == 'blockquote'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000408 let attrs = coregroup + ["cite"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000409 elseif tag == 'body'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000410 let attrs = coregroup + ["onload", "onunload"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000411 elseif tag == 'br'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000412 let attrs = coreattrs
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000413 elseif tag == 'button'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000414 let attrs = coregroup + focus + ["name", "value", "type"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000415 elseif tag == '^\(col\|colgroup\)$'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000416 let attrs = coregroup + ["span", "width", "align", "char", "charoff", "valign"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000417 elseif tag =~ '^\(del\|ins\)$'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000418 let attrs = coregroup + ["cite", "datetime"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000419 elseif tag == 'form'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000420 let attrs = coregroup + ["action", "method=\"get\" ", "method=\"post\" ", "enctype", "onsubmit", "onreset", "accept", "accept-charset"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000421 elseif tag == 'head'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000422 let attrs = i18n + ["id", "profile"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000423 elseif tag == 'html'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000424 let attrs = i18n + ["id", "xmlns"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000425 elseif tag == 'img'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000426 let attrs = coregroup + ["src", "alt", "longdesc", "height", "width", "usemap", "ismap"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000427 elseif tag == 'input'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000428 let attrs = coregroup + ["type", "name", "value", "checked", "disabled", "readonly", "size", "maxlength", "src", "alt", "usemap", "onselect", "onchange", "accept"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000429 elseif tag == 'label'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000430 let attrs = coregroup + ["for", "accesskey", "onfocus", "onblur"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000431 elseif tag == 'legend'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000432 let attrs = coregroup + ["accesskey"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000433 elseif tag == 'link'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000434 let attrs = coregroup + ["charset", "href", "hreflang", "type", "rel", "rev", "media"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000435 elseif tag == 'map'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000436 let attrs = i18n + events + ["id", "class", "style", "title", "name"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000437 elseif tag == 'meta'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000438 let attrs = i18n + ["id", "http-equiv", "content", "scheme", "name"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000439 elseif tag == 'title'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000440 let attrs = i18n + ["id"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000441 elseif tag == 'object'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000442 let attrs = coregroup + ["declare", "classid", "codebase", "data", "type", "codetype", "archive", "standby", "height", "width", "usemap", "name", "tabindex"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000443 elseif tag == 'optgroup'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000444 let attrs = coregroup + ["disbled", "label"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000445 elseif tag == 'option'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000446 let attrs = coregroup + ["disbled", "selected", "value", "label"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000447 elseif tag == 'param'
448 let attrs = ["id", "name", "value", "valuetype", "type"]
449 elseif tag == 'pre'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000450 let attrs = coregroup + ["xml:space"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000451 elseif tag == 'q'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000452 let attrs = coregroup + ["cite"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000453 elseif tag == 'script'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000454 let attrs = ["id", "charset", "type=\"text/javascript\"", "type", "src", "defer", "xml:space"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000455 elseif tag == 'select'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000456 let attrs = coregroup + ["name", "size", "multiple", "disabled", "tabindex", "onfocus", "onblur", "onchange"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000457 elseif tag == 'style'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000458 let attrs = coreattrs + ["id", "type=\"text/css\"", "type", "media", "title", "xml:space"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000459 elseif tag == 'table'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000460 let attrs = coregroup + ["summary", "width", "border", "frame", "rules", "cellspacing", "cellpadding"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000461 elseif tag =~ '^\(thead\|tfoot\|tbody\|tr\)$'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000462 let attrs = coregroup + ["align", "char", "charoff", "valign"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000463 elseif tag == 'textarea'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000464 let attrs = coregroup + ["name", "rows", "cols", "disabled", "readonly", "onselect", "onchange"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000465 elseif tag =~ '^\(th\|td\)$'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000466 let attrs = coregroup + ["abbr", "headers", "scope", "rowspan", "colspan", "align", "char", "charoff", "valign"]
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000467 else
468 return []
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000469 endif
470
471 for m in sort(attrs)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000472 if m =~ '^'.attr
473 if m =~ '^\(ismap\|defer\|declare\|nohref\|checked\|disabled\|selected\|readonly\)$' || m =~ '='
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000474 call add(res, m)
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000475 else
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000476 call add(res, m.'="')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000477 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000478 elseif m =~ attr
479 if m =~ '^\(ismap\|defer\|declare\|nohref\|checked\|disabled\|selected\|readonly\)$' || m =~ '='
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000480 call add(res2, m)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000481 else
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000482 call add(res2, m.'="')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000483 endif
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000484 endif
485 endfor
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000486
487 return res + res2
488
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000489 endif
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000490 " Close tag
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000491 let b:unaryTagsStack = "base meta link hr br param img area input col"
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000492 if context =~ '^\/'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000493 let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack")
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000494 return [opentag.">"]
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000495 endif
496 " Deal with tag completion.
Bram Moolenaara5792f52005-11-23 21:25:05 +0000497 let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack")
Bram Moolenaar09df3122006-01-23 22:23:09 +0000498 if opentag == ''
499 " Hack for sometimes failing GetLastOpenTag.
500 " As far as I tested fail isn't GLOT fault but problem
501 " of invalid document - not properly closed tags and other mish-mash.
502 " If returns empty string assume <body>. Safe bet.
503 let opentag = 'body'
504 endif
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000505
Bram Moolenaara5792f52005-11-23 21:25:05 +0000506 if !exists("g:xmldata_xhtml10s")
507 runtime! autoload/xml/xhtml10s.vim
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000508 endif
509
Bram Moolenaara5792f52005-11-23 21:25:05 +0000510 let tags = g:xmldata_xhtml10s[opentag][0]
511
Bram Moolenaarcef9dcc2005-12-06 19:50:41 +0000512 for m in sort(tags)
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000513 if m =~ '^'.context
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000514 call add(res, m)
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000515 elseif m =~ context
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000516 call add(res2, m)
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000517 endif
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000518 endfor
519
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000520 return res + res2
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000521
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000522 endif
523endfunction