123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- " 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
|