Skip to content

Commit f75a963

Browse files
committed
updated for version 7.0146
1 parent 5e0d667 commit f75a963

31 files changed

Lines changed: 628 additions & 167 deletions

runtime/autoload/ccomplete.vim

Lines changed: 86 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
" Vim completion script
22
" Language: C
33
" Maintainer: Bram Moolenaar <Bram@vim.org>
4-
" Last Change: 2005 Sep 10
4+
" Last Change: 2005 Sep 13
55

66

7-
" This function is used for the 'occultfunc' option.
7+
" This function is used for the 'omnifunc' option.
88
function! ccomplete#Complete(findstart, base)
99
if a:findstart
1010
" Locate the start of the item, including "." and "->".
@@ -38,12 +38,12 @@ function! ccomplete#Complete(findstart, base)
3838
" 2. in tags file(s) (like with ":tag")
3939
" 3. in current file (like with "gD")
4040
let res = []
41-
if searchdecl(items[0]) == 0
41+
if searchdecl(items[0], 0, 1) == 0
4242
" Found, now figure out the type.
4343
" TODO: join previous line if it makes sense
4444
let line = getline('.')
4545
let col = col('.')
46-
let res = ccomplete#Nextitem(strpart(line, 0, col), items[1:])
46+
let res = s:Nextitem(strpart(line, 0, col), items[1:])
4747
endif
4848

4949
if len(res) == 0
@@ -54,7 +54,7 @@ function! ccomplete#Complete(findstart, base)
5454
for i in range(len(diclist))
5555
" New ctags has the "typename" field.
5656
if has_key(diclist[i], 'typename')
57-
call extend(res, ccomplete#StructMembers(diclist[i]['typename'], items[1:]))
57+
call extend(res, s:StructMembers(diclist[i]['typename'], items[1:]))
5858
endif
5959

6060
" For a variable use the command, which must be a search pattern that
@@ -63,7 +63,7 @@ function! ccomplete#Complete(findstart, base)
6363
let line = diclist[i]['cmd']
6464
if line[0] == '/' && line[1] == '^'
6565
let col = match(line, items[0])
66-
call extend(res, ccomplete#Nextitem(strpart(line, 2, col - 2), items[1:])
66+
call extend(res, s:Nextitem(strpart(line, 2, col - 2), items[1:]))
6767
endif
6868
endif
6969
endfor
@@ -74,19 +74,30 @@ function! ccomplete#Complete(findstart, base)
7474
" TODO: join previous line if it makes sense
7575
let line = getline('.')
7676
let col = col('.')
77-
let res = ccomplete#Nextitem(strpart(line, 0, col), items[1:])
77+
let res = s:Nextitem(strpart(line, 0, col), items[1:])
78+
endif
79+
80+
" If the one and only match was what's already there and it is a composite
81+
" type, add a "." or "->".
82+
if len(res) == 1 && res[0]['match'] == items[-1] && len(s:SearchMembers(res, [''])) > 0
83+
" If there is a '*' before the name use "->".
84+
if match(res[0]['tagline'], '\*\s*' . res[0]['match']) > 0
85+
let res[0]['match'] .= '->'
86+
else
87+
let res[0]['match'] .= '.'
88+
endif
7889
endif
7990

8091
" The basetext is up to the last "." or "->" and won't be changed. The
8192
" matching members are concatenated to this.
8293
let basetext = matchstr(a:base, '.*\(\.\|->\)')
83-
return map(res, 'basetext . v:val')
94+
return map(res, 'basetext . v:val["match"]')
8495
endfunc
8596

8697
" Find composing type in "lead" and match items[0] with it.
8798
" Repeat this recursively for items[1], if it's there.
8899
" Return the list of matches.
89-
function! ccomplete#Nextitem(lead, items)
100+
function! s:Nextitem(lead, items)
90101

91102
" Use the text up to the variable name and split it in tokens.
92103
let tokens = split(a:lead, '\s\+\|\<')
@@ -97,7 +108,7 @@ function! ccomplete#Nextitem(lead, items)
97108

98109
" Recognize "struct foobar" and "union foobar".
99110
if (tokens[tidx] == 'struct' || tokens[tidx] == 'union') && tidx + 1 < len(tokens)
100-
let res = ccomplete#StructMembers(tokens[tidx] . ':' . tokens[tidx + 1], a:items)
111+
let res = s:StructMembers(tokens[tidx] . ':' . tokens[tidx + 1], a:items)
101112
break
102113
endif
103114

@@ -108,20 +119,42 @@ function! ccomplete#Nextitem(lead, items)
108119

109120
" Use the tags file to find out if this is a typedef.
110121
let diclist = taglist('^' . tokens[tidx] . '$')
111-
for i in range(len(diclist))
122+
for tagidx in range(len(diclist))
112123
" New ctags has the "typename" field.
113-
if has_key(diclist[i], 'typename')
114-
call extend(res, ccomplete#StructMembers(diclist[i]['typename'], a:items))
124+
if has_key(diclist[tagidx], 'typename')
125+
call extend(res, s:StructMembers(diclist[tagidx]['typename'], a:items))
126+
continue
127+
endif
128+
129+
" Only handle typedefs here.
130+
if diclist[tagidx]['kind'] != 't'
115131
continue
116132
endif
117133

118-
" For old ctags we only recognize "typedef struct foobar" in the tags
119-
" file command.
120-
let cmd = diclist[i]['cmd']
121-
let ci = matchend(cmd, 'typedef\s\+struct\s\+')
122-
if ci > 1
123-
let name = matchstr(cmd, '\w*', ci)
124-
call extend(res, ccomplete#StructMembers('struct:' . name, a:items))
134+
" For old ctags we recognize "typedef struct aaa" and
135+
" "typedef union bbb" in the tags file command.
136+
let cmd = diclist[tagidx]['cmd']
137+
let ei = matchend(cmd, 'typedef\s\+')
138+
if ei > 1
139+
let cmdtokens = split(strpart(cmd, ei), '\s\+\|\<')
140+
if len(cmdtokens) > 1
141+
if cmdtokens[0] == 'struct' || cmdtokens[0] == 'union'
142+
let name = ''
143+
" Use the first identifier after the "struct" or "union"
144+
for ti in range(len(cmdtokens) - 1)
145+
if cmdtokens[ti] =~ '^\w'
146+
let name = cmdtokens[ti]
147+
break
148+
endif
149+
endfor
150+
if name != ''
151+
call extend(res, s:StructMembers(cmdtokens[0] . ':' . name, a:items))
152+
endif
153+
else
154+
" Could be "typedef other_T some_T".
155+
call extend(res, s:Nextitem(cmdtokens[0], a:items))
156+
endif
157+
endif
125158
endif
126159
endfor
127160
if len(res) > 0
@@ -133,12 +166,13 @@ function! ccomplete#Nextitem(lead, items)
133166
endfunction
134167

135168

136-
" Return a list with resulting matches
137-
function! ccomplete#StructMembers(typename, items)
169+
" Return a list with resulting matches.
170+
" Each match is a dictionary with "match" and "tagline" entries.
171+
function! s:StructMembers(typename, items)
138172
" Todo: What about local structures?
139173
let fnames = join(map(tagfiles(), 'escape(v:val, " \\")'))
140174
if fnames == ''
141-
return [[], []]
175+
return []
142176
endif
143177

144178
let typename = a:typename
@@ -153,45 +187,49 @@ function! ccomplete#StructMembers(typename, items)
153187
let typename = substitute(typename, ':[^:]*::', ':', '')
154188
endwhile
155189

156-
let members = []
157-
let taglines = []
190+
let matches = []
158191
for l in qflist
159192
let memb = matchstr(l['text'], '[^\t]*')
160193
if memb =~ '^' . a:items[0]
161-
call add(members, memb)
162-
call add(taglines, l['text'])
194+
call add(matches, {'match': memb, 'tagline': l['text']})
163195
endif
164196
endfor
165197

166-
if len(members) > 0
198+
if len(matches) > 0
167199
" No further items, return the result.
168200
if len(a:items) == 1
169-
return members
201+
return matches
170202
endif
171203

172204
" More items following. For each of the possible members find the
173205
" matching following members.
174-
let res = []
175-
for i in range(len(members))
176-
let line = taglines[i]
177-
let e = matchend(line, '\ttypename:')
178-
if e > 0
179-
" Use typename field
180-
let name = matchstr(line, '[^\t]*', e)
181-
call extend(res, ccomplete#StructMembers(name, a:items[1:]))
182-
else
183-
let s = match(line, '\t\zs/^')
184-
if s > 0
185-
let e = match(line, members[i], s)
186-
if e > 0
187-
call extend(res, ccomplete#Nextitem(strpart(line, s, e - s), a:items[1:]))
188-
endif
189-
endif
190-
endif
191-
endfor
192-
return res
206+
return s:SearchMembers(matches, a:items[1:])
193207
endif
194208

195209
" Failed to find anything.
196210
return []
197211
endfunction
212+
213+
" For matching members, find matches for following items.
214+
function! s:SearchMembers(matches, items)
215+
let res = []
216+
for i in range(len(a:matches))
217+
let line = a:matches[i]['tagline']
218+
let e = matchend(line, '\ttypename:')
219+
if e > 0
220+
" Use typename field
221+
let name = matchstr(line, '[^\t]*', e)
222+
call extend(res, s:StructMembers(name, a:items))
223+
else
224+
" Use the search command (the declaration itself).
225+
let s = match(line, '\t\zs/^')
226+
if s > 0
227+
let e = match(line, a:matches[i]['match'], s)
228+
if e > 0
229+
call extend(res, s:Nextitem(strpart(line, s, e - s), a:items))
230+
endif
231+
endif
232+
endif
233+
endfor
234+
return res
235+
endfunc

0 commit comments

Comments
 (0)