Mercurial > vim
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 |