blob: 4c1ac4f6b5b6b50138d6474b537541cf4c5cd938 [file] [log] [blame]
Bram Moolenaara5792f52005-11-23 21:25:05 +00001" Vim completion script
Bram Moolenaard12f5c12006-01-25 22:10:52 +00002" Language: XML
Bram Moolenaara5792f52005-11-23 21:25:05 +00003" Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl )
Bram Moolenaar14b69452013-06-29 23:05:20 +02004" Last Change: 2013 Jun 29
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00005" Version: 1.9
Bram Moolenaar9964e462007-05-05 17:54:07 +00006"
7" Changelog:
Bram Moolenaar3577c6f2008-06-24 21:16:56 +00008" 1.9 - 2007 Aug 15
9" - fix closing of namespaced tags (Johannes Weiss)
Bram Moolenaar9964e462007-05-05 17:54:07 +000010" 1.8 - 2006 Jul 18
11" - allow for closing of xml tags even when data file isn't available
Bram Moolenaara5792f52005-11-23 21:25:05 +000012
13" This function will create Dictionary with users namespace strings and values
14" canonical (system) names of data files. Names should be lowercase,
15" descriptive to avoid any future conflicts. For example 'xhtml10s' should be
16" name for data of XHTML 1.0 Strict and 'xhtml10t' for XHTML 1.0 Transitional
Bram Moolenaar910f66f2006-04-05 20:41:53 +000017" User interface will be provided by XMLns command defined in ftplugin/xml.vim
Bram Moolenaara5792f52005-11-23 21:25:05 +000018" Currently supported canonicals are:
19" xhtml10s - XHTML 1.0 Strict
20" xsl - XSL
Bram Moolenaar18144c82006-04-12 21:52:12 +000021function! xmlcomplete#CreateConnection(canonical, ...) " {{{
Bram Moolenaara5792f52005-11-23 21:25:05 +000022
23 " When only one argument provided treat name as default namespace (without
24 " 'prefix:').
25 if exists("a:1")
26 let users = a:1
27 else
28 let users = 'DEFAULT'
29 endif
30
31 " Source data file. Due to suspected errors in autoload do it with
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000032 " :runtime.
Bram Moolenaara5792f52005-11-23 21:25:05 +000033 " TODO: make it properly (using autoload, that is) later
34 exe "runtime autoload/xml/".a:canonical.".vim"
35
36 " Remove all traces of unexisting files to return [] when trying
37 " omnicomplete something
38 " TODO: give warning about non-existing canonicals - should it be?
39 if !exists("g:xmldata_".a:canonical)
40 unlet! g:xmldata_connection
41 return 0
42 endif
43
44 " We need to initialize Dictionary to add key-value pair
45 if !exists("g:xmldata_connection")
46 let g:xmldata_connection = {}
47 endif
48
49 let g:xmldata_connection[users] = a:canonical
50
51endfunction
Bram Moolenaar18144c82006-04-12 21:52:12 +000052" }}}
Bram Moolenaara5792f52005-11-23 21:25:05 +000053
Bram Moolenaar18144c82006-04-12 21:52:12 +000054function! xmlcomplete#CreateEntConnection(...) " {{{
Bram Moolenaara5792f52005-11-23 21:25:05 +000055 if a:0 > 0
56 let g:xmldata_entconnect = a:1
57 else
58 let g:xmldata_entconnect = 'DEFAULT'
59 endif
60endfunction
Bram Moolenaar18144c82006-04-12 21:52:12 +000061" }}}
Bram Moolenaara5792f52005-11-23 21:25:05 +000062
63function! xmlcomplete#CompleteTags(findstart, base)
64 if a:findstart
65 " locate the start of the word
Bram Moolenaard12f5c12006-01-25 22:10:52 +000066 let curline = line('.')
Bram Moolenaara5792f52005-11-23 21:25:05 +000067 let line = getline('.')
68 let start = col('.') - 1
69 let compl_begin = col('.') - 2
70
71 while start >= 0 && line[start - 1] =~ '\(\k\|[:.-]\)'
72 let start -= 1
73 endwhile
74
75 if start >= 0 && line[start - 1] =~ '&'
76 let b:entitiescompl = 1
77 let b:compl_context = ''
78 return start
79 endif
80
81 let b:compl_context = getline('.')[0:(compl_begin)]
Bram Moolenaard12f5c12006-01-25 22:10:52 +000082 if b:compl_context !~ '<[^>]*$'
83 " Look like we may have broken tag. Check previous lines. Up to
84 " 10?
85 let i = 1
86 while 1
87 let context_line = getline(curline-i)
88 if context_line =~ '<[^>]*$'
89 " Yep, this is this line
Bram Moolenaar9964e462007-05-05 17:54:07 +000090 let context_lines = getline(curline-i, curline-1) + [b:compl_context]
Bram Moolenaard12f5c12006-01-25 22:10:52 +000091 let b:compl_context = join(context_lines, ' ')
92 break
Bram Moolenaarc15ef302006-03-19 22:11:16 +000093 elseif context_line =~ '>[^<]*$' || i == curline
Bram Moolenaard12f5c12006-01-25 22:10:52 +000094 " Normal tag line, no need for completion at all
Bram Moolenaarc15ef302006-03-19 22:11:16 +000095 " OR reached first line without tag at all
Bram Moolenaard12f5c12006-01-25 22:10:52 +000096 let b:compl_context = ''
97 break
98 endif
99 let i += 1
100 endwhile
101 " Make sure we don't have counter
102 unlet! i
103 endif
104 let b:compl_context = matchstr(b:compl_context, '.*\zs<.*')
Bram Moolenaara5792f52005-11-23 21:25:05 +0000105
106 " Make sure we will have only current namespace
107 unlet! b:xml_namespace
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000108 let b:xml_namespace = matchstr(b:compl_context, '^<\zs\k*\ze:')
Bram Moolenaara5792f52005-11-23 21:25:05 +0000109 if b:xml_namespace == ''
110 let b:xml_namespace = 'DEFAULT'
111 endif
112
113 return start
114
115 else
Bram Moolenaara5792f52005-11-23 21:25:05 +0000116 " Initialize base return lists
117 let res = []
118 let res2 = []
119 " a:base is very short - we need context
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000120 if len(b:compl_context) == 0 && !exists("b:entitiescompl")
121 return []
122 endif
123 let context = matchstr(b:compl_context, '^<\zs.*')
Bram Moolenaara5792f52005-11-23 21:25:05 +0000124 unlet! b:compl_context
Bram Moolenaar9964e462007-05-05 17:54:07 +0000125 " There is no connection of namespace and data file.
126 if !exists("g:xmldata_connection") || g:xmldata_connection == {}
127 " There is still possibility we may do something - eg. close tag
128 let b:unaryTagsStack = "base meta link hr br param img area input col"
129 if context =~ '^\/'
130 let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack")
131 return [opentag.">"]
132 else
133 return []
134 endif
135 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000136
137 " Make entities completion
138 if exists("b:entitiescompl")
139 unlet! b:entitiescompl
140
141 if !exists("g:xmldata_entconnect") || g:xmldata_entconnect == 'DEFAULT'
142 let values = g:xmldata{'_'.g:xmldata_connection['DEFAULT']}['vimxmlentities']
143 else
144 let values = g:xmldata{'_'.g:xmldata_entconnect}['vimxmlentities']
145 endif
146
147 " Get only lines with entity declarations but throw out
148 " parameter-entities - they may be completed in future
149 let entdecl = filter(getline(1, "$"), 'v:val =~ "<!ENTITY\\s\\+[^%]"')
150
151 if len(entdecl) > 0
152 let intent = map(copy(entdecl), 'matchstr(v:val, "<!ENTITY\\s\\+\\zs\\(\\k\\|[.-:]\\)\\+\\ze")')
153 let values = intent + values
154 endif
155
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000156 if len(a:base) == 1
157 for m in values
158 if m =~ '^'.a:base
159 call add(res, m.';')
160 endif
161 endfor
162 return res
163 else
164 for m in values
165 if m =~? '^'.a:base
166 call add(res, m.';')
167 elseif m =~? a:base
168 call add(res2, m.';')
169 endif
170 endfor
Bram Moolenaara5792f52005-11-23 21:25:05 +0000171
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000172 return res + res2
173 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000174
175 endif
176 if context =~ '>'
177 " Generally if context contains > it means we are outside of tag and
178 " should abandon action
179 return []
180 endif
181
182 " find tags matching with "a:base"
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000183 " If a:base contains white space it is attribute.
Bram Moolenaara5792f52005-11-23 21:25:05 +0000184 " It could be also value of attribute...
185 " We have to get first word to offer
186 " proper completions
187 if context == ''
188 let tag = ''
189 else
190 let tag = split(context)[0]
191 endif
192 " Get rid of namespace
193 let tag = substitute(tag, '^'.b:xml_namespace.':', '', '')
194
195
196 " Get last word, it should be attr name
197 let attr = matchstr(context, '.*\s\zs.*')
198 " Possible situations where any prediction would be difficult:
199 " 1. Events attributes
200 if context =~ '\s'
201
202 " If attr contains =\s*[\"'] we catched value of attribute
Bram Moolenaar8424a622006-04-19 21:23:36 +0000203 if attr =~ "=\s*[\"']" || attr =~ "=\s*$"
Bram Moolenaara5792f52005-11-23 21:25:05 +0000204 " Let do attribute specific completion
205 let attrname = matchstr(attr, '.*\ze\s*=')
Bram Moolenaar8424a622006-04-19 21:23:36 +0000206 let entered_value = matchstr(attr, ".*=\\s*[\"']\\?\\zs.*")
Bram Moolenaara5792f52005-11-23 21:25:05 +0000207
208 if tag =~ '^[?!]'
209 " Return nothing if we are inside of ! or ? tag
210 return []
211 else
Bram Moolenaar8424a622006-04-19 21:23:36 +0000212 if has_key(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}, tag) && has_key(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}[tag][1], attrname)
213 let values = g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}[tag][1][attrname]
214 else
215 return []
216 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000217 endif
218
219 if len(values) == 0
220 return []
221 endif
222
223 " We need special version of sbase
224 let attrbase = matchstr(context, ".*[\"']")
225 let attrquote = matchstr(attrbase, '.$')
Bram Moolenaar8424a622006-04-19 21:23:36 +0000226 if attrquote !~ "['\"]"
227 let attrquoteopen = '"'
228 let attrquote = '"'
229 else
230 let attrquoteopen = ''
231 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000232
233 for m in values
234 " This if is needed to not offer all completions as-is
235 " alphabetically but sort them. Those beginning with entered
236 " part will be as first choices
237 if m =~ '^'.entered_value
Bram Moolenaar8424a622006-04-19 21:23:36 +0000238 call add(res, attrquoteopen . m . attrquote.' ')
Bram Moolenaara5792f52005-11-23 21:25:05 +0000239 elseif m =~ entered_value
Bram Moolenaar8424a622006-04-19 21:23:36 +0000240 call add(res2, attrquoteopen . m . attrquote.' ')
Bram Moolenaara5792f52005-11-23 21:25:05 +0000241 endif
242 endfor
243
244 return res + res2
245
246 endif
247
248 if tag =~ '?xml'
249 " Two possible arguments for <?xml> plus variation
250 let attrs = ['encoding', 'version="1.0"', 'version']
251 elseif tag =~ '^!'
252 " Don't make completion at all
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000253 "
Bram Moolenaara5792f52005-11-23 21:25:05 +0000254 return []
255 else
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000256 if !has_key(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}, tag)
257 " Abandon when data file isn't complete
258 return []
259 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000260 let attrs = keys(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}[tag][1])
261 endif
262
263 for m in sort(attrs)
264 if m =~ '^'.attr
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000265 call add(res, m)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000266 elseif m =~ attr
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000267 call add(res2, m)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000268 endif
269 endfor
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000270 let menu = res + res2
271 let final_menu = []
272 if has_key(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}, 'vimxmlattrinfo')
273 for i in range(len(menu))
274 let item = menu[i]
275 if has_key(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}['vimxmlattrinfo'], item)
276 let m_menu = g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}['vimxmlattrinfo'][item][0]
277 let m_info = g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}['vimxmlattrinfo'][item][1]
278 else
279 let m_menu = ''
280 let m_info = ''
281 endif
282 if tag !~ '^[?!]' && len(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}[tag][1][item]) > 0 && g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}[tag][1][item][0] =~ '^\(BOOL\|'.item.'\)$'
283 let item = item
284 else
285 let item .= '="'
286 endif
287 let final_menu += [{'word':item, 'menu':m_menu, 'info':m_info}]
288 endfor
289 else
290 for i in range(len(menu))
291 let item = menu[i]
292 if tag !~ '^[?!]' && len(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}[tag][1][item]) > 0 && g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}[tag][1][item][0] =~ '^\(BOOL\|'.item.'\)$'
293 let item = item
294 else
295 let item .= '="'
296 endif
297 let final_menu += [item]
298 endfor
299 endif
300 return final_menu
Bram Moolenaara5792f52005-11-23 21:25:05 +0000301
302 endif
303 " Close tag
304 let b:unaryTagsStack = "base meta link hr br param img area input col"
305 if context =~ '^\/'
306 let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack")
307 return [opentag.">"]
308 endif
309
310 " Complete elements of XML structure
311 " TODO: #REQUIRED, #IMPLIED, #FIXED, #PCDATA - but these should be detected like
312 " entities - in first run
313 " keywords: CDATA, ID, IDREF, IDREFS, ENTITY, ENTITIES, NMTOKEN, NMTOKENS
314 " are hardly recognizable but keep it in reserve
315 " also: EMPTY ANY SYSTEM PUBLIC DATA
316 if context =~ '^!'
317 let tags = ['!ELEMENT', '!DOCTYPE', '!ATTLIST', '!ENTITY', '!NOTATION', '![CDATA[', '![INCLUDE[', '![IGNORE[']
318
319 for m in tags
320 if m =~ '^'.context
321 let m = substitute(m, '^!\[\?', '', '')
322 call add(res, m)
323 elseif m =~ context
324 let m = substitute(m, '^!\[\?', '', '')
325 call add(res2, m)
326 endif
327 endfor
328
329 return res + res2
330
331 endif
332
333 " Complete text declaration
Bram Moolenaara5792f52005-11-23 21:25:05 +0000334 if context =~ '^?'
335 let tags = ['?xml']
336
337 for m in tags
338 if m =~ '^'.context
339 call add(res, substitute(m, '^?', '', ''))
340 elseif m =~ context
341 call add(res, substitute(m, '^?', '', ''))
342 endif
343 endfor
344
345 return res + res2
346
347 endif
348
349 " Deal with tag completion.
350 let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack")
351 let opentag = substitute(opentag, '^\k*:', '', '')
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000352 if opentag == ''
Bram Moolenaar7e8fd632006-02-18 22:14:51 +0000353 "return []
354 let tags = keys(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]})
355 call filter(tags, 'v:val !~ "^vimxml"')
356 else
Bram Moolenaar18144c82006-04-12 21:52:12 +0000357 if !has_key(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}, opentag)
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000358 " Abandon when data file isn't complete
359 return []
360 endif
Bram Moolenaar7e8fd632006-02-18 22:14:51 +0000361 let tags = g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}[opentag][0]
Bram Moolenaard12f5c12006-01-25 22:10:52 +0000362 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000363
Bram Moolenaara5792f52005-11-23 21:25:05 +0000364 let context = substitute(context, '^\k*:', '', '')
365
Bram Moolenaara5792f52005-11-23 21:25:05 +0000366 for m in tags
367 if m =~ '^'.context
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000368 call add(res, m)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000369 elseif m =~ context
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000370 call add(res2, m)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000371 endif
372 endfor
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000373 let menu = res + res2
Bram Moolenaar18144c82006-04-12 21:52:12 +0000374 if b:xml_namespace == 'DEFAULT'
375 let xml_namespace = ''
376 else
377 let xml_namespace = b:xml_namespace.':'
378 endif
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000379 if has_key(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}, 'vimxmltaginfo')
380 let final_menu = []
381 for i in range(len(menu))
382 let item = menu[i]
383 if has_key(g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}['vimxmltaginfo'], item)
384 let m_menu = g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}['vimxmltaginfo'][item][0]
385 let m_info = g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}['vimxmltaginfo'][item][1]
386 else
387 let m_menu = ''
388 let m_info = ''
389 endif
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000390 let final_menu += [{'word':xml_namespace.item, 'menu':m_menu, 'info':m_info}]
391 endfor
392 else
Bram Moolenaar18144c82006-04-12 21:52:12 +0000393 let final_menu = map(menu, 'xml_namespace.v:val')
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000394 endif
Bram Moolenaar18144c82006-04-12 21:52:12 +0000395
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +0000396 return final_menu
Bram Moolenaara5792f52005-11-23 21:25:05 +0000397
398 endif
399endfunction
400
Bram Moolenaar18144c82006-04-12 21:52:12 +0000401" MM: This is severely reduced closetag.vim used with kind permission of Steven
Bram Moolenaara5792f52005-11-23 21:25:05 +0000402" Mueller
403" Changes: strip all comments; delete error messages; add checking for
404" namespace
405" Author: Steven Mueller <diffusor@ugcs.caltech.edu>
406" Last Modified: Tue May 24 13:29:48 PDT 2005
407" Version: 0.9.1
408
409function! xmlcomplete#GetLastOpenTag(unaryTagsStack)
410 let linenum=line('.')
411 let lineend=col('.') - 1 " start: cursor position
412 let first=1 " flag for first line searched
413 let b:TagStack='' " main stack of tags
414 let startInComment=s:InComment()
415
416 if exists("b:xml_namespace")
417 if b:xml_namespace == 'DEFAULT'
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000418 let tagpat='</\=\(\k\|[.:-]\)\+\|/>'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000419 else
420 let tagpat='</\='.b:xml_namespace.':\(\k\|[.-]\)\+\|/>'
421 endif
422 else
Bram Moolenaar3577c6f2008-06-24 21:16:56 +0000423 let tagpat='</\=\(\k\|[.:-]\)\+\|/>'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000424 endif
425 while (linenum>0)
426 let line=getline(linenum)
427 if first
428 let line=strpart(line,0,lineend)
429 else
430 let lineend=strlen(line)
431 endif
432 let b:lineTagStack=''
433 let mpos=0
434 let b:TagCol=0
435 while (mpos > -1)
436 let mpos=matchend(line,tagpat)
437 if mpos > -1
438 let b:TagCol=b:TagCol+mpos
439 let tag=matchstr(line,tagpat)
440
441 if exists('b:closetag_disable_synID') || startInComment==s:InCommentAt(linenum, b:TagCol)
442 let b:TagLine=linenum
443 call s:Push(matchstr(tag,'[^<>]\+'),'b:lineTagStack')
444 endif
445 let lineend=lineend-mpos
446 let line=strpart(line,mpos,lineend)
447 endif
448 endwhile
449 while (!s:EmptystackP('b:lineTagStack'))
450 let tag=s:Pop('b:lineTagStack')
451 if match(tag, '^/') == 0 "found end tag
452 call s:Push(tag,'b:TagStack')
453 elseif s:EmptystackP('b:TagStack') && !s:Instack(tag, a:unaryTagsStack) "found unclosed tag
454 return tag
455 else
456 let endtag=s:Peekstack('b:TagStack')
457 if endtag == '/'.tag || endtag == '/'
458 call s:Pop('b:TagStack') "found a open/close tag pair
459 elseif !s:Instack(tag, a:unaryTagsStack) "we have a mismatch error
460 return ''
461 endif
462 endif
463 endwhile
464 let linenum=linenum-1 | let first=0
465 endwhile
466return ''
467endfunction
468
469function! s:InComment()
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000470 return synIDattr(synID(line('.'), col('.'), 0), 'name') =~ 'Comment\|String'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000471endfunction
472
473function! s:InCommentAt(line, col)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000474 return synIDattr(synID(a:line, a:col, 0), 'name') =~ 'Comment\|String'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000475endfunction
476
477function! s:SetKeywords()
Bram Moolenaar14b69452013-06-29 23:05:20 +0200478 let s:IsKeywordBak=&l:iskeyword
479 let &l:iskeyword='33-255'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000480endfunction
481
482function! s:RestoreKeywords()
Bram Moolenaar14b69452013-06-29 23:05:20 +0200483 let &l:iskeyword=s:IsKeywordBak
Bram Moolenaara5792f52005-11-23 21:25:05 +0000484endfunction
485
486function! s:Push(el, sname)
487 if !s:EmptystackP(a:sname)
488 exe 'let '.a:sname."=a:el.' '.".a:sname
489 else
490 exe 'let '.a:sname.'=a:el'
491 endif
492endfunction
493
494function! s:EmptystackP(sname)
495 exe 'let stack='.a:sname
496 if match(stack,'^ *$') == 0
497 return 1
498 else
499 return 0
500 endif
501endfunction
502
503function! s:Instack(el, sname)
504 exe 'let stack='.a:sname
505 call s:SetKeywords()
506 let m=match(stack, '\<'.a:el.'\>')
507 call s:RestoreKeywords()
508 if m < 0
509 return 0
510 else
511 return 1
512 endif
513endfunction
514
515function! s:Peekstack(sname)
516 call s:SetKeywords()
517 exe 'let stack='.a:sname
518 let top=matchstr(stack, '\<.\{-1,}\>')
519 call s:RestoreKeywords()
520 return top
521endfunction
522
523function! s:Pop(sname)
524 if s:EmptystackP(a:sname)
525 return ''
526 endif
527 exe 'let stack='.a:sname
528 call s:SetKeywords()
529 let loc=matchend(stack,'\<.\{-1,}\>')
530 exe 'let '.a:sname.'=strpart(stack, loc+1, strlen(stack))'
531 let top=strpart(stack, match(stack, '\<'), loc)
532 call s:RestoreKeywords()
533 return top
534endfunction
535
536function! s:Clearstack(sname)
537 exe 'let '.a:sname."=''"
538endfunction
Bram Moolenaar18144c82006-04-12 21:52:12 +0000539" vim:set foldmethod=marker: