246 lines
7.4 KiB
VimL
246 lines
7.4 KiB
VimL
|
" From "go list -h".
|
||
|
function! go#tool#ValidFiles(...)
|
||
|
let l:list = ["GoFiles", "CgoFiles", "IgnoredGoFiles", "CFiles", "CXXFiles",
|
||
|
\ "MFiles", "HFiles", "FFiles", "SFiles", "SwigFiles", "SwigCXXFiles",
|
||
|
\ "SysoFiles", "TestGoFiles", "XTestGoFiles"]
|
||
|
|
||
|
" Used as completion
|
||
|
if len(a:000) > 0
|
||
|
let l:list = filter(l:list, 'strpart(v:val, 0, len(a:1)) == a:1')
|
||
|
endif
|
||
|
|
||
|
return l:list
|
||
|
endfunction
|
||
|
|
||
|
function! go#tool#Files(...) abort
|
||
|
if len(a:000) > 0
|
||
|
let source_files = a:000
|
||
|
else
|
||
|
let source_files = ['GoFiles']
|
||
|
endif
|
||
|
|
||
|
let combined = ''
|
||
|
for sf in source_files
|
||
|
" Strip dot in case people used ":GoFiles .GoFiles".
|
||
|
let sf = substitute(sf, '^\.', '', '')
|
||
|
|
||
|
" Make sure the passed options are valid.
|
||
|
if index(go#tool#ValidFiles(), sf) == -1
|
||
|
echoerr "unknown source file variable: " . sf
|
||
|
endif
|
||
|
|
||
|
if go#util#IsWin()
|
||
|
let combined .= '{{range $f := .' . sf . '}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}'
|
||
|
else
|
||
|
let combined .= "{{range $f := ." . sf . "}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}/{{$f}}{{printf \"\\n\"}}{{end}}"
|
||
|
endif
|
||
|
endfor
|
||
|
|
||
|
let out = go#tool#ExecuteInDir('go list -f ' . shellescape(combined))
|
||
|
return split(out, '\n')
|
||
|
endfunction
|
||
|
|
||
|
function! go#tool#Deps() abort
|
||
|
if go#util#IsWin()
|
||
|
let format = '{{range $f := .Deps}}{{$f}}{{printf \"\n\"}}{{end}}'
|
||
|
else
|
||
|
let format = "{{range $f := .Deps}}{{$f}}\n{{end}}"
|
||
|
endif
|
||
|
let command = 'go list -f '.shellescape(format)
|
||
|
let out = go#tool#ExecuteInDir(command)
|
||
|
return split(out, '\n')
|
||
|
endfunction
|
||
|
|
||
|
function! go#tool#Imports() abort
|
||
|
let imports = {}
|
||
|
if go#util#IsWin()
|
||
|
let format = '{{range $f := .Imports}}{{$f}}{{printf \"\n\"}}{{end}}'
|
||
|
else
|
||
|
let format = "{{range $f := .Imports}}{{$f}}{{printf \"\\n\"}}{{end}}"
|
||
|
endif
|
||
|
let command = 'go list -f '.shellescape(format)
|
||
|
let out = go#tool#ExecuteInDir(command)
|
||
|
if go#util#ShellError() != 0
|
||
|
echo out
|
||
|
return imports
|
||
|
endif
|
||
|
|
||
|
for package_path in split(out, '\n')
|
||
|
let cmd = "go list -f '{{.Name}}' " . shellescape(package_path)
|
||
|
let package_name = substitute(go#tool#ExecuteInDir(cmd), '\n$', '', '')
|
||
|
let imports[package_name] = package_path
|
||
|
endfor
|
||
|
|
||
|
return imports
|
||
|
endfunction
|
||
|
|
||
|
function! go#tool#Info(auto) abort
|
||
|
let l:mode = get(g:, 'go_info_mode', 'gocode')
|
||
|
if l:mode == 'gocode'
|
||
|
call go#complete#Info(a:auto)
|
||
|
elseif l:mode == 'guru'
|
||
|
call go#guru#DescribeInfo()
|
||
|
else
|
||
|
call go#util#EchoError('go_info_mode value: '. l:mode .' is not valid. Valid values are: [gocode, guru]')
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! go#tool#PackageName() abort
|
||
|
let command = "go list -f \"{{.Name}}\""
|
||
|
let out = go#tool#ExecuteInDir(command)
|
||
|
if go#util#ShellError() != 0
|
||
|
return -1
|
||
|
endif
|
||
|
|
||
|
return split(out, '\n')[0]
|
||
|
endfunction
|
||
|
|
||
|
function! go#tool#ParseErrors(lines) abort
|
||
|
let errors = []
|
||
|
|
||
|
for line in a:lines
|
||
|
let fatalerrors = matchlist(line, '^\(fatal error:.*\)$')
|
||
|
let tokens = matchlist(line, '^\s*\(.\{-}\):\(\d\+\):\s*\(.*\)')
|
||
|
|
||
|
if !empty(fatalerrors)
|
||
|
call add(errors, {"text": fatalerrors[1]})
|
||
|
elseif !empty(tokens)
|
||
|
" strip endlines of form ^M
|
||
|
let out = substitute(tokens[3], '\r$', '', '')
|
||
|
|
||
|
call add(errors, {
|
||
|
\ "filename" : fnamemodify(tokens[1], ':p'),
|
||
|
\ "lnum" : tokens[2],
|
||
|
\ "text" : out,
|
||
|
\ })
|
||
|
elseif !empty(errors)
|
||
|
" Preserve indented lines.
|
||
|
" This comes up especially with multi-line test output.
|
||
|
if match(line, '^\s') >= 0
|
||
|
call add(errors, {"text": line})
|
||
|
endif
|
||
|
endif
|
||
|
endfor
|
||
|
|
||
|
return errors
|
||
|
endfunction
|
||
|
|
||
|
"FilterValids filters the given items with only items that have a valid
|
||
|
"filename. Any non valid filename is filtered out.
|
||
|
function! go#tool#FilterValids(items) abort
|
||
|
" Remove any nonvalid filename from the location list to avoid opening an
|
||
|
" empty buffer. See https://github.com/fatih/vim-go/issues/287 for
|
||
|
" details.
|
||
|
let filtered = []
|
||
|
let is_readable = {}
|
||
|
|
||
|
for item in a:items
|
||
|
if has_key(item, 'bufnr')
|
||
|
let filename = bufname(item.bufnr)
|
||
|
elseif has_key(item, 'filename')
|
||
|
let filename = item.filename
|
||
|
else
|
||
|
" nothing to do, add item back to the list
|
||
|
call add(filtered, item)
|
||
|
continue
|
||
|
endif
|
||
|
|
||
|
if !has_key(is_readable, filename)
|
||
|
let is_readable[filename] = filereadable(filename)
|
||
|
endif
|
||
|
if is_readable[filename]
|
||
|
call add(filtered, item)
|
||
|
endif
|
||
|
endfor
|
||
|
|
||
|
for k in keys(filter(is_readable, '!v:val'))
|
||
|
echo "vim-go: " | echohl Identifier | echon "[run] Dropped " | echohl Constant | echon '"' . k . '"'
|
||
|
echohl Identifier | echon " from location list (nonvalid filename)" | echohl None
|
||
|
endfor
|
||
|
|
||
|
return filtered
|
||
|
endfunction
|
||
|
|
||
|
function! go#tool#ExecuteInDir(cmd) abort
|
||
|
" Verify that the directory actually exists. If the directory does not
|
||
|
" exist, then assume that the a:cmd should not be executed. Callers expect
|
||
|
" to check v:shell_error (via go#util#ShellError()), so execute a command
|
||
|
" that will return an error as if a:cmd was run and exited with an error.
|
||
|
" This helps avoid errors when working with plugins that use virtual files
|
||
|
" that don't actually exist on the file system (e.g. vim-fugitive's
|
||
|
" GitDiff).
|
||
|
if !isdirectory(expand("%:p:h"))
|
||
|
let [out, err] = go#util#Exec(["false"])
|
||
|
return ''
|
||
|
endif
|
||
|
|
||
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||
|
let dir = getcwd()
|
||
|
try
|
||
|
execute cd . fnameescape(expand("%:p:h"))
|
||
|
let out = go#util#System(a:cmd)
|
||
|
finally
|
||
|
execute cd . fnameescape(dir)
|
||
|
endtry
|
||
|
return out
|
||
|
endfunction
|
||
|
|
||
|
" Exists checks whether the given importpath exists or not. It returns 0 if
|
||
|
" the importpath exists under GOPATH.
|
||
|
function! go#tool#Exists(importpath) abort
|
||
|
let command = "go list ". a:importpath
|
||
|
let out = go#tool#ExecuteInDir(command)
|
||
|
|
||
|
if go#util#ShellError() != 0
|
||
|
return -1
|
||
|
endif
|
||
|
|
||
|
return 0
|
||
|
endfunction
|
||
|
|
||
|
" following two functions are from: https://github.com/mattn/gist-vim
|
||
|
" thanks @mattn
|
||
|
function! s:get_browser_command() abort
|
||
|
let go_play_browser_command = get(g:, 'go_play_browser_command', '')
|
||
|
if go_play_browser_command == ''
|
||
|
if go#util#IsWin()
|
||
|
let go_play_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%'
|
||
|
elseif go#util#IsMac()
|
||
|
let go_play_browser_command = 'open %URL%'
|
||
|
elseif executable('xdg-open')
|
||
|
let go_play_browser_command = 'xdg-open %URL%'
|
||
|
elseif executable('firefox')
|
||
|
let go_play_browser_command = 'firefox %URL% &'
|
||
|
elseif executable('chromium')
|
||
|
let go_play_browser_command = 'chromium %URL% &'
|
||
|
else
|
||
|
let go_play_browser_command = ''
|
||
|
endif
|
||
|
endif
|
||
|
return go_play_browser_command
|
||
|
endfunction
|
||
|
|
||
|
function! go#tool#OpenBrowser(url) abort
|
||
|
let cmd = s:get_browser_command()
|
||
|
if len(cmd) == 0
|
||
|
redraw
|
||
|
echohl WarningMsg
|
||
|
echo "It seems that you don't have general web browser. Open URL below."
|
||
|
echohl None
|
||
|
echo a:url
|
||
|
return
|
||
|
endif
|
||
|
if cmd =~ '^!'
|
||
|
let cmd = substitute(cmd, '%URL%', '\=escape(shellescape(a:url),"#")', 'g')
|
||
|
silent! exec cmd
|
||
|
elseif cmd =~ '^:[A-Z]'
|
||
|
let cmd = substitute(cmd, '%URL%', '\=escape(a:url,"#")', 'g')
|
||
|
exec cmd
|
||
|
else
|
||
|
let cmd = substitute(cmd, '%URL%', '\=shellescape(a:url)', 'g')
|
||
|
call go#util#System(cmd)
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
" vim: sw=2 ts=2 et
|