comparison runtime/autoload/ccomplete.vim @ 716:8ae24f338cab v7.0217

updated for version 7.0217
author vimboss
date Tue, 07 Mar 2006 22:38:47 +0000
parents 0137e7c3d31b
children e180933b876a
comparison
equal deleted inserted replaced
715:b526e10493b1 716:8ae24f338cab
1 " Vim completion script 1 " Vim completion script
2 " Language: C 2 " Language: C
3 " Maintainer: Bram Moolenaar <Bram@vim.org> 3 " Maintainer: Bram Moolenaar <Bram@vim.org>
4 " Last Change: 2006 Feb 10 4 " Last Change: 2006 Mar 07
5 5
6 6
7 " This function is used for the 'omnifunc' option. 7 " This function is used for the 'omnifunc' option.
8 function! ccomplete#Complete(findstart, base) 8 function! ccomplete#Complete(findstart, base)
9 if a:findstart 9 if a:findstart
121 " '->'. 121 " '->'.
122 let match = items[0] 122 let match = items[0]
123 if match(line, match . '\s*\[') > 0 123 if match(line, match . '\s*\[') > 0
124 let match .= '[' 124 let match .= '['
125 else 125 else
126 let res = s:Nextitem(strpart(line, 0, col), [''], 0) 126 let res = s:Nextitem(strpart(line, 0, col), [''], 0, 1)
127 if len(res) > 0 127 if len(res) > 0
128 " There are members, thus add "." or "->". 128 " There are members, thus add "." or "->".
129 if match(line, '\*[ \t(]*' . match . '\>') > 0 129 if match(line, '\*[ \t(]*' . match . '\>') > 0
130 let match .= '->' 130 let match .= '->'
131 else 131 else
134 endif 134 endif
135 endif 135 endif
136 let res = [{'match': match, 'tagline' : ''}] 136 let res = [{'match': match, 'tagline' : ''}]
137 else 137 else
138 " Completing "var.", "var.something", etc. 138 " Completing "var.", "var.something", etc.
139 let res = s:Nextitem(strpart(line, 0, col), items[1:], 0) 139 let res = s:Nextitem(strpart(line, 0, col), items[1:], 0, 1)
140 endif 140 endif
141 endif 141 endif
142 142
143 if len(items) == 1 143 if len(items) == 1
144 " Only one part, no "." or "->": complete from tags file. 144 " Only one part, no "." or "->": complete from tags file.
151 151
152 let res = [] 152 let res = []
153 for i in range(len(diclist)) 153 for i in range(len(diclist))
154 " New ctags has the "typename" field. 154 " New ctags has the "typename" field.
155 if has_key(diclist[i], 'typename') 155 if has_key(diclist[i], 'typename')
156 call extend(res, s:StructMembers(diclist[i]['typename'], items[1:])) 156 call extend(res, s:StructMembers(diclist[i]['typename'], items[1:], 1))
157 endif 157 endif
158 158
159 " For a variable use the command, which must be a search pattern that 159 " For a variable use the command, which must be a search pattern that
160 " shows the declaration of the variable. 160 " shows the declaration of the variable.
161 if diclist[i]['kind'] == 'v' 161 if diclist[i]['kind'] == 'v'
162 let line = diclist[i]['cmd'] 162 let line = diclist[i]['cmd']
163 if line[0] == '/' && line[1] == '^' 163 if line[0] == '/' && line[1] == '^'
164 let col = match(line, '\<' . items[0] . '\>') 164 let col = match(line, '\<' . items[0] . '\>')
165 call extend(res, s:Nextitem(strpart(line, 2, col - 2), items[1:], 0)) 165 call extend(res, s:Nextitem(strpart(line, 2, col - 2), items[1:], 0, 1))
166 endif 166 endif
167 endif 167 endif
168 endfor 168 endfor
169 endif 169 endif
170 170
171 if len(res) == 0 && searchdecl(items[0], 1) == 0 171 if len(res) == 0 && searchdecl(items[0], 1) == 0
172 " Found, now figure out the type. 172 " Found, now figure out the type.
173 " TODO: join previous line if it makes sense 173 " TODO: join previous line if it makes sense
174 let line = getline('.') 174 let line = getline('.')
175 let col = col('.') 175 let col = col('.')
176 let res = s:Nextitem(strpart(line, 0, col), items[1:], 0) 176 let res = s:Nextitem(strpart(line, 0, col), items[1:], 0, 1)
177 endif 177 endif
178 178
179 " If the last item(s) are [...] they need to be added to the matches. 179 " If the last item(s) are [...] they need to be added to the matches.
180 let last = len(items) - 1 180 let last = len(items) - 1
181 let brackets = '' 181 let brackets = ''
195 if a:bracket && match(a:line, a:match . '\s*\[') > 0 195 if a:bracket && match(a:line, a:match . '\s*\[') > 0
196 return '[' 196 return '['
197 endif 197 endif
198 198
199 " Check if the item has members. 199 " Check if the item has members.
200 if len(s:SearchMembers(a:memarg, [''])) > 0 200 if len(s:SearchMembers(a:memarg, [''], 0)) > 0
201 " If there is a '*' before the name use "->". 201 " If there is a '*' before the name use "->".
202 if match(a:line, '\*[ \t(]*' . a:match . '\>') > 0 202 if match(a:line, '\*[ \t(]*' . a:match . '\>') > 0
203 return '->' 203 return '->'
204 else 204 else
205 return '.' 205 return '.'
246 246
247 " Turn a command from a tag line to something that is useful in the menu 247 " Turn a command from a tag line to something that is useful in the menu
248 function! s:Tagcmd2extra(cmd, name, fname) 248 function! s:Tagcmd2extra(cmd, name, fname)
249 if a:cmd =~ '^/^' 249 if a:cmd =~ '^/^'
250 " The command is a search command, useful to see what it is. 250 " The command is a search command, useful to see what it is.
251 let x = matchstr(a:cmd, '^/^\zs.*\ze$/') 251 let x = matchstr(a:cmd, '^/^\s*\zs.*\ze$/')
252 let x = substitute(x, a:name, '@@', '') 252 let x = substitute(x, '\<' . a:name . '\>', '@@', '')
253 let x = substitute(x, '\\\(.\)', '\1', 'g') 253 let x = substitute(x, '\\\(.\)', '\1', 'g')
254 let x = x . ' - ' . a:fname 254 let x = x . ' - ' . a:fname
255 elseif a:cmd =~ '^\d*$' 255 elseif a:cmd =~ '^\d*$'
256 " The command is a line number, the file name is more useful. 256 " The command is a line number, the file name is more useful.
257 let x = a:fname . ' - ' . a:cmd 257 let x = a:fname . ' - ' . a:cmd
264 264
265 " Find composing type in "lead" and match items[0] with it. 265 " Find composing type in "lead" and match items[0] with it.
266 " Repeat this recursively for items[1], if it's there. 266 " Repeat this recursively for items[1], if it's there.
267 " When resolving typedefs "depth" is used to avoid infinite recursion. 267 " When resolving typedefs "depth" is used to avoid infinite recursion.
268 " Return the list of matches. 268 " Return the list of matches.
269 function! s:Nextitem(lead, items, depth) 269 function! s:Nextitem(lead, items, depth, all)
270 270
271 " Use the text up to the variable name and split it in tokens. 271 " Use the text up to the variable name and split it in tokens.
272 let tokens = split(a:lead, '\s\+\|\<') 272 let tokens = split(a:lead, '\s\+\|\<')
273 273
274 " Try to recognize the type of the variable. This is rough guessing... 274 " Try to recognize the type of the variable. This is rough guessing...
275 let res = [] 275 let res = []
276 for tidx in range(len(tokens)) 276 for tidx in range(len(tokens))
277 277
278 " Recognize "struct foobar" and "union foobar". 278 " Recognize "struct foobar" and "union foobar".
279 if (tokens[tidx] == 'struct' || tokens[tidx] == 'union') && tidx + 1 < len(tokens) 279 if (tokens[tidx] == 'struct' || tokens[tidx] == 'union') && tidx + 1 < len(tokens)
280 let res = s:StructMembers(tokens[tidx] . ':' . tokens[tidx + 1], a:items) 280 let res = s:StructMembers(tokens[tidx] . ':' . tokens[tidx + 1], a:items, a:all)
281 break 281 break
282 endif 282 endif
283 283
284 " TODO: add more reserved words 284 " TODO: add more reserved words
285 if index(['int', 'short', 'char', 'float', 'double', 'static', 'unsigned', 'extern'], tokens[tidx]) >= 0 285 if index(['int', 'short', 'char', 'float', 'double', 'static', 'unsigned', 'extern'], tokens[tidx]) >= 0
289 " Use the tags file to find out if this is a typedef. 289 " Use the tags file to find out if this is a typedef.
290 let diclist = taglist('^' . tokens[tidx] . '$') 290 let diclist = taglist('^' . tokens[tidx] . '$')
291 for tagidx in range(len(diclist)) 291 for tagidx in range(len(diclist))
292 " New ctags has the "typename" field. 292 " New ctags has the "typename" field.
293 if has_key(diclist[tagidx], 'typename') 293 if has_key(diclist[tagidx], 'typename')
294 call extend(res, s:StructMembers(diclist[tagidx]['typename'], a:items)) 294 call extend(res, s:StructMembers(diclist[tagidx]['typename'], a:items, a:all))
295 continue 295 continue
296 endif 296 endif
297 297
298 " Only handle typedefs here. 298 " Only handle typedefs here.
299 if diclist[tagidx]['kind'] != 't' 299 if diclist[tagidx]['kind'] != 't'
315 let name = cmdtokens[ti] 315 let name = cmdtokens[ti]
316 break 316 break
317 endif 317 endif
318 endfor 318 endfor
319 if name != '' 319 if name != ''
320 call extend(res, s:StructMembers(cmdtokens[0] . ':' . name, a:items)) 320 call extend(res, s:StructMembers(cmdtokens[0] . ':' . name, a:items, a:all))
321 endif 321 endif
322 elseif a:depth < 10 322 elseif a:depth < 10
323 " Could be "typedef other_T some_T". 323 " Could be "typedef other_T some_T".
324 call extend(res, s:Nextitem(cmdtokens[0], a:items, a:depth + 1)) 324 call extend(res, s:Nextitem(cmdtokens[0], a:items, a:depth + 1, a:all))
325 endif 325 endif
326 endif 326 endif
327 endif 327 endif
328 endfor 328 endfor
329 if len(res) > 0 329 if len(res) > 0
336 336
337 337
338 " Search for members of structure "typename" in tags files. 338 " Search for members of structure "typename" in tags files.
339 " Return a list with resulting matches. 339 " Return a list with resulting matches.
340 " Each match is a dictionary with "match" and "tagline" entries. 340 " Each match is a dictionary with "match" and "tagline" entries.
341 function! s:StructMembers(typename, items) 341 " When "all" is non-zero find all, otherwise just return 1 if there is any
342 " member.
343 function! s:StructMembers(typename, items, all)
342 " Todo: What about local structures? 344 " Todo: What about local structures?
343 let fnames = join(map(tagfiles(), 'escape(v:val, " \\")')) 345 let fnames = join(map(tagfiles(), 'escape(v:val, " \\")'))
344 if fnames == '' 346 if fnames == ''
345 return [] 347 return []
346 endif 348 endif
347 349
348 let typename = a:typename 350 let typename = a:typename
349 let qflist = [] 351 let qflist = []
352 if a:all == 0
353 let n = '1' " stop at first found match
354 else
355 let n = ''
356 endif
350 while 1 357 while 1
351 exe 'silent! vimgrep /\t' . typename . '\(\t\|$\)/j ' . fnames 358 exe 'silent! ' . n . 'vimgrep /\t' . typename . '\(\t\|$\)/j ' . fnames
352 let qflist = getqflist() 359 let qflist = getqflist()
353 if len(qflist) > 0 || match(typename, "::") < 0 360 if len(qflist) > 0 || match(typename, "::") < 0
354 break 361 break
355 endif 362 endif
356 " No match for "struct:context::name", remove "context::" and try again. 363 " No match for "struct:context::name", remove "context::" and try again.
378 let idx += 1 385 let idx += 1
379 endwhile 386 endwhile
380 387
381 " More items following. For each of the possible members find the 388 " More items following. For each of the possible members find the
382 " matching following members. 389 " matching following members.
383 return s:SearchMembers(matches, a:items[idx :]) 390 return s:SearchMembers(matches, a:items[idx :], a:all)
384 endif 391 endif
385 392
386 " Failed to find anything. 393 " Failed to find anything.
387 return [] 394 return []
388 endfunction 395 endfunction
389 396
390 " For matching members, find matches for following items. 397 " For matching members, find matches for following items.
391 function! s:SearchMembers(matches, items) 398 " When "all" is non-zero find all, otherwise just return 1 if there is any
399 " member.
400 function! s:SearchMembers(matches, items, all)
392 let res = [] 401 let res = []
393 for i in range(len(a:matches)) 402 for i in range(len(a:matches))
394 let typename = '' 403 let typename = ''
395 if has_key(a:matches[i], 'dict') 404 if has_key(a:matches[i], 'dict')
396 if has_key(a:matches[i].dict, 'typename') 405 if has_key(a:matches[i].dict, 'typename')
403 if e > 0 412 if e > 0
404 " Use typename field 413 " Use typename field
405 let typename = matchstr(line, '[^\t]*', e) 414 let typename = matchstr(line, '[^\t]*', e)
406 endif 415 endif
407 endif 416 endif
417
408 if typename != '' 418 if typename != ''
409 call extend(res, s:StructMembers(typename, a:items)) 419 call extend(res, s:StructMembers(typename, a:items, a:all))
410 else 420 else
411 " Use the search command (the declaration itself). 421 " Use the search command (the declaration itself).
412 let s = match(line, '\t\zs/^') 422 let s = match(line, '\t\zs/^')
413 if s > 0 423 if s > 0
414 let e = match(line, '\<' . a:matches[i]['match'] . '\>', s) 424 let e = match(line, '\<' . a:matches[i]['match'] . '\>', s)
415 if e > 0 425 if e > 0
416 call extend(res, s:Nextitem(strpart(line, s, e - s), a:items, 0)) 426 call extend(res, s:Nextitem(strpart(line, s, e - s), a:items, 0, a:all))
417 endif 427 endif
418 endif 428 endif
429 endif
430 if a:all == 0 && len(res) > 0
431 break
419 endif 432 endif
420 endfor 433 endfor
421 return res 434 return res
422 endfunc 435 endfunc