path.vim 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. " initial_go_path is used to store the initial GOPATH that was set when Vim
  2. " was started. It's used with :GoPathClear to restore the GOPATH when the user
  3. " changed it explicitly via :GoPath. Initially it's empty. It's being set when
  4. " :GoPath is used
  5. let s:initial_go_path = ""
  6. " GoPath sets or echos the current GOPATH. If no arguments are passed it
  7. " echoes the current GOPATH, if an argument is passed it replaces the current
  8. " GOPATH with it. If two double quotes are passed (the empty string in go),
  9. " it'll clear the GOPATH and will restore to the initial GOPATH.
  10. function! go#path#GoPath(...) abort
  11. " no argument, show GOPATH
  12. if len(a:000) == 0
  13. echo go#path#Default()
  14. return
  15. endif
  16. " we have an argument, replace GOPATH
  17. " clears the current manually set GOPATH and restores it to the
  18. " initial GOPATH, which was set when Vim was started.
  19. if len(a:000) == 1 && a:1 == '""'
  20. if !empty(s:initial_go_path)
  21. let $GOPATH = s:initial_go_path
  22. let s:initial_go_path = ""
  23. endif
  24. echon "vim-go: " | echohl Function | echon "GOPATH restored to ". $GOPATH | echohl None
  25. return
  26. endif
  27. echon "vim-go: " | echohl Function | echon "GOPATH changed to ". a:1 | echohl None
  28. let s:initial_go_path = $GOPATH
  29. let $GOPATH = a:1
  30. endfunction
  31. " Default returns the default GOPATH. If GOPATH is not set, it uses the
  32. " default GOPATH set starting with Go 1.8. This GOPATH can be retrieved via
  33. " 'go env GOPATH'
  34. function! go#path#Default() abort
  35. if $GOPATH == ""
  36. " use default GOPATH via go env
  37. return go#util#env("gopath")
  38. endif
  39. return $GOPATH
  40. endfunction
  41. " s:HasPath checks whether the given path exists in GOPATH environment variable
  42. " or not
  43. function! s:HasPath(path) abort
  44. let go_paths = split(go#path#Default(), go#util#PathListSep())
  45. let last_char = strlen(a:path) - 1
  46. " check cases of '/foo/bar/' and '/foo/bar'
  47. if a:path[last_char] == go#util#PathSep()
  48. let withSep = a:path
  49. let noSep = strpart(a:path, 0, last_char)
  50. else
  51. let withSep = a:path . go#util#PathSep()
  52. let noSep = a:path
  53. endif
  54. let hasA = index(go_paths, withSep) != -1
  55. let hasB = index(go_paths, noSep) != -1
  56. return hasA || hasB
  57. endfunction
  58. " Detect returns the current GOPATH. If a package manager is used, such as
  59. " Godeps, GB, it will modify the GOPATH so those directories take precedence
  60. " over the current GOPATH. It also detects diretories whose are outside
  61. " GOPATH.
  62. function! go#path#Detect() abort
  63. let gopath = go#path#Default()
  64. let current_dir = fnameescape(expand('%:p:h'))
  65. " TODO(arslan): this should be changed so folders or files should be
  66. " fetched from a customizable list. The user should define any new package
  67. " management tool by it's own.
  68. " src folders outside $GOPATH
  69. let src_roots = finddir("src", current_dir .";", -1)
  70. " for cases like GOPATH/src/foo/src/bar, pick up GOPATH/src instead of
  71. " GOPATH/src/foo/src
  72. let src_root = ""
  73. if len(src_roots) > 0
  74. let src_root = src_roots[-1]
  75. endif
  76. if !empty(src_root)
  77. let src_path = fnamemodify(src_root, ':p:h:h') . go#util#PathSep()
  78. " gb vendor plugin
  79. " (https://github.com/constabulary/gb/tree/master/cmd/gb-vendor)
  80. let gb_vendor_root = src_path . "vendor" . go#util#PathSep()
  81. if isdirectory(gb_vendor_root) && !s:HasPath(gb_vendor_root)
  82. let gopath = gb_vendor_root . go#util#PathListSep() . gopath
  83. endif
  84. if !s:HasPath(src_path)
  85. let gopath = src_path . go#util#PathListSep() . gopath
  86. endif
  87. endif
  88. " Godeps
  89. let godeps_root = finddir("Godeps", current_dir .";")
  90. if !empty(godeps_root)
  91. let godeps_path = join([fnamemodify(godeps_root, ':p:h:h'), "Godeps", "_workspace" ], go#util#PathSep())
  92. if !s:HasPath(godeps_path)
  93. let gopath = godeps_path . go#util#PathListSep() . gopath
  94. endif
  95. endif
  96. " Fix up the case where initial $GOPATH is empty,
  97. " and we end up with a trailing :
  98. let gopath = substitute(gopath, ":$", "", "")
  99. return gopath
  100. endfunction
  101. " BinPath returns the binary path of installed go tools.
  102. function! go#path#BinPath() abort
  103. let bin_path = ""
  104. " check if our global custom path is set, if not check if $GOBIN is set so
  105. " we can use it, otherwise use default GOPATH
  106. if exists("g:go_bin_path")
  107. let bin_path = g:go_bin_path
  108. elseif $GOBIN != ""
  109. let bin_path = $GOBIN
  110. else
  111. let go_paths = split(go#path#Default(), go#util#PathListSep())
  112. if len(go_paths) == 0
  113. return "" "nothing found
  114. endif
  115. let bin_path = expand(go_paths[0] . "/bin/")
  116. endif
  117. return bin_path
  118. endfunction
  119. " CheckBinPath checks whether the given binary exists or not and returns the
  120. " path of the binary. It returns an empty string doesn't exists.
  121. function! go#path#CheckBinPath(binpath) abort
  122. " remove whitespaces if user applied something like 'goimports '
  123. let binpath = substitute(a:binpath, '^\s*\(.\{-}\)\s*$', '\1', '')
  124. " save off original path
  125. let old_path = $PATH
  126. " check if we have an appropriate bin_path
  127. let go_bin_path = go#path#BinPath()
  128. if !empty(go_bin_path)
  129. " append our GOBIN and GOPATH paths and be sure they can be found there...
  130. " let us search in our GOBIN and GOPATH paths
  131. let $PATH = go_bin_path . go#util#PathListSep() . $PATH
  132. endif
  133. " if it's in PATH just return it
  134. if executable(binpath)
  135. if exists('*exepath')
  136. let binpath = exepath(binpath)
  137. endif
  138. let $PATH = old_path
  139. if go#util#IsUsingCygwinShell() == 1
  140. return s:CygwinPath(binpath)
  141. endif
  142. return binpath
  143. endif
  144. " just get the basename
  145. let basename = fnamemodify(binpath, ":t")
  146. if !executable(basename)
  147. call go#util#EchoError(printf("could not find '%s'. Run :GoInstallBinaries to fix it", basename))
  148. " restore back!
  149. let $PATH = old_path
  150. return ""
  151. endif
  152. let $PATH = old_path
  153. if go#util#IsUsingCygwinShell() == 1
  154. return s:CygwinPath(a:binpath)
  155. endif
  156. return go_bin_path . go#util#PathSep() . basename
  157. endfunction
  158. function! s:CygwinPath(path)
  159. return substitute(a:path, '\\', '/', "g")
  160. endfunction
  161. " vim: sw=2 ts=2 et