2014-10-31 17:30:24 -04:00
|
|
|
" Copyright 2011 The Go Authors. All rights reserved.
|
|
|
|
" Use of this source code is governed by a BSD-style
|
|
|
|
" license that can be found in the LICENSE file.
|
|
|
|
"
|
|
|
|
" This file provides a utility function that performs auto-completion of
|
|
|
|
" package names, for use by other commands.
|
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
" don't spam the user when Vim is started in Vi compatibility mode
|
|
|
|
let s:cpo_save = &cpo
|
|
|
|
set cpo&vim
|
|
|
|
|
2014-10-31 17:30:24 -04:00
|
|
|
let s:goos = $GOOS
|
|
|
|
let s:goarch = $GOARCH
|
|
|
|
|
|
|
|
if len(s:goos) == 0
|
2016-06-26 07:12:36 -04:00
|
|
|
if exists('g:golang_goos')
|
|
|
|
let s:goos = g:golang_goos
|
|
|
|
elseif has('win32') || has('win64')
|
|
|
|
let s:goos = 'windows'
|
|
|
|
elseif has('macunix')
|
|
|
|
let s:goos = 'darwin'
|
|
|
|
else
|
|
|
|
let s:goos = '*'
|
|
|
|
endif
|
2014-10-31 17:30:24 -04:00
|
|
|
endif
|
|
|
|
|
|
|
|
if len(s:goarch) == 0
|
2016-06-26 07:12:36 -04:00
|
|
|
if exists('g:golang_goarch')
|
|
|
|
let s:goarch = g:golang_goarch
|
|
|
|
else
|
|
|
|
let s:goarch = '*'
|
|
|
|
endif
|
2014-10-31 17:30:24 -04:00
|
|
|
endif
|
|
|
|
|
2016-12-27 09:46:49 -05:00
|
|
|
function! go#package#Paths() abort
|
2016-06-26 07:12:36 -04:00
|
|
|
let dirs = []
|
|
|
|
|
|
|
|
if !exists("s:goroot")
|
|
|
|
if executable('go')
|
2017-07-06 08:57:35 -04:00
|
|
|
let s:goroot = go#util#env("goroot")
|
2016-06-26 07:12:36 -04:00
|
|
|
if go#util#ShellError() != 0
|
|
|
|
echomsg '''go env GOROOT'' failed'
|
|
|
|
endif
|
|
|
|
else
|
|
|
|
let s:goroot = $GOROOT
|
2014-10-31 17:30:24 -04:00
|
|
|
endif
|
2016-06-26 07:12:36 -04:00
|
|
|
endif
|
2014-10-31 17:30:24 -04:00
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
if len(s:goroot) != 0 && isdirectory(s:goroot)
|
|
|
|
let dirs += [s:goroot]
|
|
|
|
endif
|
2014-10-31 17:30:24 -04:00
|
|
|
|
2017-12-13 09:05:24 -05:00
|
|
|
let workspaces = split(go#path#Default(), go#util#PathListSep())
|
2016-06-26 07:12:36 -04:00
|
|
|
if workspaces != []
|
|
|
|
let dirs += workspaces
|
|
|
|
endif
|
2014-10-31 17:30:24 -04:00
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
return dirs
|
2014-10-31 17:30:24 -04:00
|
|
|
endfunction
|
|
|
|
|
2018-03-31 10:56:26 -04:00
|
|
|
let s:import_paths = {}
|
2018-12-17 06:28:27 -05:00
|
|
|
" ImportPath returns the import path of the package for current buffer.
|
2017-07-06 08:57:35 -04:00
|
|
|
function! go#package#ImportPath() abort
|
2018-03-31 10:56:26 -04:00
|
|
|
let dir = expand("%:p:h")
|
|
|
|
if has_key(s:import_paths, dir)
|
|
|
|
return s:import_paths[dir]
|
|
|
|
endif
|
|
|
|
|
2019-03-08 06:04:56 -05:00
|
|
|
let [l:out, l:err] = go#util#ExecInDir(['go', 'list'])
|
2018-06-14 06:31:12 -04:00
|
|
|
if l:err != 0
|
2017-07-06 08:57:35 -04:00
|
|
|
return -1
|
|
|
|
endif
|
2014-10-31 17:30:24 -04:00
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
let l:importpath = split(out, '\n')[0]
|
2016-06-26 07:12:36 -04:00
|
|
|
|
2017-07-06 08:57:35 -04:00
|
|
|
" go list returns '_CURRENTDIRECTORY' if the directory is not inside GOPATH.
|
|
|
|
" Check it and retun an error if that is the case
|
2018-12-17 06:28:27 -05:00
|
|
|
if l:importpath[0] ==# '_'
|
2016-06-26 07:12:36 -04:00
|
|
|
return -1
|
|
|
|
endif
|
2014-10-31 17:30:24 -04:00
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
let s:import_paths[dir] = l:importpath
|
2018-03-31 10:56:26 -04:00
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
return l:importpath
|
2014-10-31 17:30:24 -04:00
|
|
|
endfunction
|
|
|
|
|
2017-07-06 08:57:35 -04:00
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
" FromPath returns the import path of arg.
|
2016-12-27 09:46:49 -05:00
|
|
|
function! go#package#FromPath(arg) abort
|
2018-12-17 06:28:27 -05:00
|
|
|
let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
|
|
|
|
let l:dir = getcwd()
|
2014-10-31 17:30:24 -04:00
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
let l:path = a:arg
|
|
|
|
if !isdirectory(l:path)
|
|
|
|
let l:path = fnamemodify(l:path, ':h')
|
|
|
|
endif
|
2016-06-26 07:12:36 -04:00
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
execute l:cd fnameescape(l:path)
|
|
|
|
let [l:out, l:err] = go#util#Exec(['go', 'list'])
|
|
|
|
execute l:cd fnameescape(l:dir)
|
|
|
|
if l:err != 0
|
2016-06-26 07:12:36 -04:00
|
|
|
return -1
|
|
|
|
endif
|
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
let l:importpath = split(l:out, '\n')[0]
|
|
|
|
|
|
|
|
" go list returns '_CURRENTDIRECTORY' if the directory is not inside GOPATH.
|
|
|
|
" Check it and retun an error if that is the case
|
|
|
|
if l:importpath[0] ==# '_'
|
|
|
|
return -1
|
2016-06-26 07:12:36 -04:00
|
|
|
endif
|
2018-12-17 06:28:27 -05:00
|
|
|
|
|
|
|
return l:importpath
|
2014-10-31 17:30:24 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-12-27 09:46:49 -05:00
|
|
|
function! go#package#CompleteMembers(package, member) abort
|
2018-12-17 06:28:27 -05:00
|
|
|
let [l:content, l:err] = go#util#Exec(['go', 'doc', a:package])
|
2018-06-14 06:31:12 -04:00
|
|
|
if l:err || !len(content)
|
2016-06-26 07:12:36 -04:00
|
|
|
return []
|
|
|
|
endif
|
2018-06-14 06:31:12 -04:00
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
let lines = filter(split(content, "\n"),"v:val !~ '^\\s\\+$'")
|
|
|
|
try
|
|
|
|
let mx1 = '^\s\+\(\S+\)\s\+=\s\+.*'
|
|
|
|
let mx2 = '^\%(const\|var\|type\|func\) \([A-Z][^ (]\+\).*'
|
|
|
|
let candidates = map(filter(copy(lines), 'v:val =~ mx1'),
|
|
|
|
\ 'substitute(v:val, mx1, "\\1", "")')
|
|
|
|
\ + map(filter(copy(lines), 'v:val =~ mx2'),
|
|
|
|
\ 'substitute(v:val, mx2, "\\1", "")')
|
|
|
|
return filter(candidates, '!stridx(v:val, a:member)')
|
|
|
|
catch
|
|
|
|
return []
|
|
|
|
endtry
|
2014-10-31 17:30:24 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-12-27 09:46:49 -05:00
|
|
|
function! go#package#Complete(ArgLead, CmdLine, CursorPos) abort
|
2016-06-26 07:12:36 -04:00
|
|
|
let words = split(a:CmdLine, '\s\+', 1)
|
2015-07-13 06:22:46 -04:00
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
" do not complete package members for these commands
|
|
|
|
let neglect_commands = ["GoImportAs", "GoGuruScope"]
|
2015-07-13 06:22:46 -04:00
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
if len(words) > 2 && index(neglect_commands, words[0]) == -1
|
|
|
|
" Complete package members
|
|
|
|
return go#package#CompleteMembers(words[1], words[2])
|
|
|
|
endif
|
2014-10-31 17:30:24 -04:00
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
let dirs = go#package#Paths()
|
2014-10-31 17:30:24 -04:00
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
if len(dirs) == 0
|
|
|
|
" should not happen
|
|
|
|
return []
|
|
|
|
endif
|
2014-10-31 17:30:24 -04:00
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
let ret = {}
|
|
|
|
for dir in dirs
|
|
|
|
" this may expand to multiple lines
|
|
|
|
let root = split(expand(dir . '/pkg/' . s:goos . '_' . s:goarch), "\n")
|
|
|
|
call add(root, expand(dir . '/src'))
|
|
|
|
for r in root
|
|
|
|
for i in split(globpath(r, a:ArgLead.'*'), "\n")
|
|
|
|
if isdirectory(i)
|
|
|
|
let i .= '/'
|
|
|
|
elseif i !~ '\.a$'
|
|
|
|
continue
|
|
|
|
endif
|
|
|
|
let i = substitute(substitute(i[len(r)+1:], '[\\]', '/', 'g'),
|
|
|
|
\ '\.a$', '', 'g')
|
|
|
|
|
|
|
|
" without this the result can have duplicates in form of
|
|
|
|
" 'encoding/json' and '/encoding/json/'
|
|
|
|
let i = go#util#StripPathSep(i)
|
|
|
|
|
|
|
|
let ret[i] = i
|
|
|
|
endfor
|
2014-10-31 17:30:24 -04:00
|
|
|
endfor
|
2018-12-17 06:28:27 -05:00
|
|
|
endfor
|
|
|
|
return sort(keys(ret))
|
2014-10-31 17:30:24 -04:00
|
|
|
endfunction
|
|
|
|
|
2018-12-17 06:28:27 -05:00
|
|
|
" restore Vi compatibility settings
|
|
|
|
let &cpo = s:cpo_save
|
|
|
|
unlet s:cpo_save
|
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
" vim: sw=2 ts=2 et
|