package.vim 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. " Copyright 2011 The Go Authors. All rights reserved.
  2. " Use of this source code is governed by a BSD-style
  3. " license that can be found in the LICENSE file.
  4. "
  5. " This file provides a utility function that performs auto-completion of
  6. " package names, for use by other commands.
  7. let s:goos = $GOOS
  8. let s:goarch = $GOARCH
  9. if len(s:goos) == 0
  10. if exists('g:golang_goos')
  11. let s:goos = g:golang_goos
  12. elseif has('win32') || has('win64')
  13. let s:goos = 'windows'
  14. elseif has('macunix')
  15. let s:goos = 'darwin'
  16. else
  17. let s:goos = '*'
  18. endif
  19. endif
  20. if len(s:goarch) == 0
  21. if exists('g:golang_goarch')
  22. let s:goarch = g:golang_goarch
  23. else
  24. let s:goarch = '*'
  25. endif
  26. endif
  27. function! go#package#Paths() abort
  28. let dirs = []
  29. if !exists("s:goroot")
  30. if executable('go')
  31. let s:goroot = go#util#env("goroot")
  32. if go#util#ShellError() != 0
  33. echomsg '''go env GOROOT'' failed'
  34. endif
  35. else
  36. let s:goroot = $GOROOT
  37. endif
  38. endif
  39. if len(s:goroot) != 0 && isdirectory(s:goroot)
  40. let dirs += [s:goroot]
  41. endif
  42. let workspaces = split(go#path#Default(), go#util#PathListSep())
  43. if workspaces != []
  44. let dirs += workspaces
  45. endif
  46. return dirs
  47. endfunction
  48. " ImportPath returns the import path in the current directory it was executed
  49. function! go#package#ImportPath() abort
  50. let out = go#tool#ExecuteInDir("go list")
  51. if go#util#ShellError() != 0
  52. return -1
  53. endif
  54. let import_path = split(out, '\n')[0]
  55. " go list returns '_CURRENTDIRECTORY' if the directory is not inside GOPATH.
  56. " Check it and retun an error if that is the case
  57. if import_path[0] ==# '_'
  58. return -1
  59. endif
  60. return import_path
  61. endfunction
  62. function! go#package#FromPath(arg) abort
  63. let path = fnamemodify(resolve(a:arg), ':p')
  64. let dirs = go#package#Paths()
  65. for dir in dirs
  66. if len(dir) && match(path, dir) == 0
  67. let workspace = dir
  68. break
  69. endif
  70. endfor
  71. if !exists('workspace')
  72. return -1
  73. endif
  74. let path = substitute(path, '/*$', '', '')
  75. let workspace = substitute(workspace . '/src/', '/+', '', '')
  76. if isdirectory(path)
  77. return substitute(path, workspace, '', '')
  78. else
  79. return substitute(substitute(path, workspace, '', ''),
  80. \ '/' . fnamemodify(path, ':t'), '', '')
  81. endif
  82. endfunction
  83. function! go#package#CompleteMembers(package, member) abort
  84. silent! let content = go#util#System('godoc ' . a:package)
  85. if go#util#ShellError() || !len(content)
  86. return []
  87. endif
  88. let lines = filter(split(content, "\n"),"v:val !~ '^\\s\\+$'")
  89. try
  90. let mx1 = '^\s\+\(\S+\)\s\+=\s\+.*'
  91. let mx2 = '^\%(const\|var\|type\|func\) \([A-Z][^ (]\+\).*'
  92. let candidates = map(filter(copy(lines), 'v:val =~ mx1'),
  93. \ 'substitute(v:val, mx1, "\\1", "")')
  94. \ + map(filter(copy(lines), 'v:val =~ mx2'),
  95. \ 'substitute(v:val, mx2, "\\1", "")')
  96. return filter(candidates, '!stridx(v:val, a:member)')
  97. catch
  98. return []
  99. endtry
  100. endfunction
  101. function! go#package#Complete(ArgLead, CmdLine, CursorPos) abort
  102. let words = split(a:CmdLine, '\s\+', 1)
  103. " do not complete package members for these commands
  104. let neglect_commands = ["GoImportAs", "GoGuruScope"]
  105. if len(words) > 2 && index(neglect_commands, words[0]) == -1
  106. " Complete package members
  107. return go#package#CompleteMembers(words[1], words[2])
  108. endif
  109. let dirs = go#package#Paths()
  110. if len(dirs) == 0
  111. " should not happen
  112. return []
  113. endif
  114. let ret = {}
  115. for dir in dirs
  116. " this may expand to multiple lines
  117. let root = split(expand(dir . '/pkg/' . s:goos . '_' . s:goarch), "\n")
  118. call add(root, expand(dir . '/src'))
  119. for r in root
  120. for i in split(globpath(r, a:ArgLead.'*'), "\n")
  121. if isdirectory(i)
  122. let i .= '/'
  123. elseif i !~ '\.a$'
  124. continue
  125. endif
  126. let i = substitute(substitute(i[len(r)+1:], '[\\]', '/', 'g'),
  127. \ '\.a$', '', 'g')
  128. " without this the result can have duplicates in form of
  129. " 'encoding/json' and '/encoding/json/'
  130. let i = go#util#StripPathSep(i)
  131. let ret[i] = i
  132. endfor
  133. endfor
  134. endfor
  135. return sort(keys(ret))
  136. endfunction
  137. " vim: sw=2 ts=2 et