blob: 122aa096f69d7217f14016a0883a690185de9a28 [file] [log] [blame]
Bram Moolenaare344bea2005-09-01 20:46:49 +00001" Vim completion script
2" Language: C
3" Maintainer: Bram Moolenaar <Bram@vim.org>
Bram Moolenaar1056d982006-03-09 22:37:52 +00004" Last Change: 2006 Mar 09
Bram Moolenaare344bea2005-09-01 20:46:49 +00005
Bram Moolenaara4a08382005-09-09 19:52:02 +00006
Bram Moolenaarf75a9632005-09-13 21:20:47 +00007" This function is used for the 'omnifunc' option.
Bram Moolenaare344bea2005-09-01 20:46:49 +00008function! ccomplete#Complete(findstart, base)
9 if a:findstart
Bram Moolenaar0e5bd962006-02-04 00:59:56 +000010 " Locate the start of the item, including ".", "->" and "[...]".
Bram Moolenaare344bea2005-09-01 20:46:49 +000011 let line = getline('.')
12 let start = col('.') - 1
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000013 let lastword = -1
Bram Moolenaare344bea2005-09-01 20:46:49 +000014 while start > 0
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000015 if line[start - 1] =~ '\w'
16 let start -= 1
17 elseif line[start - 1] =~ '\.'
18 if lastword == -1
19 let lastword = start
20 endif
Bram Moolenaare344bea2005-09-01 20:46:49 +000021 let start -= 1
22 elseif start > 1 && line[start - 2] == '-' && line[start - 1] == '>'
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000023 if lastword == -1
24 let lastword = start
25 endif
Bram Moolenaare344bea2005-09-01 20:46:49 +000026 let start -= 2
Bram Moolenaar0e5bd962006-02-04 00:59:56 +000027 elseif line[start - 1] == ']'
28 " Skip over [...].
29 let n = 0
30 let start -= 1
31 while start > 0
32 let start -= 1
33 if line[start] == '['
34 if n == 0
35 break
36 endif
37 let n -= 1
38 elseif line[start] == ']' " nested []
39 let n += 1
40 endif
41 endwhile
Bram Moolenaare344bea2005-09-01 20:46:49 +000042 else
43 break
44 endif
45 endwhile
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000046
47 " Return the column of the last word, which is going to be changed.
48 " Remember the text that comes before it in s:prepended.
49 if lastword == -1
50 let s:prepended = ''
51 return start
52 endif
53 let s:prepended = strpart(line, start, lastword - start)
54 return lastword
Bram Moolenaare344bea2005-09-01 20:46:49 +000055 endif
56
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +000057 " Return list of matches.
58
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000059 let base = s:prepended . a:base
60
Bram Moolenaar0e5bd962006-02-04 00:59:56 +000061 " Don't do anything for an empty base, would result in all the tags in the
62 " tags file.
63 if base == ''
64 return []
65 endif
66
Bram Moolenaar1056d982006-03-09 22:37:52 +000067 " init cache for vimgrep to empty
68 let s:grepCache = {}
69
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +000070 " Split item in words, keep empty word after "." or "->".
71 " "aa" -> ['aa'], "aa." -> ['aa', ''], "aa.bb" -> ['aa', 'bb'], etc.
Bram Moolenaar0e5bd962006-02-04 00:59:56 +000072 " We can't use split, because we need to skip nested [...].
73 let items = []
74 let s = 0
75 while 1
76 let e = match(base, '\.\|->\|\[', s)
77 if e < 0
78 if s == 0 || base[s - 1] != ']'
79 call add(items, strpart(base, s))
80 endif
81 break
Bram Moolenaard5cdbeb2005-10-10 20:59:28 +000082 endif
Bram Moolenaar0e5bd962006-02-04 00:59:56 +000083 if s == 0 || base[s - 1] != ']'
84 call add(items, strpart(base, s, e - s))
85 endif
86 if base[e] == '.'
87 let s = e + 1 " skip over '.'
88 elseif base[e] == '-'
89 let s = e + 2 " skip over '->'
90 else
91 " Skip over [...].
92 let n = 0
93 let s = e
94 let e += 1
95 while e < len(base)
96 if base[e] == ']'
97 if n == 0
98 break
99 endif
100 let n -= 1
101 elseif base[e] == '[' " nested [...]
102 let n += 1
103 endif
104 let e += 1
105 endwhile
106 let e += 1
107 call add(items, strpart(base, s, e - s))
108 let s = e
109 endif
110 endwhile
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000111
Bram Moolenaara4a08382005-09-09 19:52:02 +0000112 " Find the variable items[0].
113 " 1. in current function (like with "gd")
114 " 2. in tags file(s) (like with ":tag")
115 " 3. in current file (like with "gD")
116 let res = []
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000117 if searchdecl(items[0], 0, 1) == 0
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000118 " Found, now figure out the type.
119 " TODO: join previous line if it makes sense
120 let line = getline('.')
121 let col = col('.')
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000122 if len(items) == 1
123 " Completing one word and it's a local variable: May add '[', '.' or
124 " '->'.
125 let match = items[0]
126 if match(line, match . '\s*\[') > 0
127 let match .= '['
128 else
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000129 let res = s:Nextitem(strpart(line, 0, col), [''], 0, 1)
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000130 if len(res) > 0
131 " There are members, thus add "." or "->".
132 if match(line, '\*[ \t(]*' . match . '\>') > 0
133 let match .= '->'
134 else
135 let match .= '.'
136 endif
137 endif
138 endif
139 let res = [{'match': match, 'tagline' : ''}]
140 else
141 " Completing "var.", "var.something", etc.
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000142 let res = s:Nextitem(strpart(line, 0, col), items[1:], 0, 1)
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000143 endif
144 endif
145
146 if len(items) == 1
147 " Only one part, no "." or "->": complete from tags file.
148 call extend(res, map(taglist('^' . base), 's:Tag2item(v:val)'))
Bram Moolenaara4a08382005-09-09 19:52:02 +0000149 endif
150
151 if len(res) == 0
152 " Find the variable in the tags file(s)
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000153 let diclist = taglist('^' . items[0] . '$')
154
155 let res = []
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000156 for i in range(len(diclist))
Bram Moolenaara4a08382005-09-09 19:52:02 +0000157 " New ctags has the "typename" field.
158 if has_key(diclist[i], 'typename')
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000159 call extend(res, s:StructMembers(diclist[i]['typename'], items[1:], 1))
Bram Moolenaara4a08382005-09-09 19:52:02 +0000160 endif
161
162 " For a variable use the command, which must be a search pattern that
163 " shows the declaration of the variable.
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000164 if diclist[i]['kind'] == 'v'
165 let line = diclist[i]['cmd']
166 if line[0] == '/' && line[1] == '^'
Bram Moolenaare3226be2005-12-18 22:10:00 +0000167 let col = match(line, '\<' . items[0] . '\>')
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000168 call extend(res, s:Nextitem(strpart(line, 2, col - 2), items[1:], 0, 1))
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000169 endif
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000170 endif
171 endfor
172 endif
173
Bram Moolenaara4a08382005-09-09 19:52:02 +0000174 if len(res) == 0 && searchdecl(items[0], 1) == 0
175 " Found, now figure out the type.
176 " TODO: join previous line if it makes sense
177 let line = getline('.')
178 let col = col('.')
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000179 let res = s:Nextitem(strpart(line, 0, col), items[1:], 0, 1)
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000180 endif
181
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000182 " If the last item(s) are [...] they need to be added to the matches.
183 let last = len(items) - 1
184 let brackets = ''
185 while last >= 0
186 if items[last][0] != '['
187 break
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000188 endif
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000189 let brackets = items[last] . brackets
190 let last -= 1
191 endwhile
Bram Moolenaara4a08382005-09-09 19:52:02 +0000192
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000193 return map(res, 's:Tagline2item(v:val, brackets)')
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000194endfunc
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000195
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000196function! s:GetAddition(line, match, memarg, bracket)
197 " Guess if the item is an array.
198 if a:bracket && match(a:line, a:match . '\s*\[') > 0
199 return '['
200 endif
201
202 " Check if the item has members.
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000203 if len(s:SearchMembers(a:memarg, [''], 0)) > 0
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000204 " If there is a '*' before the name use "->".
205 if match(a:line, '\*[ \t(]*' . a:match . '\>') > 0
206 return '->'
207 else
208 return '.'
Bram Moolenaar280f1262006-01-30 00:14:18 +0000209 endif
210 endif
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000211 return ''
212endfunction
213
214" Turn the tag info "val" into an item for completion.
215" "val" is is an item in the list returned by taglist().
216" If it is a variable we may add "." or "->". Don't do it for other types,
217" such as a typedef, by not including the info that s:GetAddition() uses.
218function! s:Tag2item(val)
Bram Moolenaarf52c7252006-02-10 23:23:57 +0000219 let x = s:Tagcmd2extra(a:val['cmd'], a:val['name'], a:val['filename'])
220
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000221 if has_key(a:val, "kind")
222 if a:val["kind"] == 'v'
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000223 return {'match': a:val['name'], 'tagline': "\t" . a:val['cmd'], 'dict': a:val, 'extra': x}
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000224 endif
225 if a:val["kind"] == 'f'
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000226 return {'match': a:val['name'] . '(', 'tagline': "", 'extra': x}
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000227 endif
228 endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000229 return {'match': a:val['name'], 'tagline': '', 'extra': x}
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000230endfunction
231
232" Turn a match item "val" into an item for completion.
233" "val['match']" is the matching item.
234" "val['tagline']" is the tagline in which the last part was found.
235function! s:Tagline2item(val, brackets)
Bram Moolenaarf52c7252006-02-10 23:23:57 +0000236 let line = a:val['tagline']
237 let word = a:val['match'] . a:brackets . s:GetAddition(line, a:val['match'], [a:val], a:brackets == '')
Bram Moolenaar8b6144b2006-02-08 09:20:24 +0000238 if has_key(a:val, 'extra')
239 return {'word': word, 'menu': a:val['extra']}
240 endif
Bram Moolenaarf52c7252006-02-10 23:23:57 +0000241
242 " Isolate the command after the tag and filename.
243 let s = matchstr(line, '[^\t]*\t[^\t]*\t\zs\(/^.*$/\|[^\t]*\)\ze\(;"\t\|\t\|$\)')
244 if s != ''
245 return {'word': word, 'menu': s:Tagcmd2extra(s, a:val['match'], matchstr(line, '[^\t]*\t\zs[^\t]*\ze\t'))}
246 endif
247 return {'word': word}
Bram Moolenaar280f1262006-01-30 00:14:18 +0000248endfunction
249
Bram Moolenaarf52c7252006-02-10 23:23:57 +0000250" Turn a command from a tag line to something that is useful in the menu
251function! s:Tagcmd2extra(cmd, name, fname)
252 if a:cmd =~ '^/^'
253 " The command is a search command, useful to see what it is.
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000254 let x = matchstr(a:cmd, '^/^\s*\zs.*\ze$/')
255 let x = substitute(x, '\<' . a:name . '\>', '@@', '')
Bram Moolenaarf52c7252006-02-10 23:23:57 +0000256 let x = substitute(x, '\\\(.\)', '\1', 'g')
257 let x = x . ' - ' . a:fname
258 elseif a:cmd =~ '^\d*$'
259 " The command is a line number, the file name is more useful.
260 let x = a:fname . ' - ' . a:cmd
261 else
262 " Not recognized, use command and file name.
263 let x = a:cmd . ' - ' . a:fname
264 endif
265 return x
266endfunction
Bram Moolenaar280f1262006-01-30 00:14:18 +0000267
Bram Moolenaara4a08382005-09-09 19:52:02 +0000268" Find composing type in "lead" and match items[0] with it.
269" Repeat this recursively for items[1], if it's there.
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000270" When resolving typedefs "depth" is used to avoid infinite recursion.
Bram Moolenaara4a08382005-09-09 19:52:02 +0000271" Return the list of matches.
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000272function! s:Nextitem(lead, items, depth, all)
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000273
274 " Use the text up to the variable name and split it in tokens.
275 let tokens = split(a:lead, '\s\+\|\<')
276
277 " Try to recognize the type of the variable. This is rough guessing...
Bram Moolenaara4a08382005-09-09 19:52:02 +0000278 let res = []
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000279 for tidx in range(len(tokens))
280
Bram Moolenaar1056d982006-03-09 22:37:52 +0000281 " Skip tokens starting with a non-ID character.
282 if tokens[tidx] !~ '^\h'
283 continue
284 endif
285
Bram Moolenaara4a08382005-09-09 19:52:02 +0000286 " Recognize "struct foobar" and "union foobar".
287 if (tokens[tidx] == 'struct' || tokens[tidx] == 'union') && tidx + 1 < len(tokens)
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000288 let res = s:StructMembers(tokens[tidx] . ':' . tokens[tidx + 1], a:items, a:all)
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000289 break
290 endif
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000291
Bram Moolenaara4a08382005-09-09 19:52:02 +0000292 " TODO: add more reserved words
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000293 if index(['int', 'short', 'char', 'float', 'double', 'static', 'unsigned', 'extern'], tokens[tidx]) >= 0
Bram Moolenaara4a08382005-09-09 19:52:02 +0000294 continue
295 endif
296
297 " Use the tags file to find out if this is a typedef.
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000298 let diclist = taglist('^' . tokens[tidx] . '$')
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000299 for tagidx in range(len(diclist))
Bram Moolenaara4a08382005-09-09 19:52:02 +0000300 " New ctags has the "typename" field.
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000301 if has_key(diclist[tagidx], 'typename')
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000302 call extend(res, s:StructMembers(diclist[tagidx]['typename'], a:items, a:all))
Bram Moolenaara4a08382005-09-09 19:52:02 +0000303 continue
304 endif
305
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000306 " Only handle typedefs here.
307 if diclist[tagidx]['kind'] != 't'
308 continue
309 endif
310
311 " For old ctags we recognize "typedef struct aaa" and
312 " "typedef union bbb" in the tags file command.
313 let cmd = diclist[tagidx]['cmd']
314 let ei = matchend(cmd, 'typedef\s\+')
315 if ei > 1
316 let cmdtokens = split(strpart(cmd, ei), '\s\+\|\<')
317 if len(cmdtokens) > 1
318 if cmdtokens[0] == 'struct' || cmdtokens[0] == 'union'
319 let name = ''
320 " Use the first identifier after the "struct" or "union"
321 for ti in range(len(cmdtokens) - 1)
322 if cmdtokens[ti] =~ '^\w'
323 let name = cmdtokens[ti]
324 break
325 endif
326 endfor
327 if name != ''
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000328 call extend(res, s:StructMembers(cmdtokens[0] . ':' . name, a:items, a:all))
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000329 endif
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000330 elseif a:depth < 10
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000331 " Could be "typedef other_T some_T".
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000332 call extend(res, s:Nextitem(cmdtokens[0], a:items, a:depth + 1, a:all))
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000333 endif
334 endif
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000335 endif
336 endfor
Bram Moolenaara4a08382005-09-09 19:52:02 +0000337 if len(res) > 0
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000338 break
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000339 endif
Bram Moolenaara4a08382005-09-09 19:52:02 +0000340 endfor
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000341
Bram Moolenaara4a08382005-09-09 19:52:02 +0000342 return res
343endfunction
344
345
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000346" Search for members of structure "typename" in tags files.
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000347" Return a list with resulting matches.
348" Each match is a dictionary with "match" and "tagline" entries.
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000349" When "all" is non-zero find all, otherwise just return 1 if there is any
350" member.
351function! s:StructMembers(typename, items, all)
Bram Moolenaara4a08382005-09-09 19:52:02 +0000352 " Todo: What about local structures?
353 let fnames = join(map(tagfiles(), 'escape(v:val, " \\")'))
354 if fnames == ''
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000355 return []
Bram Moolenaara4a08382005-09-09 19:52:02 +0000356 endif
357
358 let typename = a:typename
359 let qflist = []
Bram Moolenaar1056d982006-03-09 22:37:52 +0000360 let cached = 0
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000361 if a:all == 0
362 let n = '1' " stop at first found match
Bram Moolenaar1056d982006-03-09 22:37:52 +0000363 if has_key(s:grepCache, a:typename)
364 let qflist = s:grepCache[a:typename]
365 let cached = 1
366 endif
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000367 else
368 let n = ''
369 endif
Bram Moolenaar1056d982006-03-09 22:37:52 +0000370 if !cached
371 while 1
372 exe 'silent! ' . n . 'vimgrep /\t' . typename . '\(\t\|$\)/j ' . fnames
373
374 let qflist = getqflist()
375 if len(qflist) > 0 || match(typename, "::") < 0
376 break
377 endif
378 " No match for "struct:context::name", remove "context::" and try again.
379 let typename = substitute(typename, ':[^:]*::', ':', '')
380 endwhile
381
382 if a:all == 0
383 " Store the result to be able to use it again later.
384 let s:grepCache[a:typename] = qflist
Bram Moolenaara4a08382005-09-09 19:52:02 +0000385 endif
Bram Moolenaar1056d982006-03-09 22:37:52 +0000386 endif
Bram Moolenaara4a08382005-09-09 19:52:02 +0000387
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000388 let matches = []
Bram Moolenaara4a08382005-09-09 19:52:02 +0000389 for l in qflist
390 let memb = matchstr(l['text'], '[^\t]*')
391 if memb =~ '^' . a:items[0]
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000392 call add(matches, {'match': memb, 'tagline': l['text']})
Bram Moolenaara4a08382005-09-09 19:52:02 +0000393 endif
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000394 endfor
395
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000396 if len(matches) > 0
Bram Moolenaar0e5bd962006-02-04 00:59:56 +0000397 " Skip over [...] items
398 let idx = 1
399 while 1
400 if idx >= len(a:items)
401 return matches " No further items, return the result.
402 endif
403 if a:items[idx][0] != '['
404 break
405 endif
406 let idx += 1
407 endwhile
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000408
409 " More items following. For each of the possible members find the
410 " matching following members.
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000411 return s:SearchMembers(matches, a:items[idx :], a:all)
Bram Moolenaarcaa0fcf2005-09-07 21:21:14 +0000412 endif
413
414 " Failed to find anything.
415 return []
Bram Moolenaare344bea2005-09-01 20:46:49 +0000416endfunction
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000417
418" For matching members, find matches for following items.
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000419" When "all" is non-zero find all, otherwise just return 1 if there is any
420" member.
421function! s:SearchMembers(matches, items, all)
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000422 let res = []
423 for i in range(len(a:matches))
Bram Moolenaar280f1262006-01-30 00:14:18 +0000424 let typename = ''
425 if has_key(a:matches[i], 'dict')
Bram Moolenaar280f1262006-01-30 00:14:18 +0000426 if has_key(a:matches[i].dict, 'typename')
427 let typename = a:matches[i].dict['typename']
428 endif
429 let line = "\t" . a:matches[i].dict['cmd']
430 else
431 let line = a:matches[i]['tagline']
432 let e = matchend(line, '\ttypename:')
433 if e > 0
434 " Use typename field
435 let typename = matchstr(line, '[^\t]*', e)
436 endif
437 endif
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000438
Bram Moolenaar280f1262006-01-30 00:14:18 +0000439 if typename != ''
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000440 call extend(res, s:StructMembers(typename, a:items, a:all))
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000441 else
442 " Use the search command (the declaration itself).
443 let s = match(line, '\t\zs/^')
444 if s > 0
Bram Moolenaar280f1262006-01-30 00:14:18 +0000445 let e = match(line, '\<' . a:matches[i]['match'] . '\>', s)
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000446 if e > 0
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000447 call extend(res, s:Nextitem(strpart(line, s, e - s), a:items, 0, a:all))
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000448 endif
449 endif
450 endif
Bram Moolenaar1f35bf92006-03-07 22:38:47 +0000451 if a:all == 0 && len(res) > 0
452 break
453 endif
Bram Moolenaarf75a9632005-09-13 21:20:47 +0000454 endfor
455 return res
456endfunc