blob: 0b4bc5fd88be40db874556f38609dae0c7e4aa85 [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 Moolenaar8b6144b2006-02-08 09:20:24 +00004" Last Change: 2006 Feb 6
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 Moolenaar8b6144b2006-02-08 09:20:24 +000016 " Handling of entities {{{
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000017 if start >= 0 && line[start - 1] =~ '&'
18 let b:entitiescompl = 1
19 let b:compl_context = ''
20 return start
21 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +000022 " }}}
23 " Handling of <style> tag {{{
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000024 let stylestart = searchpair('<style\>', '', '<\/style\>', "bnW")
25 let styleend = searchpair('<style\>', '', '<\/style\>', "nW")
26 if stylestart != 0 && styleend != 0
Bram Moolenaar28c258f2006-01-25 22:02:51 +000027 if stylestart <= curline && styleend >= curline
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000028 let start = col('.') - 1
29 let b:csscompl = 1
30 while start >= 0 && line[start - 1] =~ '\(\k\|-\)'
31 let start -= 1
32 endwhile
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000033 endif
34 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +000035 " }}}
36 " Handling of <script> tag {{{
Bram Moolenaarb8a7b562006-02-01 21:47:16 +000037 let scriptstart = searchpair('<script\>', '', '<\/script\>', "bnW")
38 let scriptend = searchpair('<script\>', '', '<\/script\>', "nW")
39 if scriptstart != 0 && scriptend != 0
40 if scriptstart <= curline && scriptend >= curline
41 let start = col('.') - 1
42 let b:jscompl = 1
43 let b:jsrange = [scriptstart, scriptend]
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +000044 while start >= 0 && line[start - 1] =~ '\k'
Bram Moolenaarb8a7b562006-02-01 21:47:16 +000045 let start -= 1
46 endwhile
Bram Moolenaar8b6144b2006-02-08 09:20:24 +000047 " We are inside of <script> tag. But we should also get contents
48 " of all linked external files and (secondary, less probably) other <script> tags
49 " This logic could possible be done in separate function - may be
50 " reused in events scripting (also with option could be reused for
51 " CSS
52 let b:js_extfiles = []
53 let l = line('.')
54 let c = col('.')
55 call cursor(1,1)
56 while search('<\@<=script\>', 'W') && line('.') <= l
57 if synIDattr(synID(line('.'),col('.')-1,0),"name") !~? 'comment'
58 let sname = matchstr(getline('.'), '<script[^>]*src\s*=\s*\([''"]\)\zs.\{-}\ze\1')
59 if filereadable(sname)
60 let b:js_extfiles += readfile(sname)
61 endif
62 endif
63 endwhile
64 call cursor(1,1)
65 let js_scripttags = []
66 while search('<script\>', 'W') && line('.') < l
67 if matchstr(getline('.'), '<script[^>]*src') == ''
68 let js_scripttag = getline(line('.'), search('</script>', 'W'))
69 let js_scripttags += js_scripttag
70 endif
71 endwhile
72 let b:js_extfiles += js_scripttags
73 call cursor(l,c)
74 unlet! l c
Bram Moolenaarb8a7b562006-02-01 21:47:16 +000075 endif
76 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +000077 " }}}
Bram Moolenaarb8a7b562006-02-01 21:47:16 +000078 if !exists("b:csscompl") && !exists("b:jscompl")
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000079 let b:compl_context = getline('.')[0:(compl_begin)]
Bram Moolenaar28c258f2006-01-25 22:02:51 +000080 if b:compl_context !~ '<[^>]*$'
Bram Moolenaar8b6144b2006-02-08 09:20:24 +000081 " Look like we may have broken tag. Check previous lines.
Bram Moolenaar28c258f2006-01-25 22:02:51 +000082 let i = 1
83 while 1
84 let context_line = getline(curline-i)
85 if context_line =~ '<[^>]*$'
86 " Yep, this is this line
87 let context_lines = getline(curline-i, curline)
88 let b:compl_context = join(context_lines, ' ')
89 break
90 elseif context_line =~ '>[^<]*$'
91 " Normal tag line, no need for completion at all
92 let b:compl_context = ''
93 break
94 endif
95 let i += 1
96 endwhile
97 " Make sure we don't have counter
98 unlet! i
99 endif
Bram Moolenaar09df3122006-01-23 22:23:09 +0000100 let b:compl_context = matchstr(b:compl_context, '.*\zs<.*')
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000101 " Return proper start for on-events. Without that beginning of
102 " completion will be badly reported
103 if b:compl_context =~? 'on[a-z]*\s*=\s*\(''[^'']*\|"[^"]*\)$'
104 let start = col('.') - 1
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000105 while start >= 0 && line[start - 1] =~ '\k'
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000106 let start -= 1
107 endwhile
108 endif
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000109 else
110 let b:compl_context = getline('.')[0:compl_begin]
111 endif
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000112 return start
113 else
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000114 " Initialize base return lists
115 let res = []
116 let res2 = []
117 " a:base is very short - we need context
118 let context = b:compl_context
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000119 " Check if we should do CSS completion inside of <style> tag
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000120 " or JS completion inside of <script> tag
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000121 if exists("b:csscompl")
122 unlet! b:csscompl
Bram Moolenaar09df3122006-01-23 22:23:09 +0000123 let context = b:compl_context
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000124 unlet! b:compl_context
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000125 return csscomplete#CompleteCSS(0, context)
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000126 elseif exists("b:jscompl")
127 unlet! b:jscompl
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000128 return javascriptcomplete#CompleteJS(0, a:base)
Bram Moolenaar09df3122006-01-23 22:23:09 +0000129 else
130 if len(b:compl_context) == 0 && !exists("b:entitiescompl")
131 return []
132 endif
133 let context = matchstr(b:compl_context, '.\zs.*')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000134 endif
Bram Moolenaar09df3122006-01-23 22:23:09 +0000135 unlet! b:compl_context
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000136 " Entities completion {{{
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000137 if exists("b:entitiescompl")
138 unlet! b:entitiescompl
139
Bram Moolenaara5792f52005-11-23 21:25:05 +0000140 if !exists("g:xmldata_xhtml10s")
141 runtime! autoload/xml/xhtml10s.vim
142 endif
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000143
Bram Moolenaara5792f52005-11-23 21:25:05 +0000144 let entities = g:xmldata_xhtml10s['vimxmlentities']
145
Bram Moolenaar09df3122006-01-23 22:23:09 +0000146 if len(a:base) == 1
147 for m in entities
148 if m =~ '^'.a:base
149 call add(res, m.';')
150 endif
151 endfor
152 return res
153 else
154 for m in entities
155 if m =~? '^'.a:base
156 call add(res, m.';')
157 elseif m =~? a:base
158 call add(res2, m.';')
159 endif
160 endfor
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000161
Bram Moolenaar09df3122006-01-23 22:23:09 +0000162 return res + res2
163 endif
164
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000165
166 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000167 " }}}
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000168 if context =~ '>'
169 " Generally if context contains > it means we are outside of tag and
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000170 " should abandon action - with one exception: <style> span { bo
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000171 if context =~ 'style[^>]\{-}>[^<]\{-}$'
172 return csscomplete#CompleteCSS(0, context)
Bram Moolenaarb8a7b562006-02-01 21:47:16 +0000173 elseif context =~ 'script[^>]\{-}>[^<]\{-}$'
174 let b:jsrange = [line('.'), search('<\/script\>', 'nW')]
175 return javascriptcomplete#CompleteJS(0, context)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000176 else
177 return []
178 endif
179 endif
180
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000181 " If context contains > it means we are already outside of tag and we
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000182 " should abandon action
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000183 " If context contains white space it is attribute.
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000184 " It can be also value of attribute.
185 " We have to get first word to offer proper completions
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000186 if context == ''
187 let tag = ''
188 else
189 let tag = split(context)[0]
190 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000191 " Get last word, it should be attr name
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000192 let attr = matchstr(context, '.*\s\zs.*')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000193 " Possible situations where any prediction would be difficult:
194 " 1. Events attributes
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000195 if context =~ '\s'
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000196 " Sort out style, class, and on* cases
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000197 if context =~? "\\(on[a-z]*\\|id\\|style\\|class\\)\\s*=\\s*[\"']"
198 " Id, class completion {{{
199 if context =~? "\\(id\\|class\\)\\s*=\\s*[\"'][a-zA-Z0-9_ -]*$"
200 if context =~? "class\\s*=\\s*[\"'][a-zA-Z0-9_ -]*$"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000201 let search_for = "class"
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000202 elseif context =~? "id\\s*=\\s*[\"'][a-zA-Z0-9_ -]*$"
Bram Moolenaar1e015462005-09-25 22:16:38 +0000203 let search_for = "id"
204 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000205 " Handle class name completion
206 " 1. Find lines of <link stylesheet>
207 " 1a. Check file for @import
208 " 2. Extract filename(s?) of stylesheet,
209 call cursor(1,1)
210 let head = getline(search('<head\>'), search('<\/head>'))
211 let headjoined = join(copy(head), ' ')
212 if headjoined =~ '<style'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000213 " Remove possibly confusing CSS operators
Bram Moolenaar1e015462005-09-25 22:16:38 +0000214 let stylehead = substitute(headjoined, '+>\*[,', ' ', 'g')
215 if search_for == 'class'
216 let styleheadlines = split(stylehead)
217 let headclasslines = filter(copy(styleheadlines), "v:val =~ '\\([a-zA-Z0-9:]\\+\\)\\?\\.[a-zA-Z0-9_-]\\+'")
218 else
219 let stylesheet = split(headjoined, '[{}]')
220 " Get all lines which fit id syntax
221 let classlines = filter(copy(stylesheet), "v:val =~ '#[a-zA-Z0-9_-]\\+'")
222 " Filter out possible color definitions
223 call filter(classlines, "v:val !~ ':\\s*#[a-zA-Z0-9_-]\\+'")
224 " Filter out complex border definitions
225 call filter(classlines, "v:val !~ '\\(none\\|hidden\\|dotted\\|dashed\\|solid\\|double\\|groove\\|ridge\\|inset\\|outset\\)\\s*#[a-zA-Z0-9_-]\\+'")
226 let templines = join(classlines, ' ')
227 let headclasslines = split(templines)
228 call filter(headclasslines, "v:val =~ '#[a-zA-Z0-9_-]\\+'")
229 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000230 let internal = 1
231 else
232 let internal = 0
233 endif
234 let styletable = []
235 let secimportfiles = []
236 let filestable = filter(copy(head), "v:val =~ '\\(@import\\|link.*stylesheet\\)'")
237 for line in filestable
238 if line =~ "@import"
239 let styletable += [matchstr(line, "import\\s\\+\\(url(\\)\\?[\"']\\?\\zs\\f\\+\\ze")]
240 elseif line =~ "<link"
241 let styletable += [matchstr(line, "href\\s*=\\s*[\"']\\zs\\f\\+\\ze")]
242 endif
243 endfor
Bram Moolenaar1e015462005-09-25 22:16:38 +0000244 for file in styletable
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000245 if filereadable(file)
246 let stylesheet = readfile(file)
247 let secimport = filter(copy(stylesheet), "v:val =~ '@import'")
248 if len(secimport) > 0
249 for line in secimport
Bram Moolenaar1e015462005-09-25 22:16:38 +0000250 let secfile = matchstr(line, "import\\s\\+\\(url(\\)\\?[\"']\\?\\zs\\f\\+\\ze")
251 let secfile = fnamemodify(file, ":p:h").'/'.secfile
252 let secimportfiles += [secfile]
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000253 endfor
254 endif
255 endif
256 endfor
257 let cssfiles = styletable + secimportfiles
258 let classes = []
259 for file in cssfiles
260 if filereadable(file)
261 let stylesheet = readfile(file)
Bram Moolenaar1e015462005-09-25 22:16:38 +0000262 let stylefile = join(stylesheet, ' ')
263 let stylefile = substitute(stylefile, '+>\*[,', ' ', 'g')
264 if search_for == 'class'
265 let stylesheet = split(stylefile)
266 let classlines = filter(copy(stylesheet), "v:val =~ '\\([a-zA-Z0-9:]\\+\\)\\?\\.[a-zA-Z0-9_-]\\+'")
267 else
268 let stylesheet = split(stylefile, '[{}]')
269 " Get all lines which fit id syntax
270 let classlines = filter(copy(stylesheet), "v:val =~ '#[a-zA-Z0-9_-]\\+'")
271 " Filter out possible color definitions
272 call filter(classlines, "v:val !~ ':\\s*#[a-zA-Z0-9_-]\\+'")
273 " Filter out complex border definitions
274 call filter(classlines, "v:val !~ '\\(none\\|hidden\\|dotted\\|dashed\\|solid\\|double\\|groove\\|ridge\\|inset\\|outset\\)\\s*#[a-zA-Z0-9_-]\\+'")
275 let templines = join(classlines, ' ')
276 let stylelines = split(templines)
277 let classlines = filter(stylelines, "v:val =~ '#[a-zA-Z0-9_-]\\+'")
278
279 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000280 endif
281 " We gathered classes definitions from all external files
282 let classes += classlines
283 endfor
284 if internal == 1
285 let classes += headclasslines
286 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000287
288 if search_for == 'class'
289 let elements = {}
290 for element in classes
291 if element =~ '^\.'
292 let class = matchstr(element, '^\.\zs[a-zA-Z][a-zA-Z0-9_-]*\ze')
293 let class = substitute(class, ':.*', '', '')
294 if has_key(elements, 'common')
295 let elements['common'] .= ' '.class
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000296 else
Bram Moolenaar1e015462005-09-25 22:16:38 +0000297 let elements['common'] = class
298 endif
299 else
300 let class = matchstr(element, '[a-zA-Z1-6]*\.\zs[a-zA-Z][a-zA-Z0-9_-]*\ze')
301 let tagname = tolower(matchstr(element, '[a-zA-Z1-6]*\ze.'))
302 if tagname != ''
303 if has_key(elements, tagname)
304 let elements[tagname] .= ' '.class
305 else
306 let elements[tagname] = class
307 endif
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000308 endif
309 endif
Bram Moolenaar1e015462005-09-25 22:16:38 +0000310 endfor
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000311
Bram Moolenaar1e015462005-09-25 22:16:38 +0000312 if has_key(elements, tag) && has_key(elements, 'common')
313 let values = split(elements[tag]." ".elements['common'])
314 elseif has_key(elements, tag) && !has_key(elements, 'common')
315 let values = split(elements[tag])
316 elseif !has_key(elements, tag) && has_key(elements, 'common')
317 let values = split(elements['common'])
318 else
319 return []
320 endif
321
322 elseif search_for == 'id'
323 " Find used IDs
324 " 1. Catch whole file
325 let filelines = getline(1, line('$'))
326 " 2. Find lines with possible id
327 let used_id_lines = filter(filelines, 'v:val =~ "id\\s*=\\s*[\"''][a-zA-Z0-9_-]\\+"')
328 " 3a. Join all filtered lines
329 let id_string = join(used_id_lines, ' ')
330 " 3b. And split them to be sure each id is in separate item
331 let id_list = split(id_string, 'id\s*=\s*')
332 " 4. Extract id values
333 let used_id = map(id_list, 'matchstr(v:val, "[\"'']\\zs[a-zA-Z0-9_-]\\+\\ze")')
334 let joined_used_id = ','.join(used_id, ',').','
335
336 let allvalues = map(classes, 'matchstr(v:val, ".*#\\zs[a-zA-Z0-9_-]\\+")')
337
338 let values = []
339
340 for element in classes
341 if joined_used_id !~ ','.element.','
342 let values += [element]
343 endif
344
345 endfor
346
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000347 endif
348
349 " We need special version of sbase
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000350 let classbase = matchstr(context, ".*[\"']")
Bram Moolenaar1e015462005-09-25 22:16:38 +0000351 let classquote = matchstr(classbase, '.$')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000352
353 let entered_class = matchstr(attr, ".*=\\s*[\"']\\zs.*")
354
355 for m in sort(values)
356 if m =~? '^'.entered_class
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000357 call add(res, m . classquote)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000358 elseif m =~? entered_class
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000359 call add(res2, m . classquote)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000360 endif
361 endfor
362
363 return res + res2
364
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000365 elseif context =~? "style\\s*=\\s*[\"'][^\"']*$"
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000366 return csscomplete#CompleteCSS(0, context)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000367
368 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000369 " }}}
370 " Complete on-events {{{
371 if context =~? 'on[a-z]*\s*=\s*\(''[^'']*\|"[^"]*\)$'
372 " We have to:
373 " 1. Find external files
374 let b:js_extfiles = []
375 let l = line('.')
376 let c = col('.')
377 call cursor(1,1)
378 while search('<\@<=script\>', 'W') && line('.') <= l
379 if synIDattr(synID(line('.'),col('.')-1,0),"name") !~? 'comment'
380 let sname = matchstr(getline('.'), '<script[^>]*src\s*=\s*\([''"]\)\zs.\{-}\ze\1')
381 if filereadable(sname)
382 let b:js_extfiles += readfile(sname)
383 endif
384 endif
385 endwhile
386 " 2. Find at least one <script> tag
387 call cursor(1,1)
388 let js_scripttags = []
389 while search('<script\>', 'W') && line('.') < l
390 if matchstr(getline('.'), '<script[^>]*src') == ''
391 let js_scripttag = getline(line('.'), search('</script>', 'W'))
392 let js_scripttags += js_scripttag
393 endif
394 endwhile
395 let b:js_extfiles += js_scripttags
396
397 " 3. Proper call for javascriptcomplete#CompleteJS
398 call cursor(l,c)
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000399 let js_context = matchstr(a:base, '\k\+$')
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000400 let js_shortcontext = substitute(a:base, js_context.'$', '', '')
401 let b:compl_context = context
402 let b:jsrange = [l, l]
403 unlet! l c
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000404 return javascriptcomplete#CompleteJS(0, js_context)
405
406 endif
407
408 " }}}
409 let stripbase = matchstr(context, ".*\\(on[a-zA-Z]*\\|style\\|class\\)\\s*=\\s*[\"']\\zs.*")
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000410 " Now we have context stripped from all chars up to style/class.
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000411 " It may fail with some strange style value combinations.
412 if stripbase !~ "[\"']"
413 return []
414 endif
415 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000416 " Value of attribute completion {{{
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000417 " If attr contains =\s*[\"'] we catched value of attribute
418 if attr =~ "=\s*[\"']"
419 " Let do attribute specific completion
420 let attrname = matchstr(attr, '.*\ze\s*=')
421 let entered_value = matchstr(attr, ".*=\\s*[\"']\\zs.*")
422 let values = []
423 if attrname == 'media'
424 let values = ["screen", "tty", "tv", "projection", "handheld", "print", "braille", "aural", "all"]
425 elseif attrname == 'xml:space'
426 let values = ["preserve"]
427 elseif attrname == 'shape'
Bram Moolenaar8349fd72005-10-12 20:52:20 +0000428 let values = ["rect", "circle", "poly", "default"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000429 elseif attrname == 'valuetype'
430 let values = ["data", "ref", "object"]
431 elseif attrname == 'method'
432 let values = ["get", "post"]
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000433 elseif attrname == 'dir'
434 let values = ["ltr", "rtl"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000435 elseif attrname == 'frame'
436 let values = ["void", "above", "below", "hsides", "lhs", "rhs", "vsides", "box", "border"]
437 elseif attrname == 'rules'
438 let values = ["none", "groups", "rows", "all"]
439 elseif attrname == 'align'
440 let values = ["left", "center", "right", "justify", "char"]
441 elseif attrname == 'valign'
442 let values = ["top", "middle", "bottom", "baseline"]
443 elseif attrname == 'scope'
444 let values = ["row", "col", "rowgroup", "colgroup"]
445 elseif attrname == 'href'
446 " Now we are looking for local anchors defined by name or id
447 if entered_value =~ '^#'
448 let file = join(getline(1, line('$')), ' ')
449 " Split it be sure there will be one id/name element in
450 " item, it will be also first word [a-zA-Z0-9_-] in element
451 let oneelement = split(file, "\\(meta \\)\\@<!\\(name\\|id\\)\\s*=\\s*[\"']")
452 for i in oneelement
453 let values += ['#'.matchstr(i, "^[a-zA-Z][a-zA-Z0-9%_-]*")]
454 endfor
455 endif
456 elseif attrname == 'type'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000457 if context =~ '^input'
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000458 let values = ["text", "password", "checkbox", "radio", "submit", "reset", "file", "hidden", "image", "button"]
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000459 elseif context =~ '^button'
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000460 let values = ["button", "submit", "reset"]
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000461 elseif context =~ '^style'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000462 let values = ["text/css"]
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000463 elseif context =~ '^script'
Bram Moolenaar1e015462005-09-25 22:16:38 +0000464 let values = ["text/javascript"]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000465 endif
466 else
467 return []
468 endif
469
470 if len(values) == 0
471 return []
472 endif
473
474 " We need special version of sbase
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000475 let attrbase = matchstr(context, ".*[\"']")
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000476 let attrquote = matchstr(attrbase, '.$')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000477
478 for m in values
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000479 " This if is needed to not offer all completions as-is
480 " alphabetically but sort them. Those beginning with entered
481 " part will be as first choices
482 if m =~ '^'.entered_value
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000483 call add(res, m . attrquote.' ')
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000484 elseif m =~ entered_value
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000485 call add(res2, m . attrquote.' ')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000486 endif
487 endfor
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000488
489 return res + res2
490
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000491 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000492 " }}}
493 " Attribute completion {{{
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000494 " Shorten context to not include last word
495 let sbase = matchstr(context, '.*\ze\s.*')
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000496
497 " Load data {{{
498 if !exists("g:xmldata_xhtml10s")
499 runtime! autoload/xml/xhtml10s.vim
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000500 endif
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000501 " }}}
502 "
503 let attrs = keys(g:xmldata_xhtml10s[tag][1])
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000504
505 for m in sort(attrs)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000506 if m =~ '^'.attr
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000507 call add(res, m)
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000508 elseif m =~ attr
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000509 call add(res2, m)
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000510 endif
511 endfor
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000512 let menu = res + res2
513 if has_key(g:xmldata_xhtml10s, 'vimxmlattrinfo')
514 let final_menu = []
515 for i in range(len(menu))
516 let item = menu[i]
517 if has_key(g:xmldata_xhtml10s['vimxmlattrinfo'], item)
518 let m_menu = g:xmldata_xhtml10s['vimxmlattrinfo'][item][0]
519 let m_info = g:xmldata_xhtml10s['vimxmlattrinfo'][item][1]
520 if m_menu !~ 'Bool'
521 let item .= '="'
522 endif
523 else
524 let m_menu = ''
525 let m_info = ''
526 let item .= '="'
527 endif
528 let final_menu += [{'word':item, 'menu':m_menu, 'info':m_info}]
529 endfor
530 else
531 let final_menu = map(menu, 'v:val."=\""')
532 endif
533 return final_menu
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000534
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000535 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000536 " }}}
537 " Close tag {{{
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000538 let b:unaryTagsStack = "base meta link hr br param img area input col"
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000539 if context =~ '^\/'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000540 let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack")
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000541 return [opentag.">"]
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000542 endif
543 " Deal with tag completion.
Bram Moolenaara5792f52005-11-23 21:25:05 +0000544 let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack")
Bram Moolenaar09df3122006-01-23 22:23:09 +0000545 if opentag == ''
546 " Hack for sometimes failing GetLastOpenTag.
547 " As far as I tested fail isn't GLOT fault but problem
548 " of invalid document - not properly closed tags and other mish-mash.
549 " If returns empty string assume <body>. Safe bet.
550 let opentag = 'body'
551 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000552 " }}}
553 " Load data {{{
Bram Moolenaara5792f52005-11-23 21:25:05 +0000554 if !exists("g:xmldata_xhtml10s")
555 runtime! autoload/xml/xhtml10s.vim
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000556 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000557 " }}}
558 " Tag completion {{{
Bram Moolenaar4c903f92005-09-14 21:32:32 +0000559
Bram Moolenaara5792f52005-11-23 21:25:05 +0000560 let tags = g:xmldata_xhtml10s[opentag][0]
561
Bram Moolenaarcef9dcc2005-12-06 19:50:41 +0000562 for m in sort(tags)
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000563 if m =~ '^'.context
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000564 call add(res, m)
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +0000565 elseif m =~ context
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000566 call add(res2, m)
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000567 endif
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000568 endfor
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000569 let menu = res + res2
570 if has_key(g:xmldata_xhtml10s, 'vimxmltaginfo')
571 let final_menu = []
572 for i in range(len(menu))
573 let item = menu[i]
574 if has_key(g:xmldata_xhtml10s['vimxmltaginfo'], item)
575 let m_menu = g:xmldata_xhtml10s['vimxmltaginfo'][item][0]
576 let m_info = g:xmldata_xhtml10s['vimxmltaginfo'][item][1]
577 else
578 let m_menu = ''
579 let m_info = ''
580 endif
581 let final_menu += [{'word':item, 'menu':m_menu, 'info':m_info}]
582 endfor
583 else
584 let final_menu = menu
585 endif
586 return final_menu
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000587
Bram Moolenaar6b730e12005-09-16 21:47:57 +0000588
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000589 " }}}
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000590 endif
591endfunction
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000592" vim:set foldmethod=marker: