@@ -32,7 +32,7 @@ if len(s:goarch) == 0
32
32
endif
33
33
endif
34
34
35
- function ! go#package#Paths () abort
35
+ function ! s: paths () abort
36
36
let dirs = []
37
37
38
38
if ! exists (" s:goroot" )
@@ -58,6 +58,64 @@ function! go#package#Paths() abort
58
58
return dirs
59
59
endfunction
60
60
61
+ function ! s: module () abort
62
+ let [l: out , l: err ] = go#util#ExecInDir ([' go' , ' list' , ' -m' , ' -f' , ' {{.Dir}}' ])
63
+ if l: err != 0
64
+ return {}
65
+ endif
66
+ let l: dir = split (l: out , ' \n' )[0 ]
67
+
68
+ let [l: out , l: err ] = go#util#ExecInDir ([' go' , ' list' , ' -m' , ' -f' , ' {{.Path}}' ])
69
+ if l: err != 0
70
+ return {}
71
+ endif
72
+ let l: path = split (l: out , ' \n' )[0 ]
73
+
74
+ return {' dir' : l: dir , ' path' : l: path }
75
+ endfunction
76
+
77
+ function ! s: vendordirs () abort
78
+ let l: vendorsuffix = go#util#PathSep () . ' vendor'
79
+ let l: module = s: module ()
80
+ if empty (l: module )
81
+ let [l: root , l: err ] = go#util#ExecInDir ([' go' , ' list' , ' -f' , ' {{.Root}}' ])
82
+ if l: err != 0
83
+ return []
84
+ endif
85
+ let l: root = split (l: root , ' \n' )[0 ] . go#util#PathSep () . ' src'
86
+
87
+ let [l: dir , l: err ] = go#util#ExecInDir ([' go' , ' list' , ' -f' , ' {{.Dir}}' ])
88
+ if l: err != 0
89
+ return []
90
+ endif
91
+ let l: dir = split (l: dir , ' \n' )[0 ]
92
+
93
+ let l: vendordirs = []
94
+ let l: i = 0
95
+ while l: dir != l: root
96
+ let l: i += 1
97
+
98
+ if l: i == 4
99
+ return []
100
+ endif
101
+ let l: vendordir = l: dir . l: vendorsuffix
102
+ if isdirectory (l: vendordir )
103
+ let l: vendordirs = add (l: vendordirs , l: vendordir )
104
+ endif
105
+
106
+ let l: dir = fnamemodify (l: dir , ' :h' )
107
+ endwhile
108
+
109
+ return l: vendordirs
110
+ endif
111
+
112
+ let l: vendordir = l: module .dir . l: vendorsuffix
113
+ if ! isdirectory (l: vendordir )
114
+ return []
115
+ endif
116
+ return [l: vendordir ]
117
+ endfunction
118
+
61
119
let s: import_paths = {}
62
120
" ImportPath returns the import path of the package for current buffer.
63
121
function ! go#package#ImportPath () abort
@@ -144,33 +202,71 @@ function! go#package#Complete(ArgLead, CmdLine, CursorPos) abort
144
202
return go#package#CompleteMembers (words[1 ], words[2 ])
145
203
endif
146
204
147
- let dirs = go#package#Paths ()
205
+ let dirs = s: paths ()
206
+ let module = s: module ()
148
207
149
- if len (dirs) == 0
208
+ if len (dirs) == 0 && empty (module)
150
209
" should not happen
151
210
return []
152
211
endif
153
212
213
+ let vendordirs = s: vendordirs ()
214
+
154
215
let ret = {}
155
216
for dir in dirs
156
217
" this may expand to multiple lines
157
218
let root = split (expand (dir . ' /pkg/' . s: goos . ' _' . s: goarch ), " \n " )
158
- call add (root, expand (dir . ' /src' ))
159
- for r in root
160
- for i in split (globpath (r , a: ArgLead .' *' ), " \n " )
161
- if isdirectory (i )
162
- let i .= ' /'
163
- elseif i !~ ' \.a$'
219
+ let root = add (root, expand (dir . ' /src' ), )
220
+ let root = extend (root, vendordirs)
221
+ let root = add (root, module)
222
+ for item in root
223
+ " item may be a dictionary when operating in a module.
224
+ if type (item) == type ({})
225
+ if empty (item)
226
+ continue
227
+ endif
228
+ let dir = item.dir
229
+ let path = item.path
230
+ else
231
+ let dir = item
232
+ let path = item
233
+ endif
234
+
235
+ if ! empty (module) && dir == module.dir
236
+ if stridx (a: ArgLead , module.path ) == 0 && len (a: ArgLead ) != len (module.path )
237
+ let glob = globpath (module.dir , substitute (a: ArgLead , module.path , ' ' , ' ' ).' *' )
238
+ elseif stridx (module.path , a: ArgLead ) == 0 && stridx (module.path , ' /' , len (a: ArgLead )) < 0
239
+ " use the module directory when a:ArgLead is contained in
240
+ " module.path and module.path does not have any path segments after
241
+ " a:ArgLead.
242
+ let glob = module.dir
243
+ else
244
+ continue
245
+ endif
246
+ else
247
+ let glob = globpath (dir , a: ArgLead .' *' )
248
+ endif
249
+ for candidate in split (glob )
250
+ if isdirectory (candidate)
251
+ let candidate .= ' /'
252
+ elseif candidate !~ ' \.a$'
164
253
continue
165
254
endif
166
- let i = substitute (substitute (i [len (r )+ 1 :], ' [\\]' , ' /' , ' g' ),
255
+
256
+ if dir !=# path
257
+ let candidate = substitute (candidate, ' ^' . dir , path , ' g' )
258
+ else
259
+ let candidate = candidate[len (dir )+ 1 :]
260
+ endif
261
+ " replace a backslash with a forward slash and drop .a suffixes
262
+ let candidate = substitute (substitute (candidate, ' [\\]' , ' /' , ' g' ),
167
263
\ ' \.a$' , ' ' , ' g' )
168
264
169
265
" without this the result can have duplicates in form of
170
266
" 'encoding/json' and '/encoding/json/'
171
- let i = go#util#StripPathSep (i )
267
+ let candidate = go#util#StripPathSep (candidate )
172
268
173
- let ret [i ] = i
269
+ let ret [candidate ] = candidate
174
270
endfor
175
271
endfor
176
272
endfor
0 commit comments