go.vim 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. " install necessary Go tools
  2. if exists("g:go_loaded_install")
  3. finish
  4. endif
  5. let g:go_loaded_install = 1
  6. " Not using the has('patch-7.4.1689') syntax because that wasn't added until
  7. " 7.4.237, and we want to be sure this works for everyone (this is also why
  8. " we're not using utils#EchoError()).
  9. "
  10. " Version 7.4.1689 was chosen because that's what the most recent Ubuntu LTS
  11. " release (16.04) uses.
  12. if
  13. \ get(g:, 'go_version_warning', 1) != 0 &&
  14. \ (v:version < 704 || (v:version == 704 && !has('patch1689')))
  15. \ && !has('nvim')
  16. echohl Error
  17. echom "vim-go requires Vim 7.4.1689 or Neovim, but you're using an older version."
  18. echom "Please update your Vim for the best vim-go experience."
  19. echom "If you really want to continue you can set this to make the error go away:"
  20. echom " let g:go_version_warning = 0"
  21. echom "Note that some features may error out or behave incorrectly."
  22. echom "Please do not report bugs unless you're using Vim 7.4.1689 or newer."
  23. echohl None
  24. " Make sure people see this.
  25. sleep 2
  26. endif
  27. " these packages are used by vim-go and can be automatically installed if
  28. " needed by the user with GoInstallBinaries
  29. let s:packages = {
  30. \ 'asmfmt': ['github.com/klauspost/asmfmt/cmd/asmfmt'],
  31. \ 'dlv': ['github.com/derekparker/delve/cmd/dlv'],
  32. \ 'errcheck': ['github.com/kisielk/errcheck'],
  33. \ 'fillstruct': ['github.com/davidrjenni/reftools/cmd/fillstruct'],
  34. \ 'gocode': ['github.com/nsf/gocode', {'windows': '-ldflags -H=windowsgui'}],
  35. \ 'godef': ['github.com/rogpeppe/godef'],
  36. \ 'gogetdoc': ['github.com/zmb3/gogetdoc'],
  37. \ 'goimports': ['golang.org/x/tools/cmd/goimports'],
  38. \ 'golint': ['github.com/golang/lint/golint'],
  39. \ 'gometalinter': ['github.com/alecthomas/gometalinter'],
  40. \ 'gomodifytags': ['github.com/fatih/gomodifytags'],
  41. \ 'gorename': ['golang.org/x/tools/cmd/gorename'],
  42. \ 'gotags': ['github.com/jstemmer/gotags'],
  43. \ 'guru': ['golang.org/x/tools/cmd/guru'],
  44. \ 'impl': ['github.com/josharian/impl'],
  45. \ 'keyify': ['github.com/dominikh/go-tools/cmd/keyify'],
  46. \ 'motion': ['github.com/fatih/motion'],
  47. \ }
  48. " These commands are available on any filetypes
  49. command! -nargs=* -complete=customlist,s:complete GoInstallBinaries call s:GoInstallBinaries(-1, <f-args>)
  50. command! -nargs=* -complete=customlist,s:complete GoUpdateBinaries call s:GoInstallBinaries(1, <f-args>)
  51. command! -nargs=? -complete=dir GoPath call go#path#GoPath(<f-args>)
  52. fun! s:complete(lead, cmdline, cursor)
  53. return filter(keys(s:packages), 'strpart(v:val, 0, len(a:lead)) == a:lead')
  54. endfun
  55. " GoInstallBinaries downloads and installs binaries defined in s:packages to
  56. " $GOBIN or $GOPATH/bin. GoInstallBinaries will update already installed
  57. " binaries only if updateBinaries = 1. By default, all packages in s:packages
  58. " will be installed, but the set can be limited by passing the desired
  59. " packages in the unnamed arguments.
  60. function! s:GoInstallBinaries(updateBinaries, ...)
  61. let err = s:CheckBinaries()
  62. if err != 0
  63. return
  64. endif
  65. if go#path#Default() == ""
  66. echohl Error
  67. echomsg "vim.go: $GOPATH is not set and 'go env GOPATH' returns empty"
  68. echohl None
  69. return
  70. endif
  71. let go_bin_path = go#path#BinPath()
  72. " change $GOBIN so go get can automatically install to it
  73. let $GOBIN = go_bin_path
  74. " old_path is used to restore users own path
  75. let old_path = $PATH
  76. " vim's executable path is looking in PATH so add our go_bin path to it
  77. let $PATH = go_bin_path . go#util#PathListSep() . $PATH
  78. " when shellslash is set on MS-* systems, shellescape puts single quotes
  79. " around the output string. cmd on Windows does not handle single quotes
  80. " correctly. Unsetting shellslash forces shellescape to use double quotes
  81. " instead.
  82. let resetshellslash = 0
  83. if has('win32') && &shellslash
  84. let resetshellslash = 1
  85. set noshellslash
  86. endif
  87. let cmd = "go get -v "
  88. if get(g:, "go_get_update", 1) != 0
  89. let cmd .= "-u "
  90. endif
  91. let s:go_version = matchstr(go#util#System("go version"), '\d.\d.\d')
  92. " https://github.com/golang/go/issues/10791
  93. if s:go_version > "1.4.0" && s:go_version < "1.5.0"
  94. let cmd .= "-f "
  95. endif
  96. " Filter packages from arguments (if any).
  97. let l:packages = {}
  98. if a:0 > 0
  99. for l:bin in a:000
  100. let l:pkg = get(s:packages, l:bin, [])
  101. if len(l:pkg) == 0
  102. call go#util#EchoError('unknown binary: ' . l:bin)
  103. return
  104. endif
  105. let l:packages[l:bin] = l:pkg
  106. endfor
  107. else
  108. let l:packages = s:packages
  109. endif
  110. let l:platform = ''
  111. if go#util#IsWin()
  112. let l:platform = 'windows'
  113. endif
  114. for [binary, pkg] in items(l:packages)
  115. let l:importPath = pkg[0]
  116. let l:goGetFlags = len(pkg) > 1 ? get(pkg[1], l:platform, '') : ''
  117. let binname = "go_" . binary . "_bin"
  118. let bin = binary
  119. if exists("g:{binname}")
  120. let bin = g:{binname}
  121. endif
  122. if !executable(bin) || a:updateBinaries == 1
  123. if a:updateBinaries == 1
  124. echo "vim-go: Updating " . binary . ". Reinstalling ". importPath . " to folder " . go_bin_path
  125. else
  126. echo "vim-go: ". binary ." not found. Installing ". importPath . " to folder " . go_bin_path
  127. endif
  128. let out = go#util#System(printf('%s %s %s', cmd, l:goGetFlags, shellescape(importPath)))
  129. if go#util#ShellError() != 0
  130. echom "Error installing " . importPath . ": " . out
  131. endif
  132. endif
  133. endfor
  134. " restore back!
  135. let $PATH = old_path
  136. if resetshellslash
  137. set shellslash
  138. endif
  139. endfunction
  140. " CheckBinaries checks if the necessary binaries to install the Go tool
  141. " commands are available.
  142. function! s:CheckBinaries()
  143. if !executable('go')
  144. echohl Error | echomsg "vim-go: go executable not found." | echohl None
  145. return -1
  146. endif
  147. if !executable('git')
  148. echohl Error | echomsg "vim-go: git executable not found." | echohl None
  149. return -1
  150. endif
  151. endfunction
  152. " Autocommands
  153. " ============================================================================
  154. "
  155. function! s:echo_go_info()
  156. if !get(g:, "go_echo_go_info", 1)
  157. return
  158. endif
  159. if !exists('v:completed_item') || empty(v:completed_item)
  160. return
  161. endif
  162. let item = v:completed_item
  163. if !has_key(item, "info")
  164. return
  165. endif
  166. if empty(item.info)
  167. return
  168. endif
  169. redraws! | echo "vim-go: " | echohl Function | echon item.info | echohl None
  170. endfunction
  171. function! s:auto_type_info()
  172. " GoInfo automatic update
  173. if get(g:, "go_auto_type_info", 0)
  174. call go#tool#Info(1)
  175. endif
  176. endfunction
  177. function! s:auto_sameids()
  178. " GoSameId automatic update
  179. if get(g:, "go_auto_sameids", 0)
  180. call go#guru#SameIds()
  181. endif
  182. endfunction
  183. function! s:fmt_autosave()
  184. " Go code formatting on save
  185. if get(g:, "go_fmt_autosave", 1)
  186. call go#fmt#Format(-1)
  187. endif
  188. endfunction
  189. function! s:asmfmt_autosave()
  190. " Go asm formatting on save
  191. if get(g:, "go_asmfmt_autosave", 0)
  192. call go#asmfmt#Format()
  193. endif
  194. endfunction
  195. function! s:metalinter_autosave()
  196. " run gometalinter on save
  197. if get(g:, "go_metalinter_autosave", 0)
  198. call go#lint#Gometa(1)
  199. endif
  200. endfunction
  201. function! s:template_autocreate()
  202. " create new template from scratch
  203. if get(g:, "go_template_autocreate", 1)
  204. call go#template#create()
  205. endif
  206. endfunction
  207. augroup vim-go
  208. autocmd!
  209. autocmd CursorHold *.go call s:auto_type_info()
  210. autocmd CursorHold *.go call s:auto_sameids()
  211. " Echo the identifier information when completion is done. Useful to see
  212. " the signature of a function, etc...
  213. if exists('##CompleteDone')
  214. autocmd CompleteDone *.go call s:echo_go_info()
  215. endif
  216. autocmd BufWritePre *.go call s:fmt_autosave()
  217. autocmd BufWritePre *.s call s:asmfmt_autosave()
  218. autocmd BufWritePost *.go call s:metalinter_autosave()
  219. autocmd BufNewFile *.go call s:template_autocreate()
  220. " clear SameIds when the buffer is unloaded so that loading another buffer
  221. " in the same window doesn't highlight the most recently matched
  222. " identifier's positions.
  223. autocmd BufWinEnter *.go call go#guru#ClearSameIds()
  224. autocmd BufEnter *.go
  225. \ if get(g:, 'go_autodetect_gopath', 0) && !exists('b:old_gopath')
  226. \| let b:old_gopath = exists('$GOPATH') ? $GOPATH : -1
  227. \| let $GOPATH = go#path#Detect()
  228. \| endif
  229. autocmd BufLeave *.go
  230. \ if exists('b:old_gopath')
  231. \| if b:old_gopath isnot -1
  232. \| let $GOPATH = b:old_gopath
  233. \| endif
  234. \| unlet b:old_gopath
  235. \| endif
  236. augroup end
  237. " vim: sw=2 ts=2 et