1
0
mirror of https://github.com/amix/vimrc synced 2025-06-16 09:35:01 +08:00

Updated plugins

This commit is contained in:
Amir Salihefendic
2018-06-14 12:31:12 +02:00
parent 7288aee801
commit 3e3297af67
273 changed files with 11821 additions and 5377 deletions

View File

@ -1,8 +1,3 @@
" By default use edit (current buffer view) to switch
if !exists("g:go_alternate_mode")
let g:go_alternate_mode = "edit"
endif
" Test alternates between the implementation of code and the test code.
function! go#alternate#Switch(bang, cmd) abort
let file = expand('%')
@ -23,7 +18,7 @@ function! go#alternate#Switch(bang, cmd) abort
call go#util#EchoError("couldn't find ".alt_file)
return
elseif empty(a:cmd)
execute ":" . g:go_alternate_mode . " " . alt_file
execute ":" . go#config#AlternateMode() . " " . alt_file
else
execute ":" . a:cmd . " " . alt_file
endif

View File

@ -28,41 +28,40 @@ function! go#asmfmt#Format() abort
call writefile(go#util#GetLines(), l:tmpname)
" Run asmfmt.
let path = go#path#CheckBinPath("asmfmt")
if empty(path)
let [l:out, l:err] = go#util#Exec(['asmfmt', '-w', l:tmpname])
if l:err
call go#util#EchoError(l:out)
return
endif
let out = go#util#System(path . ' -w ' . l:tmpname)
" If there's no error, replace the current file with the output.
if go#util#ShellError() == 0
" Remove undo point caused by BufWritePre.
try | silent undojoin | catch | endtry
" Remove undo point caused by BufWritePre.
try | silent undojoin | catch | endtry
" Replace the current file with the temp file; then reload the buffer.
let old_fileformat = &fileformat
" save old file permissions
let original_fperm = getfperm(expand('%'))
call rename(l:tmpname, expand('%'))
" restore old file permissions
call setfperm(expand('%'), original_fperm)
silent edit!
let &fileformat = old_fileformat
let &syntax = &syntax
endif
" Replace the current file with the temp file; then reload the buffer.
let old_fileformat = &fileformat
" save old file permissions
let original_fperm = getfperm(expand('%'))
call rename(l:tmpname, expand('%'))
" restore old file permissions
call setfperm(expand('%'), original_fperm)
silent edit!
let &fileformat = old_fileformat
let &syntax = &syntax
" Restore the cursor/window positions.
call winrestview(l:curw)
endfunction
function! go#asmfmt#ToggleAsmFmtAutoSave() abort
if get(g:, "go_asmfmt_autosave", 0)
let g:go_asmfmt_autosave = 1
if go#config#AsmfmtAutosave()
call go#config#SetAsmfmtAutosave(1)
call go#util#EchoProgress("auto asmfmt enabled")
return
end
let g:go_asmfmt_autosave = 0
call go#config#SetAsmfmtAutosave(0)
call go#util#EchoProgress("auto asmfmt disabled")
endfunction

View File

@ -1,6 +1,17 @@
function! go#cmd#autowrite() abort
if &autowrite == 1 || &autowriteall == 1
silent! wall
else
for l:nr in range(0, bufnr('$'))
if buflisted(l:nr) && getbufvar(l:nr, '&modified')
" Sleep one second to make sure people see the message. Otherwise it is
" often immediacy overwritten by the async messages (which also don't
" invoke the "hit ENTER" prompt).
call go#util#EchoWarning('[No write since last change]')
sleep 1
return
endif
endfor
endif
endfunction
@ -14,14 +25,14 @@ function! go#cmd#Build(bang, ...) abort
" placeholder with the current folder (indicated with '.'). We also pass -i
" that tries to install the dependencies, this has the side effect that it
" caches the build results, so every other build is faster.
let args =
\ ["build"] +
let l:args =
\ ['build', '-tags', go#config#BuildTags()] +
\ map(copy(a:000), "expand(v:val)") +
\ [".", "errors"]
" Vim async.
if go#util#has_job()
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
call go#util#EchoProgress("building dispatched ...")
endif
@ -33,7 +44,7 @@ function! go#cmd#Build(bang, ...) abort
" Nvim async.
elseif has('nvim')
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
call go#util#EchoProgress("building dispatched ...")
endif
@ -77,21 +88,26 @@ endfunction
" BuildTags sets or shows the current build tags used for tools
function! go#cmd#BuildTags(bang, ...) abort
if a:0
if a:0 == 1 && a:1 == '""'
unlet g:go_build_tags
let v = a:1
if v == '""' || v == "''"
let v = ""
endif
call go#config#SetBuildTags(v)
let tags = go#config#BuildTags()
if empty(tags)
call go#util#EchoSuccess("build tags are cleared")
else
let g:go_build_tags = a:1
call go#util#EchoSuccess("build tags are changed to: ". a:1)
call go#util#EchoSuccess("build tags are changed to: " . tags)
endif
return
endif
if !exists('g:go_build_tags')
let tags = go#config#BuildTags()
if empty(tags)
call go#util#EchoSuccess("build tags are not set")
else
call go#util#EchoSuccess("current build tags: ". g:go_build_tags)
call go#util#EchoSuccess("current build tags: " . tags)
endif
endfunction
@ -170,12 +186,12 @@ function! go#cmd#Install(bang, ...) abort
" expand all wildcards(i.e: '%' to the current file name)
let goargs = map(copy(a:000), "expand(v:val)")
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
call go#util#EchoProgress("installing dispatched ...")
endif
call s:cmd_job({
\ 'cmd': ['go', 'install'] + goargs,
\ 'cmd': ['go', 'install', '-tags', go#config#BuildTags()] + goargs,
\ 'bang': a:bang,
\ 'for': 'GoInstall',
\})

View File

@ -1,12 +1,10 @@
let s:sock_type = (has('win32') || has('win64')) ? 'tcp' : 'unix'
function! s:gocodeCommand(cmd, args) abort
let bin_path = go#path#CheckBinPath("gocode")
if empty(bin_path)
return []
endif
let socket_type = get(g:, 'go_gocode_socket_type', s:sock_type)
let socket_type = go#config#GocodeSocketType()
let cmd = [bin_path]
let cmd = extend(cmd, ['-sock', socket_type])
@ -45,27 +43,26 @@ function! s:sync_gocode(cmd, args, input) abort
return l:result
endfunction
" TODO(bc): reset when gocode isn't running
let s:optionsEnabled = 0
function! s:gocodeEnableOptions() abort
if s:optionsEnabled
return
endif
let bin_path = go#path#CheckBinPath("gocode")
if empty(bin_path)
let l:bin_path = go#path#CheckBinPath("gocode")
if empty(l:bin_path)
return
endif
let s:optionsEnabled = 1
call go#util#System(printf('%s set propose-builtins %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_propose_builtins', 1))))
call go#util#System(printf('%s set autobuild %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_autobuild', 1))))
call go#util#System(printf('%s set unimported-packages %s', go#util#Shellescape(bin_path), s:toBool(get(g:, 'go_gocode_unimported_packages', 0))))
call go#util#Exec(['gocode', 'set', 'propose-builtins', s:toBool(go#config#GocodeProposeBuiltins())])
call go#util#Exec(['gocode', 'set', 'autobuild', s:toBool(go#config#GocodeAutobuild())])
call go#util#Exec(['gocode', 'set', 'unimported-packages', s:toBool(go#config#GocodeUnimportedPackages())])
endfunction
function! s:toBool(val) abort
if a:val | return 'true ' | else | return 'false' | endif
if a:val | return 'true' | else | return 'false' | endif
endfunction
function! s:gocodeAutocomplete() abort
@ -85,7 +82,7 @@ function! go#complete#GetInfo() abort
endfunction
function! go#complete#Info(auto) abort
if go#util#has_job()
if go#util#has_job(1)
return s:async_info(a:auto)
else
return s:sync_info(a:auto)
@ -252,13 +249,13 @@ function! go#complete#Complete(findstart, base) abort
endfunction
function! go#complete#ToggleAutoTypeInfo() abort
if get(g:, "go_auto_type_info", 0)
let g:go_auto_type_info = 0
if go#config#AutoTypeInfo()
call go#config#SetAutoTypeInfo(0)
call go#util#EchoProgress("auto type info disabled")
return
end
let g:go_auto_type_info = 1
call go#config#SetAutoTypeInfo(1)
call go#util#EchoProgress("auto type info enabled")
endfunction

View File

@ -0,0 +1,432 @@
function! go#config#AutodetectGopath() abort
return get(g:, 'go_autodetect_gopath', 0)
endfunction
function! go#config#ListTypeCommands() abort
return get(g:, 'go_list_type_commands', {})
endfunction
function! go#config#VersionWarning() abort
return get(g:, 'go_version_warning', 1)
endfunction
function! go#config#BuildTags() abort
return get(g:, 'go_build_tags', '')
endfunction
function! go#config#SetBuildTags(value) abort
if a:value is ''
silent! unlet g:go_build_tags
return
endif
let g:go_build_tags = a:value
endfunction
function! go#config#TestTimeout() abort
return get(g:, 'go_test_timeout', '10s')
endfunction
function! go#config#TestShowName() abort
return get(g:, 'go_test_show_name', 0)
endfunction
function! go#config#TermHeight() abort
return get(g:, 'go_term_height', winheight(0))
endfunction
function! go#config#TermWidth() abort
return get(g:, 'go_term_width', winwidth(0))
endfunction
function! go#config#TermMode() abort
return get(g:, 'go_term_mode', 'vsplit')
endfunction
function! go#config#TermEnabled() abort
return get(g:, 'go_term_enabled', 0)
endfunction
function! go#config#SetTermEnabled(value) abort
let g:go_term_enabled = a:value
endfunction
function! go#config#TemplateUsePkg() abort
return get(g:, 'go_template_use_pkg', 0)
endfunction
function! go#config#TemplateTestFile() abort
return get(g:, 'go_template_test_file', "hello_world_test.go")
endfunction
function! go#config#TemplateFile() abort
return get(g:, 'go_template_file', "hello_world.go")
endfunction
function! go#config#StatuslineDuration() abort
return get(g:, 'go_statusline_duration', 60000)
endfunction
function! go#config#SnippetEngine() abort
return get(g:, 'go_snippet_engine', 'automatic')
endfunction
function! go#config#PlayBrowserCommand() abort
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
return get(g:, 'go_play_browser_command', go_play_browser_command)
endfunction
function! go#config#MetalinterDeadline() abort
" gometalinter has a default deadline of 5 seconds only when asynchronous
" jobs are not supported.
let deadline = '5s'
if go#util#has_job() && has('lambda')
let deadline = ''
endif
return get(g:, 'go_metalinter_deadline', deadline)
endfunction
function! go#config#ListType() abort
return get(g:, 'go_list_type', '')
endfunction
function! go#config#ListAutoclose() abort
return get(g:, 'go_list_autoclose', 1)
endfunction
function! go#config#InfoMode() abort
return get(g:, 'go_info_mode', 'gocode')
endfunction
function! go#config#GuruScope() abort
let scope = get(g:, 'go_guru_scope', [])
if !empty(scope)
" strip trailing slashes for each path in scope. bug:
" https://github.com/golang/go/issues/14584
let scopes = go#util#StripTrailingSlash(scope)
endif
return scope
endfunction
function! go#config#SetGuruScope(scope) abort
if empty(a:scope)
if exists('g:go_guru_scope')
unlet g:go_guru_scope
endif
else
let g:go_guru_scope = a:scope
endif
endfunction
function! go#config#GocodeUnimportedPackages() abort
return get(g:, 'go_gocode_unimported_packages', 0)
endfunction
let s:sock_type = (has('win32') || has('win64')) ? 'tcp' : 'unix'
function! go#config#GocodeSocketType() abort
return get(g:, 'go_gocode_socket_type', s:sock_type)
endfunction
function! go#config#GocodeProposeBuiltins() abort
return get(g:, 'go_gocode_propose_builtins', 1)
endfunction
function! go#config#GocodeAutobuild() abort
return get(g:, 'go_gocode_autobuild', 1)
endfunction
function! go#config#EchoCommandInfo() abort
return get(g:, 'go_echo_command_info', 1)
endfunction
function! go#config#DocUrl() abort
let godoc_url = get(g:, 'go_doc_url', 'https://godoc.org')
if godoc_url isnot 'https://godoc.org'
" strip last '/' character if available
let last_char = strlen(godoc_url) - 1
if godoc_url[last_char] == '/'
let godoc_url = strpart(godoc_url, 0, last_char)
endif
" custom godoc installations expect /pkg before package names
let godoc_url .= "/pkg"
endif
return godoc_url
endfunction
function! go#config#DefReuseBuffer() abort
return get(g:, 'go_def_reuse_buffer', 0)
endfunction
function! go#config#DefMode() abort
return get(g:, 'go_def_mode', 'guru')
endfunction
function! go#config#DeclsIncludes() abort
return get(g:, 'go_decls_includes', 'func,type')
endfunction
function! go#config#Debug() abort
return get(g:, 'go_debug', [])
endfunction
function! go#config#DebugWindows() abort
return get(g:, 'go_debug_windows', {
\ 'stack': 'leftabove 20vnew',
\ 'out': 'botright 10new',
\ 'vars': 'leftabove 30vnew',
\ }
\ )
endfunction
function! go#config#DebugAddress() abort
return get(g:, 'go_debug_address', '127.0.0.1:8181')
endfunction
function! go#config#DebugCommands() abort
" make sure g:go_debug_commands is set so that it can be added to easily.
let g:go_debug_commands = get(g:, 'go_debug_commands', {})
return g:go_debug_commands
endfunction
function! go#config#SetDebugDiag(value) abort
let g:go_debug_diag = a:value
endfunction
function! go#config#AutoSameids() abort
return get(g:, 'go_auto_sameids', 0)
endfunction
function! go#config#SetAutoSameids(value) abort
let g:go_auto_sameids = a:value
endfunction
function! go#config#AddtagsTransform() abort
return get(g:, 'go_addtags_transform', "snakecase")
endfunction
function! go#config#TemplateAutocreate() abort
return get(g:, "go_template_autocreate", 1)
endfunction
function! go#config#SetTemplateAutocreate(value) abort
let g:go_template_autocreate = a:value
endfunction
function! go#config#MetalinterCommand() abort
return get(g:, "go_metalinter_command", "")
endfunction
function! go#config#MetalinterAutosaveEnabled() abort
return get(g:, 'go_metalinter_autosave_enabled', ['vet', 'golint'])
endfunction
function! go#config#MetalinterEnabled() abort
return get(g:, "go_metalinter_enabled", ['vet', 'golint', 'errcheck'])
endfunction
function! go#config#MetalinterDisabled() abort
return get(g:, "go_metalinter_disabled", [])
endfunction
function! go#config#GolintBin() abort
return get(g:, "go_golint_bin", "golint")
endfunction
function! go#config#ErrcheckBin() abort
return get(g:, "go_errcheck_bin", "errcheck")
endfunction
function! go#config#MetalinterAutosave() abort
return get(g:, "go_metalinter_autosave", 0)
endfunction
function! go#config#SetMetalinterAutosave(value) abort
let g:go_metalinter_autosave = a:value
endfunction
function! go#config#ListHeight() abort
return get(g:, "go_list_height", 0)
endfunction
function! go#config#FmtAutosave() abort
return get(g:, "go_fmt_autosave", 1)
endfunction
function! go#config#SetFmtAutosave(value) abort
let g:go_fmt_autosave = a:value
endfunction
function! go#config#AsmfmtAutosave() abort
return get(g:, "go_asmfmt_autosave", 0)
endfunction
function! go#config#SetAsmfmtAutosave(value) abort
let g:go_asmfmt_autosave = a:value
endfunction
function! go#config#DocMaxHeight() abort
return get(g:, "go_doc_max_height", 20)
endfunction
function! go#config#AutoTypeInfo() abort
return get(g:, "go_auto_type_info", 0)
endfunction
function! go#config#SetAutoTypeInfo(value) abort
let g:go_auto_type_info = a:value
endfunction
function! go#config#AlternateMode() abort
return get(g:, "go_alternate_mode", "edit")
endfunction
function! go#config#DeclsMode() abort
return get(g:, "go_decls_mode", "")
endfunction
function! go#config#DocCommand() abort
return get(g:, "go_doc_command", ["godoc"])
endfunction
function! go#config#FmtCommand() abort
return get(g:, "go_fmt_command", "gofmt")
endfunction
function! go#config#FmtOptions() abort
return get(g:, "go_fmt_options", {})
endfunction
function! go#config#FmtFailSilently() abort
return get(g:, "go_fmt_fail_silently", 0)
endfunction
function! go#config#FmtExperimental() abort
return get(g:, "go_fmt_experimental", 0 )
endfunction
function! go#config#PlayOpenBrowser() abort
return get(g:, "go_play_open_browser", 1)
endfunction
function! go#config#GorenameBin() abort
return get(g:, "go_gorename_bin", "gorename")
endfunction
function! go#config#GorenamePrefill() abort
return get(g:, "go_gorename_prefill", 'expand("<cword>") =~# "^[A-Z]"' .
\ '? go#util#pascalcase(expand("<cword>"))' .
\ ': go#util#camelcase(expand("<cword>"))')
endfunction
function! go#config#TextobjIncludeFunctionDoc() abort
return get(g:, "go_textobj_include_function_doc", 1)
endfunction
function! go#config#TextobjIncludeVariable() abort
return get(g:, "go_textobj_include_variable", 1)
endfunction
function! go#config#BinPath() abort
return get(g:, "go_bin_path", "")
endfunction
function! go#config#HighlightArrayWhitespaceError() abort
return get(g:, 'go_highlight_array_whitespace_error', 0)
endfunction
function! go#config#HighlightChanWhitespaceError() abort
return get(g:, 'go_highlight_chan_whitespace_error', 0)
endfunction
function! go#config#HighlightExtraTypes() abort
return get(g:, 'go_highlight_extra_types', 0)
endfunction
function! go#config#HighlightSpaceTabError() abort
return get(g:, 'go_highlight_space_tab_error', 0)
endfunction
function! go#config#HighlightTrailingWhitespaceError() abort
return get(g:, 'go_highlight_trailing_whitespace_error', 0)
endfunction
function! go#config#HighlightOperators() abort
return get(g:, 'go_highlight_operators', 0)
endfunction
function! go#config#HighlightFunctions() abort
return get(g:, 'go_highlight_functions', 0)
endfunction
function! go#config#HighlightFunctionArguments() abort
return get(g:, 'go_highlight_function_arguments', 0)
endfunction
function! go#config#HighlightFunctionCalls() abort
return get(g:, 'go_highlight_function_calls', 0)
endfunction
function! go#config#HighlightFields() abort
return get(g:, 'go_highlight_fields', 0)
endfunction
function! go#config#HighlightTypes() abort
return get(g:, 'go_highlight_types', 0)
endfunction
function! go#config#HighlightBuildConstraints() abort
return get(g:, 'go_highlight_build_constraints', 0)
endfunction
function! go#config#HighlightStringSpellcheck() abort
return get(g:, 'go_highlight_string_spellcheck', 1)
endfunction
function! go#config#HighlightFormatStrings() abort
return get(g:, 'go_highlight_format_strings', 1)
endfunction
function! go#config#HighlightGenerateTags() abort
return get(g:, 'go_highlight_generate_tags', 0)
endfunction
function! go#config#HighlightVariableAssignments() abort
return get(g:, 'go_highlight_variable_assignments', 0)
endfunction
function! go#config#HighlightVariableDeclarations() abort
return get(g:, 'go_highlight_variable_declarations', 0)
endfunction
function go#config#FoldEnable(...) abort
if a:0 > 0
return index(go#config#FoldEnable(), a:1) > -1
endif
return get(g:, 'go_fold_enable', ['block', 'import', 'varconst', 'package_comment'])
endfunction
" Set the default value. A value of "1" is a shortcut for this, for
" compatibility reasons.
if exists("g:go_gorename_prefill") && g:go_gorename_prefill == 1
unlet g:go_gorename_prefill
endif
" vim: sw=2 ts=2 et

View File

@ -44,13 +44,13 @@ function! go#coverage#Buffer(bang, ...) abort
let s:toggle = 1
let l:tmpname = tempname()
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
call go#util#EchoProgress("testing...")
endif
if go#util#has_job()
call s:coverage_job({
\ 'cmd': ['go', 'test', '-coverprofile', l:tmpname] + a:000,
\ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname] + a:000,
\ 'complete': function('s:coverage_callback', [l:tmpname]),
\ 'bang': a:bang,
\ 'for': 'GoTest',
@ -64,15 +64,15 @@ function! go#coverage#Buffer(bang, ...) abort
endif
let disabled_term = 0
if get(g:, 'go_term_enabled')
if go#config#TermEnabled()
let disabled_term = 1
let g:go_term_enabled = 0
call go#config#SetTermEnabled(0)
endif
let id = call('go#test#Test', args)
if disabled_term
let g:go_term_enabled = 1
call go#config#SetTermEnabled(1)
endif
if has('nvim')
@ -106,7 +106,7 @@ function! go#coverage#Browser(bang, ...) abort
let l:tmpname = tempname()
if go#util#has_job()
call s:coverage_job({
\ 'cmd': ['go', 'test', '-coverprofile', l:tmpname],
\ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname],
\ 'complete': function('s:coverage_browser_callback', [l:tmpname]),
\ 'bang': a:bang,
\ 'for': 'GoTest',
@ -126,10 +126,8 @@ function! go#coverage#Browser(bang, ...) abort
return
endif
if go#util#ShellError() == 0
let openHTML = 'go tool cover -html='.l:tmpname
call go#tool#ExecuteInDir(openHTML)
call go#tool#ExecuteInDir(['go', 'tool', 'cover', '-html=' . l:tmpname])
endif
call delete(l:tmpname)
@ -332,8 +330,7 @@ endfunction
function! s:coverage_browser_callback(coverfile, job, exit_status, data)
if a:exit_status == 0
let openHTML = 'go tool cover -html='.a:coverfile
call go#tool#ExecuteInDir(openHTML)
call go#tool#ExecuteInDir(['go', 'tool', 'cover', '-html=' . a:coverfile])
endif
call delete(a:coverfile)
@ -366,8 +363,7 @@ function! s:coverage_browser_handler(job, exit_status, data) abort
let l:tmpname = s:coverage_browser_handler_jobs[a:job.id]
if a:exit_status == 0
let openHTML = 'go tool cover -html='.l:tmpname
call go#tool#ExecuteInDir(openHTML)
call go#tool#ExecuteInDir(['go', 'tool', 'cover', '-html=' . l:tmpname])
endif
call delete(l:tmpname)

View File

@ -1,17 +1,5 @@
scriptencoding utf-8
if !exists('g:go_debug_windows')
let g:go_debug_windows = {
\ 'stack': 'leftabove 20vnew',
\ 'out': 'botright 10new',
\ 'vars': 'leftabove 30vnew',
\ }
endif
if !exists('g:go_debug_address')
let g:go_debug_address = '127.0.0.1:8181'
endif
if !exists('s:state')
let s:state = {
\ 'rpcid': 1,
@ -25,7 +13,7 @@ if !exists('s:state')
\}
if go#util#HasDebug('debugger-state')
let g:go_debug_diag = s:state
call go#config#SetDebugDiag(s:state)
endif
endif
@ -71,9 +59,6 @@ endfunction
function! s:call_jsonrpc(method, ...) abort
if go#util#HasDebug('debugger-commands')
if !exists('g:go_debug_commands')
let g:go_debug_commands = []
endif
echom 'sending to dlv ' . a:method
endif
@ -274,6 +259,11 @@ function! go#debug#Stop() abort
set noballooneval
set balloonexpr=
augroup vim-go-debug
autocmd!
augroup END
augroup! vim-go-debug
endfunction
function! s:goto_file() abort
@ -416,8 +406,9 @@ function! s:start_cb(ch, json) abort
return
endif
if exists('g:go_debug_windows["stack"]') && g:go_debug_windows['stack'] != ''
exe 'silent ' . g:go_debug_windows['stack']
let debugwindows = go#config#DebugWindows()
if has_key(debugwindows, "stack") && debugwindows['stack'] != ''
exe 'silent ' . debugwindows['stack']
silent file `='__GODEBUG_STACKTRACE__'`
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
setlocal filetype=godebugstacktrace
@ -425,16 +416,16 @@ function! s:start_cb(ch, json) abort
nmap <buffer> q <Plug>(go-debug-stop)
endif
if exists('g:go_debug_windows["out"]') && g:go_debug_windows['out'] != ''
exe 'silent ' . g:go_debug_windows['out']
if has_key(debugwindows, "out") && debugwindows['out'] != ''
exe 'silent ' . debugwindows['out']
silent file `='__GODEBUG_OUTPUT__'`
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
setlocal filetype=godebugoutput
nmap <buffer> q <Plug>(go-debug-stop)
endif
if exists('g:go_debug_windows["vars"]') && g:go_debug_windows['vars'] != ''
exe 'silent ' . g:go_debug_windows['vars']
if has_key(debugwindows, "vars") && debugwindows['vars'] != ''
exe 'silent ' . debugwindows['vars']
silent file `='__GODEBUG_VARIABLES__'`
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
setlocal filetype=godebugvariables
@ -462,16 +453,20 @@ function! s:start_cb(ch, json) abort
nnoremap <silent> <Plug>(go-debug-stop) :<C-u>call go#debug#Stop()<CR>
nnoremap <silent> <Plug>(go-debug-print) :<C-u>call go#debug#Print(expand('<cword>'))<CR>
nmap <F5> <Plug>(go-debug-continue)
nmap <F6> <Plug>(go-debug-print)
nmap <F9> <Plug>(go-debug-breakpoint)
nmap <F10> <Plug>(go-debug-next)
nmap <F11> <Plug>(go-debug-step)
set balloonexpr=go#debug#BalloonExpr()
set ballooneval
exe bufwinnr(oldbuf) 'wincmd w'
augroup vim-go-debug
autocmd!
autocmd FileType go nmap <buffer> <F5> <Plug>(go-debug-continue)
autocmd FileType go nmap <buffer> <F6> <Plug>(go-debug-print)
autocmd FileType go nmap <buffer> <F9> <Plug>(go-debug-breakpoint)
autocmd FileType go nmap <buffer> <F10> <Plug>(go-debug-next)
autocmd FileType go nmap <buffer> <F11> <Plug>(go-debug-step)
augroup END
doautocmd vim-go-debug FileType go
endfunction
function! s:err_cb(ch, msg) abort
@ -484,7 +479,7 @@ function! s:out_cb(ch, msg) abort
let s:state['message'] += [a:msg]
" TODO: why do this in this callback?
if stridx(a:msg, g:go_debug_address) != -1
if stridx(a:msg, go#config#DebugAddress()) != -1
call ch_setoptions(a:ch, {
\ 'out_cb': function('s:logger', ['OUT: ']),
\ 'err_cb': function('s:logger', ['ERR: ']),
@ -504,6 +499,8 @@ endfunction
" Start the debug mode. The first argument is the package name to compile and
" debug, anything else will be passed to the running program.
function! go#debug#Start(is_test, ...) abort
call go#cmd#autowrite()
if has('nvim')
call go#util#EchoError('This feature only works in Vim for now; Neovim is not (yet) supported. Sorry :-(')
return
@ -521,7 +518,7 @@ function! go#debug#Start(is_test, ...) abort
let s:start_args = a:000
if go#util#HasDebug('debugger-state')
let g:go_debug_diag = s:state
call go#config#SetDebugDiag(s:state)
endif
" cd in to test directory; this is also what running "go test" does.
@ -555,15 +552,18 @@ function! go#debug#Start(is_test, ...) abort
let l:cmd = [
\ dlv,
\ (a:is_test ? 'test' : 'debug'),
\ l:pkgname,
\ '--output', tempname(),
\ '--headless',
\ '--api-version', '2',
\ '--log',
\ '--listen', g:go_debug_address,
\ '--log', 'debugger',
\ '--listen', go#config#DebugAddress(),
\ '--accept-multiclient',
\]
if get(g:, 'go_build_tags', '') isnot ''
let l:cmd += ['--build-flags', '--tags=' . g:go_build_tags]
let buildtags = go#config#BuildTags()
if buildtags isnot ''
let l:cmd += ['--build-flags', '--tags=' . buildtags]
endif
let l:cmd += l:args
@ -800,6 +800,8 @@ function! go#debug#Stack(name) abort
endfunction
function! go#debug#Restart() abort
call go#cmd#autowrite()
try
call job_stop(s:state['job'])
while has_key(s:state, 'job') && job_status(s:state['job']) is# 'run'
@ -891,14 +893,4 @@ endfunction
sign define godebugbreakpoint text=> texthl=GoDebugBreakpoint
sign define godebugcurline text== linehl=GoDebugCurrent texthl=GoDebugCurrent
fun! s:hi()
hi GoDebugBreakpoint term=standout ctermbg=117 ctermfg=0 guibg=#BAD4F5 guifg=Black
hi GoDebugCurrent term=reverse ctermbg=12 ctermfg=7 guibg=DarkBlue guifg=White
endfun
augroup vim-go-breakpoint
autocmd!
autocmd ColorScheme * call s:hi()
augroup end
call s:hi()
" vim: sw=2 ts=2 et

View File

@ -1,11 +1,8 @@
if !exists('g:go_decls_mode')
let g:go_decls_mode = ''
endif
function! go#decls#Decls(mode, ...) abort
if g:go_decls_mode == 'ctrlp'
let decls_mode = go#config#DeclsMode()
if decls_mode == 'ctrlp'
call ctrlp#init(call("ctrlp#decls#cmd", [a:mode] + a:000))
elseif g:go_decls_mode == 'fzf'
elseif decls_mode == 'fzf'
call call("fzf#decls#cmd", [a:mode] + a:000)
else
if globpath(&rtp, 'plugin/ctrlp.vim') != ""

View File

@ -8,7 +8,7 @@ function! go#def#Jump(mode) abort
" godef which also has it's own quirks. But this issue come up so many
" times I've decided to support both. By default we still use guru as it
" covers all edge cases, but now anyone can switch to godef if they wish
let bin_name = get(g:, 'go_def_mode', 'guru')
let bin_name = go#config#DefMode()
if bin_name == 'godef'
if &modified
" Write current unsaved buffer to a temp file and use the modified content
@ -17,23 +17,16 @@ function! go#def#Jump(mode) abort
let fname = l:tmpname
endif
let bin_path = go#path#CheckBinPath("godef")
if empty(bin_path)
return
endif
let command = printf("%s -f=%s -o=%s -t", go#util#Shellescape(bin_path),
\ go#util#Shellescape(fname), go#util#OffsetCursor())
let out = go#util#System(command)
let [l:out, l:err] = go#util#Exec(['godef',
\ '-f=' . l:fname,
\ '-o=' . go#util#OffsetCursor(),
\ '-t'])
if exists("l:tmpname")
call delete(l:tmpname)
endif
elseif bin_name == 'guru'
let bin_path = go#path#CheckBinPath("guru")
if empty(bin_path)
return
endif
let cmd = [bin_path]
elseif bin_name == 'guru'
let cmd = [bin_name, '-tags', go#config#BuildTags()]
let stdin_content = ""
if &modified
@ -42,13 +35,7 @@ function! go#def#Jump(mode) abort
call add(cmd, "-modified")
endif
if exists('g:go_build_tags')
let tags = get(g:, 'go_build_tags')
call extend(cmd, ["-tags", tags])
endif
let fname = fname.':#'.go#util#OffsetCursor()
call extend(cmd, ["definition", fname])
call extend(cmd, ["definition", fname . ':#' . go#util#OffsetCursor()])
if go#util#has_job()
let l:spawn_args = {
@ -66,18 +53,17 @@ function! go#def#Jump(mode) abort
return
endif
let command = join(cmd, " ")
if &modified
let out = go#util#System(command, stdin_content)
let [l:out, l:err] = go#util#Exec(l:cmd, stdin_content)
else
let out = go#util#System(command)
let [l:out, l:err] = go#util#Exec(l:cmd)
endif
else
call go#util#EchoError('go_def_mode value: '. bin_name .' is not valid. Valid values are: [godef, guru]')
return
endif
if go#util#ShellError() != 0
if l:err
call go#util#EchoError(out)
return
endif
@ -138,7 +124,7 @@ function! go#def#jump_to_declaration(out, mode, bin_name) abort
if filename != fnamemodify(expand("%"), ':p:gs?\\?/?')
" jump to existing buffer if, 1. we have enabled it, 2. the buffer is loaded
" and 3. there is buffer window number we switch to
if get(g:, 'go_def_reuse_buffer', 0) && bufloaded(filename) != 0 && bufwinnr(filename) != -1
if go#config#DefReuseBuffer() && bufloaded(filename) != 0 && bufwinnr(filename) != -1
" jumpt to existing buffer if it exists
execute bufwinnr(filename) . 'wincmd w'
else

View File

@ -4,18 +4,14 @@
let s:buf_nr = -1
if !exists("g:go_doc_command")
let g:go_doc_command = ["godoc"]
endif
function! go#doc#OpenBrowser(...) abort
" check if we have gogetdoc as it gives us more and accurate information.
" Only supported if we have json_decode as it's not worth to parse the plain
" non-json output of gogetdoc
let bin_path = go#path#CheckBinPath('gogetdoc')
if !empty(bin_path) && exists('*json_decode')
let json_out = s:gogetdoc(1)
if go#util#ShellError() != 0
let [l:json_out, l:err] = s:gogetdoc(1)
if l:err
call go#util#EchoError(json_out)
return
endif
@ -29,14 +25,12 @@ function! go#doc#OpenBrowser(...) abort
let name = out["name"]
let decl = out["decl"]
let godoc_url = s:custom_godoc_url()
let godoc_url = go#config#DocUrl()
let godoc_url .= "/" . import
if decl !~ "^package"
let godoc_url .= "#" . name
endif
echo godoc_url
call go#tool#OpenBrowser(godoc_url)
return
endif
@ -50,28 +44,27 @@ function! go#doc#OpenBrowser(...) abort
let exported_name = pkgs[1]
" example url: https://godoc.org/github.com/fatih/set#Set
let godoc_url = s:custom_godoc_url() . "/" . pkg . "#" . exported_name
let godoc_url = go#config#DocUrl() . "/" . pkg . "#" . exported_name
call go#tool#OpenBrowser(godoc_url)
endfunction
function! go#doc#Open(newmode, mode, ...) abort
" With argument: run "godoc [arg]".
if len(a:000)
if empty(go#path#CheckBinPath(g:go_doc_command[0]))
if empty(go#path#CheckBinPath(go#config#DocCommand()[0]))
return
endif
let command = printf("%s %s", go#util#Shelljoin(g:go_doc_command), join(a:000, ' '))
let out = go#util#System(command)
let [l:out, l:err] = go#util#Exec(go#config#DocCommand() + a:000)
" Without argument: run gogetdoc on cursor position.
else
let out = s:gogetdoc(0)
let [l:out, l:err] = s:gogetdoc(0)
if out == -1
return
endif
endif
if go#util#ShellError() != 0
if l:err
call go#util#EchoError(out)
return
endif
@ -97,7 +90,7 @@ function! s:GodocView(newposition, position, content) abort
if !is_visible
if a:position == "split"
" cap window height to 20, but resize it for smaller contents
let max_height = get(g:, "go_doc_max_height", 20)
let max_height = go#config#DocMaxHeight()
let content_height = len(split(a:content, "\n"))
if content_height > max_height
exe 'resize ' . max_height
@ -135,33 +128,20 @@ function! s:GodocView(newposition, position, content) abort
endfunction
function! s:gogetdoc(json) abort
" check if we have 'gogetdoc' and use it automatically
let bin_path = go#path#CheckBinPath('gogetdoc')
if empty(bin_path)
return -1
endif
let cmd = [go#util#Shellescape(bin_path)]
let offset = go#util#OffsetCursor()
let fname = expand("%:p:gs!\\!/!")
let pos = shellescape(fname.':#'.offset)
let cmd += ["-pos", pos]
let l:cmd = [
\ 'gogetdoc',
\ '-tags', go#config#BuildTags(),
\ '-pos', expand("%:p:gs!\\!/!") . ':#' . go#util#OffsetCursor()]
if a:json
let cmd += ["-json"]
let l:cmd += ['-json']
endif
let command = join(cmd, " ")
if &modified
let command .= " -modified"
let out = go#util#System(command, go#util#archive())
else
let out = go#util#System(command)
let l:cmd += ['-modified']
return go#util#Exec(l:cmd, go#util#archive())
endif
return out
return go#util#Exec(l:cmd)
endfunction
" returns the package and exported name. exported name might be empty.
@ -206,18 +186,4 @@ function! s:godocWord(args) abort
return [pkg, exported_name]
endfunction
function! s:custom_godoc_url() abort
let godoc_url = get(g:, 'go_doc_url', 'https://godoc.org')
if godoc_url isnot 'https://godoc.org'
" strip last '/' character if available
let last_char = strlen(godoc_url) - 1
if godoc_url[last_char] == '/'
let godoc_url = strpart(godoc_url, 0, last_char)
endif
" custom godoc installations expect /pkg before package names
let godoc_url .= "/pkg"
endif
return godoc_url
endfunction
" vim: sw=2 ts=2 et

View File

@ -3,6 +3,8 @@ function! go#fillstruct#FillStruct() abort
\ '-file', bufname(''),
\ '-offset', go#util#OffsetCursor(),
\ '-line', line('.')]
" Needs: https://github.com/davidrjenni/reftools/pull/14
"\ '-tags', go#config#BuildTags()]
" Read from stdin if modified.
if &modified

View File

@ -5,22 +5,6 @@
" fmt.vim: Vim command to format Go files with gofmt (and gofmt compatible
" toorls, such as goimports).
if !exists("g:go_fmt_command")
let g:go_fmt_command = "gofmt"
endif
if !exists('g:go_fmt_options')
let g:go_fmt_options = ''
endif
if !exists('g:go_fmt_fail_silently')
let g:go_fmt_fail_silently = 0
endif
if !exists("g:go_fmt_experimental")
let g:go_fmt_experimental = 0
endif
" we have those problems :
" http://stackoverflow.com/questions/12741977/prevent-vim-from-updating-its-undo-tree
" http://stackoverflow.com/questions/18532692/golang-formatter-and-vim-how-to-destroy-history-record?rq=1
@ -30,7 +14,7 @@ endif
" this and have VimL experience, please look at the function for
" improvements, patches are welcome :)
function! go#fmt#Format(withGoimport) abort
if g:go_fmt_experimental == 1
if go#config#FmtExperimental()
" Using winsaveview to save/restore cursor state has the problem of
" closing folds on save:
" https://github.com/fatih/vim-go/issues/502
@ -64,18 +48,18 @@ function! go#fmt#Format(withGoimport) abort
let l:tmpname = tr(l:tmpname, '\', '/')
endif
let bin_name = g:go_fmt_command
let bin_name = go#config#FmtCommand()
if a:withGoimport == 1
let bin_name = "goimports"
endif
let current_col = col('.')
let out = go#fmt#run(bin_name, l:tmpname, expand('%'))
let [l:out, l:err] = go#fmt#run(bin_name, l:tmpname, expand('%'))
let diff_offset = len(readfile(l:tmpname)) - line('$')
if go#util#ShellError() == 0
if l:err == 0
call go#fmt#update_file(l:tmpname, expand('%'))
elseif g:go_fmt_fail_silently == 0
elseif !go#config#FmtFailSilently()
let errors = s:parse_errors(expand('%'), out)
call s:show_errors(errors)
endif
@ -83,7 +67,7 @@ function! go#fmt#Format(withGoimport) abort
" We didn't use the temp file, so clean up
call delete(l:tmpname)
if g:go_fmt_experimental == 1
if go#config#FmtExperimental()
" restore our undo history
silent! exe 'rundo ' . tmpundofile
call delete(tmpundofile)
@ -154,64 +138,27 @@ endfunction
" run runs the gofmt/goimport command for the given source file and returns
" the output of the executed command. Target is the real file to be formatted.
function! go#fmt#run(bin_name, source, target)
let cmd = s:fmt_cmd(a:bin_name, a:source, a:target)
if empty(cmd)
let l:cmd = s:fmt_cmd(a:bin_name, a:source, a:target)
if empty(l:cmd)
return
endif
let command = join(cmd, " ")
" execute our command...
let out = go#util#System(command)
return out
return go#util#Exec(l:cmd)
endfunction
" fmt_cmd returns a dict that contains the command to execute gofmt (or
" goimports). args is dict with
" fmt_cmd returns the command to run as a list.
function! s:fmt_cmd(bin_name, source, target)
" check if the user has installed command binary.
" For example if it's goimports, let us check if it's installed,
" if not the user get's a warning via go#path#CheckBinPath()
let bin_path = go#path#CheckBinPath(a:bin_name)
if empty(bin_path)
return []
endif
" start constructing the command
let bin_path = go#util#Shellescape(bin_path)
let cmd = [bin_path]
call add(cmd, "-w")
let l:cmd = [a:bin_name, '-w']
" add the options for binary (if any). go_fmt_options was by default of type
" string, however to allow customization it's now a dictionary of binary
" name mapping to options.
let opts = g:go_fmt_options
if type(g:go_fmt_options) == type({})
let opts = has_key(g:go_fmt_options, a:bin_name) ? g:go_fmt_options[a:bin_name] : ""
let opts = go#config#FmtOptions()
if type(opts) == type({})
let opts = has_key(opts, a:bin_name) ? opts[a:bin_name] : ""
endif
call extend(cmd, split(opts, " "))
if a:bin_name == "goimports"
" lazy check if goimports support `-srcdir`. We should eventually remove
" this in the future
if !exists('b:goimports_vendor_compatible')
let out = go#util#System(bin_path . " --help")
if out !~ "-srcdir"
call go#util#EchoWarning(printf("vim-go: goimports (%s) does not support srcdir. Update with: :GoUpdateBinaries", bin_path))
else
let b:goimports_vendor_compatible = 1
endif
endif
if exists('b:goimports_vendor_compatible') && b:goimports_vendor_compatible
let ssl_save = &shellslash
set noshellslash
" use the filename without the fully qualified name if the tree is
" symlinked into the GOPATH, goimports won't work properly.
call extend(cmd, ["-srcdir", shellescape(a:target)])
let &shellslash = ssl_save
endif
if a:bin_name is# 'goimports'
call extend(cmd, ["-srcdir", a:target])
endif
call add(cmd, a:source)
@ -254,13 +201,13 @@ function! s:show_errors(errors) abort
endfunction
function! go#fmt#ToggleFmtAutoSave() abort
if get(g:, "go_fmt_autosave", 1)
let g:go_fmt_autosave = 0
if go#config#FmtAutosave()
call go#config#SetFmtAutosave(0)
call go#util#EchoProgress("auto fmt disabled")
return
end
let g:go_fmt_autosave = 1
call go#config#SetFmtAutosave(1)
call go#util#EchoProgress("auto fmt enabled")
endfunction

View File

@ -16,12 +16,6 @@ function! s:guru_cmd(args) range abort
let selected = a:args.selected
let result = {}
let pkg = go#package#ImportPath()
" this is important, check it!
if pkg == -1 && needs_scope
return {'err': "current directory is not inside of a valid GOPATH"}
endif
"return with a warning if the binary doesn't exist
let bin_path = go#path#CheckBinPath("guru")
@ -30,9 +24,8 @@ function! s:guru_cmd(args) range abort
endif
" start constructing the command
let cmd = [bin_path]
let cmd = [bin_path, '-tags', go#config#BuildTags()]
let filename = fnamemodify(expand("%"), ':p:gs?\\?/?')
if &modified
let result.stdin_content = go#util#archive()
call add(cmd, "-modified")
@ -43,44 +36,22 @@ function! s:guru_cmd(args) range abort
call add(cmd, "-json")
endif
" check for any tags
if exists('g:go_build_tags')
let tags = get(g:, 'go_build_tags')
call extend(cmd, ["-tags", tags])
let result.tags = tags
endif
" some modes require scope to be defined (such as callers). For these we
" choose a sensible setting, which is using the current file's package
let scopes = []
if needs_scope
let scopes = [pkg]
endif
" check for any user defined scope setting. users can define the scope,
" in package pattern form. examples:
" golang.org/x/tools/cmd/guru # a single package
" golang.org/x/tools/... # all packages beneath dir
" ... # the entire workspace.
if exists('g:go_guru_scope')
" check that the setting is of type list
if type(get(g:, 'go_guru_scope')) != type([])
return {'err' : "go_guru_scope should of type list"}
let scopes = go#config#GuruScope()
if empty(scopes)
" some modes require scope to be defined (such as callers). For these we
" choose a sensible setting, which is using the current file's package
if needs_scope
let pkg = go#package#ImportPath()
if pkg == -1
return {'err': "current directory is not inside of a valid GOPATH"}
endif
let scopes = [pkg]
endif
let scopes = get(g:, 'go_guru_scope')
endif
" now add the scope to our command if there is any
" Add the scope.
if !empty(scopes)
" strip trailing slashes for each path in scoped. bug:
" https://github.com/golang/go/issues/14584
let scopes = go#util#StripTrailingSlash(scopes)
" create shell-safe entries of the list
if !has("nvim") && !go#util#has_job() | let scopes = go#util#Shelllist(scopes) | endif
" guru expect a comma-separated list of patterns, construct it
" guru expect a comma-separated list of patterns.
let l:scope = join(scopes, ",")
let result.scope = l:scope
call extend(cmd, ["-scope", l:scope])
@ -94,8 +65,8 @@ function! s:guru_cmd(args) range abort
let pos = printf("#%s,#%s", pos1, pos2)
endif
let filename .= ':'.pos
call extend(cmd, [mode, filename])
let l:filename = fnamemodify(expand("%"), ':p:gs?\\?/?') . ':' . pos
call extend(cmd, [mode, l:filename])
let result.cmd = cmd
return result
@ -119,22 +90,20 @@ function! s:sync_guru(args) abort
endif
endif
" run, forrest run!!!
let command = join(result.cmd, " ")
if has_key(result, 'stdin_content')
let out = go#util#System(command, result.stdin_content)
if has_key(l:result, 'stdin_content')
let [l:out, l:err] = go#util#Exec(l:result.cmd, l:result.stdin_content)
else
let out = go#util#System(command)
let [l:out, l:err] = go#util#Exec(l:result.cmd)
endif
if has_key(a:args, 'custom_parse')
call a:args.custom_parse(go#util#ShellError(), out, a:args.mode)
call a:args.custom_parse(l:err, l:out, a:args.mode)
else
call s:parse_guru_output(go#util#ShellError(), out, a:args.mode)
call s:parse_guru_output(l:err, l:out, a:args.mode)
endif
return out
return l:out
endfunc
" use vim or neovim job api as appropriate
@ -144,12 +113,43 @@ function! s:job_start(cmd, start_options) abort
endif
let opts = {'stdout_buffered': v:true, 'stderr_buffered': v:true}
let stdout_buf = ""
function opts.on_stdout(job_id, data, event) closure
call a:start_options.callback(a:job_id, join(a:data, "\n"))
let l:data = a:data
let l:data[0] = stdout_buf . l:data[0]
let stdout_buf = ""
if l:data[-1] != ""
let stdout_buf = l:data[-1]
endif
let l:data = l:data[:-2]
if len(l:data) == 0
return
endif
call a:start_options.callback(a:job_id, join(l:data, "\n"))
endfunction
let stderr_buf = ""
function opts.on_stderr(job_id, data, event) closure
call a:start_options.callback(a:job_id, join(a:data, "\n"))
let l:data = a:data
let l:data[0] = stderr_buf . l:data[0]
let stderr_buf = ""
if l:data[-1] != ""
let stderr_buf = l:data[-1]
endif
let l:data = l:data[:-2]
if len(l:data) == 0
return
endif
call a:start_options.callback(a:job_id, join(l:data, "\n"))
endfunction
function opts.on_exit(job_id, exit_code, event) closure
call a:start_options.exit_cb(a:job_id, a:exit_code)
call a:start_options.close_cb(a:job_id)
@ -158,7 +158,7 @@ function! s:job_start(cmd, start_options) abort
" use a shell for input redirection if needed
let cmd = a:cmd
if has_key(a:start_options, 'in_io') && a:start_options.in_io ==# 'file' && !empty(a:start_options.in_name)
let cmd = ['/bin/sh', '-c', join(a:cmd, ' ') . ' <' . a:start_options.in_name]
let cmd = ['/bin/sh', '-c', go#util#Shelljoin(a:cmd) . ' <' . a:start_options.in_name]
endif
return jobstart(cmd, opts)
@ -172,7 +172,6 @@ function! s:async_guru(args) abort
return
endif
if !has_key(a:args, 'disable_progress')
if a:args.needs_scope
call go#util#EchoProgress("analysing with scope " . result.scope .
@ -278,6 +277,18 @@ function! go#guru#Implements(selected) abort
call s:run_guru(args)
endfunction
" Shows the set of possible objects to which a pointer may point.
function! go#guru#PointsTo(selected) abort
let l:args = {
\ 'mode': 'pointsto',
\ 'format': 'plain',
\ 'selected': a:selected,
\ 'needs_scope': 1,
\ }
call s:run_guru(l:args)
endfunction
" Report the possible constants, global variables, and concrete types that may
" appear in a value of type error
function! go#guru#Whicherrs(selected) abort
@ -524,20 +535,20 @@ function! s:same_ids_highlight(exit_val, output, mode) abort
call go#guru#ClearSameIds() " run after calling guru to reduce flicker.
if a:output[0] !=# '{'
if !get(g:, 'go_auto_sameids', 0)
if !go#config#AutoSameids()
call go#util#EchoError(a:output)
endif
return
endif
let result = json_decode(a:output)
if type(result) != type({}) && !get(g:, 'go_auto_sameids', 0)
if type(result) != type({}) && !go#config#AutoSameids()
call go#util#EchoError("malformed output from guru")
return
endif
if !has_key(result, 'sameids')
if !get(g:, 'go_auto_sameids', 0)
if !go#config#AutoSameids()
call go#util#EchoError("no same_ids founds for the given identifier")
endif
return
@ -563,7 +574,7 @@ function! s:same_ids_highlight(exit_val, output, mode) abort
call matchaddpos('goSameId', [[str2nr(pos[-2]), str2nr(pos[-1]), str2nr(poslen)]])
endfor
if get(g:, "go_auto_sameids", 0)
if go#config#AutoSameids()
" re-apply SameIds at the current cursor position at the time the buffer
" is redisplayed: e.g. :edit, :GoRename, etc.
augroup vim-go-sameids
@ -605,15 +616,15 @@ function! go#guru#ToggleSameIds() abort
endfunction
function! go#guru#AutoToogleSameIds() abort
if get(g:, "go_auto_sameids", 0)
if go#config#AutoSameids()
call go#util#EchoProgress("sameids auto highlighting disabled")
call go#guru#ClearSameIds()
let g:go_auto_sameids = 0
call go#config#SetAutoSameids(0)
return
endif
call go#util#EchoSuccess("sameids auto highlighting enabled")
let g:go_auto_sameids = 1
call go#config#SetAutoSameids(1)
endfunction
@ -648,21 +659,26 @@ endfun
function! go#guru#Scope(...) abort
if a:0
let scope = a:000
if a:0 == 1 && a:1 == '""'
unlet g:go_guru_scope
let scope = []
endif
call go#config#SetGuruScope(scope)
if empty(scope)
call go#util#EchoSuccess("guru scope is cleared")
else
let g:go_guru_scope = a:000
call go#util#EchoSuccess("guru scope changed to: ". join(a:000, ","))
endif
return
endif
if !exists('g:go_guru_scope')
let scope = go#config#GuruScope()
if empty(scope)
call go#util#EchoError("guru scope is not set")
else
call go#util#EchoSuccess("current guru scope: ". join(g:go_guru_scope, ","))
call go#util#EchoSuccess("current guru scope: ". join(scope, ","))
endif
endfunction

View File

@ -0,0 +1,15 @@
function Test_GuruScope_Set() abort
silent call go#guru#Scope("example.com/foo/bar")
let actual = go#config#GuruScope()
call assert_equal(["example.com/foo/bar"], actual)
silent call go#guru#Scope('""')
silent let actual = go#config#GuruScope()
call assert_equal([], actual, "setting scope to empty string should clear")
if exists('g:go_guru_scope')
unlet g:go_guru_scope
endif
endfunction
" vim: sw=2 ts=2 et

View File

@ -27,8 +27,8 @@ function! go#import#SwitchImport(enabled, localname, path, bang) abort
endif
if a:bang == "!"
let out = go#util#System("go get -u -v ".shellescape(path))
if go#util#ShellError() != 0
let [l:out, l:err] = go#util#Exec(['go', 'get', '-u', '-v', path])
if err != 0
call s:Error("Can't find import: " . path . ":" . out)
endif
endif

View File

@ -0,0 +1,34 @@
let s:templatepath = go#util#Join(expand('<sfile>:p:h:h:h'), '.github', 'ISSUE_TEMPLATE.md')
function! go#issue#New() abort
let body = substitute(s:issuebody(), '[^A-Za-z0-9_.~-]', '\="%".printf("%02X",char2nr(submatch(0)))', 'g')
let url = "https://github.com/fatih/vim-go/issues/new?body=" . l:body
call go#tool#OpenBrowser(l:url)
endfunction
function! s:issuebody() abort
let lines = readfile(s:templatepath)
let rtrimpat = '[[:space:]]\+$'
let body = []
for l in lines
let body = add(body, l)
if l =~ '^\* Vim version'
redir => out
silent version
redir END
let body = extend(body, split(out, "\n")[0:2])
elseif l =~ '^\* Go version'
let [out, err] = go#util#Exec(['go', 'version'])
let body = add(body, substitute(l:out, rtrimpat, '', ''))
elseif l =~ '^\* Go environment'
let [out, err] = go#util#Exec(['go', 'env'])
let body = add(body, substitute(l:out, rtrimpat, '', ''))
endif
endfor
return join(body, "\n")
endfunction
" vim: sw=2 ts=2 et

View File

@ -33,7 +33,7 @@
function go#job#Spawn(args)
let cbs = {}
let state = {
\ 'winnr': winnr(),
\ 'winid': win_getid(winnr()),
\ 'dir': getcwd(),
\ 'jobdir': fnameescape(expand("%:p:h")),
\ 'messages': [],
@ -73,7 +73,7 @@ function go#job#Spawn(args)
let self.exit_status = a:exitval
let self.exited = 1
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
if a:exitval == 0
call go#util#EchoSuccess("SUCCESS")
else
@ -104,15 +104,20 @@ function go#job#Spawn(args)
let cbs.close_cb = function('s:close_cb', [], state)
function state.show_errors(job, exit_status, data)
let l:winid = win_getid(winnr())
call win_gotoid(self.winid)
let l:listtype = go#list#Type(self.for)
if a:exit_status == 0
call go#list#Clean(l:listtype)
call win_gotoid(l:winid)
return
endif
let l:listtype = go#list#Type(self.for)
if len(a:data) == 0
call go#list#Clean(l:listtype)
call win_gotoid(l:winid)
return
endif
@ -132,10 +137,11 @@ function go#job#Spawn(args)
if empty(errors)
" failed to parse errors, output the original content
call go#util#EchoError(self.messages + [self.dir])
call win_gotoid(l:winid)
return
endif
if self.winnr == winnr()
if self.winid == l:winid
call go#list#Window(l:listtype, len(errors))
if !self.bang
call go#list#JumpToFirst(l:listtype)

View File

@ -50,7 +50,7 @@ function! s:spawn(bang, desc, for, args) abort
let job = {
\ 'desc': a:desc,
\ 'bang': a:bang,
\ 'winnr': winnr(),
\ 'winid': win_getid(winnr()),
\ 'importpath': go#package#ImportPath(),
\ 'state': "RUNNING",
\ 'stderr' : [],
@ -98,6 +98,9 @@ endfunction
" on_stderr handler. If there are no errors and a quickfix window is open,
" it'll be closed.
function! s:on_exit(job_id, exit_status, event) dict abort
let l:winid = win_getid(winnr())
call win_gotoid(self.winid)
let status = {
\ 'desc': 'last status',
\ 'type': self.status_type,
@ -129,17 +132,18 @@ function! s:on_exit(job_id, exit_status, event) dict abort
let self.state = "SUCCESS"
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
call go#util#EchoSuccess("[" . self.status_type . "] SUCCESS")
endif
execute cd . fnameescape(dir)
call win_gotoid(l:winid)
return
endif
let self.state = "FAILED"
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
call go#util#EchoError("[" . self.status_type . "] FAILED")
endif
@ -152,11 +156,12 @@ function! s:on_exit(job_id, exit_status, event) dict abort
if !len(errors)
" failed to parse errors, output the original content
call go#util#EchoError(std_combined[0])
call win_gotoid(l:winid)
return
endif
" if we are still in the same windows show the list
if self.winnr == winnr()
if self.winid == l:winid
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !self.bang
call go#list#JumpToFirst(l:listtype)

View File

@ -1,20 +1,20 @@
function! go#keyify#Keyify()
let bin_path = go#path#CheckBinPath("keyify")
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
" Needs: https://github.com/dominikh/go-tools/pull/272
"\ '-tags', go#config#BuildTags(),
let l:cmd = ['keyify',
\ '-json',
\ printf('%s:#%s', fnamemodify(expand('%'), ':p:gs?\\?/?'), go#util#OffsetCursor())]
if empty(bin_path) || !exists('*json_decode')
let [l:out, l:err] = go#util#Exec(l:cmd)
if l:err
call go#util#EchoError("non-zero exit code: " . l:out)
return
endif
" Get result of command as json, that contains `start`, `end` and `replacement`
let command = printf("%s -json %s:#%s", go#util#Shellescape(bin_path),
\ go#util#Shellescape(fname), go#util#OffsetCursor())
let output = go#util#System(command)
silent! let result = json_decode(output)
silent! let result = json_decode(l:out)
" We want to output the error message in case the result isn't a JSON
if type(result) != type({})
call go#util#EchoError(s:chomp(output))
call go#util#EchoError(s:chomp(l:out))
return
endif

View File

@ -1,27 +1,3 @@
if !exists("g:go_metalinter_command")
let g:go_metalinter_command = ""
endif
if !exists("g:go_metalinter_autosave_enabled")
let g:go_metalinter_autosave_enabled = ['vet', 'golint']
endif
if !exists("g:go_metalinter_enabled")
let g:go_metalinter_enabled = ['vet', 'golint', 'errcheck']
endif
if !exists("g:go_metalinter_disabled")
let g:go_metalinter_disabled = []
endif
if !exists("g:go_golint_bin")
let g:go_golint_bin = "golint"
endif
if !exists("g:go_errcheck_bin")
let g:go_errcheck_bin = "errcheck"
endif
function! go#lint#Gometa(autosave, ...) abort
if a:0 == 0
let goargs = [expand('%:p:h')]
@ -37,14 +13,14 @@ function! go#lint#Gometa(autosave, ...) abort
let cmd = [bin_path]
let cmd += ["--disable-all"]
if a:autosave || empty(g:go_metalinter_command)
if a:autosave || empty(go#config#MetalinterCommand())
" linters
let linters = a:autosave ? g:go_metalinter_autosave_enabled : g:go_metalinter_enabled
let linters = a:autosave ? go#config#MetalinterAutosaveEnabled() : go#config#MetalinterEnabled()
for linter in linters
let cmd += ["--enable=".linter]
endfor
for linter in g:go_metalinter_disabled
for linter in go#config#MetalinterDisabled()
let cmd += ["--disable=".linter]
endfor
@ -56,7 +32,7 @@ function! go#lint#Gometa(autosave, ...) abort
let cmd += ["--tests"]
else
" the user wants something else, let us use it.
let cmd += split(g:go_metalinter_command, " ")
let cmd += split(go#config#MetalinterCommand(), " ")
endif
if a:autosave
@ -68,33 +44,19 @@ function! go#lint#Gometa(autosave, ...) abort
let cmd += [printf('--include=^%s:.*$', fnamemodify(expand('%:p'), ":."))]
endif
" gometalinter has a default deadline of 5 seconds.
"
" For async mode (s:lint_job), we want to override the default deadline only
" if we have a deadline configured.
"
" For sync mode (go#util#System), always explicitly pass the 5 seconds
" deadline if there is no other deadline configured. If a deadline is
" configured, then use it.
" Call gometalinter asynchronously.
let deadline = go#config#MetalinterDeadline()
if deadline != ''
let cmd += ["--deadline=" . deadline]
endif
let cmd += goargs
if go#util#has_job() && has('lambda')
let deadline = get(g:, 'go_metalinter_deadline', 0)
if deadline != 0
let cmd += ["--deadline=" . deadline]
endif
let cmd += goargs
call s:lint_job({'cmd': cmd}, a:autosave)
return
endif
" We're calling gometalinter synchronously.
let cmd += ["--deadline=" . get(g:, 'go_metalinter_deadline', "5s")]
let cmd += goargs
let [l:out, l:err] = go#util#Exec(cmd)
if a:autosave
@ -128,27 +90,21 @@ endfunction
" Golint calls 'golint' on the current directory. Any warnings are populated in
" the location list
function! go#lint#Golint(...) abort
let bin_path = go#path#CheckBinPath(g:go_golint_bin)
if empty(bin_path)
return
endif
let bin_path = go#util#Shellescape(bin_path)
if a:0 == 0
let out = go#util#System(bin_path . " " . go#util#Shellescape(go#package#ImportPath()))
let [l:out, l:err] = go#util#Exec([go#config#GolintBin(), go#package#ImportPath()])
else
let out = go#util#System(bin_path . " " . go#util#Shelljoin(a:000))
let [l:out, l:err] = go#util#Exec([go#config#GolintBin()] + a:000)
endif
if empty(out)
echon "vim-go: " | echohl Function | echon "[lint] PASS" | echohl None
if empty(l:out)
call go#util#EchoSuccess('[lint] PASS')
return
endif
let l:listtype = go#list#Type("GoLint")
call go#list#Parse(l:listtype, out, "GoLint")
let errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(errors))
call go#list#Parse(l:listtype, l:out, "GoLint")
let l:errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(l:errors))
call go#list#JumpToFirst(l:listtype)
endfunction
@ -156,26 +112,28 @@ endfunction
" the location list
function! go#lint#Vet(bang, ...) abort
call go#cmd#autowrite()
echon "vim-go: " | echohl Identifier | echon "calling vet..." | echohl None
call go#util#EchoProgress('calling vet...')
if a:0 == 0
let out = go#util#System('go vet ' . go#util#Shellescape(go#package#ImportPath()))
let [l:out, l:err] = go#util#Exec(['go', 'vet', go#package#ImportPath()])
else
let out = go#util#System('go tool vet ' . go#util#Shelljoin(a:000))
let [l:out, l:err] = go#util#Exec(['go', 'tool', 'vet'] + a:000)
endif
let l:listtype = go#list#Type("GoVet")
if go#util#ShellError() != 0
let errorformat="%-Gexit status %\\d%\\+," . &errorformat
if l:err != 0
let errorformat = "%-Gexit status %\\d%\\+," . &errorformat
call go#list#ParseFormat(l:listtype, l:errorformat, out, "GoVet")
let errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:bang
call go#list#JumpToFirst(l:listtype)
endif
echon "vim-go: " | echohl ErrorMsg | echon "[vet] FAIL" | echohl None
call go#util#EchoError('[vet] FAIL')
else
call go#list#Clean(l:listtype)
redraw | echon "vim-go: " | echohl Function | echon "[vet] PASS" | echohl None
call go#util#EchoSuccess('[vet] PASS')
endif
endfunction
@ -183,42 +141,34 @@ endfunction
" the location list
function! go#lint#Errcheck(...) abort
if a:0 == 0
let import_path = go#package#ImportPath()
let l:import_path = go#package#ImportPath()
if import_path == -1
echohl Error | echomsg "vim-go: package is not inside GOPATH src" | echohl None
call go#util#EchoError('package is not inside GOPATH src')
return
endif
else
let import_path = go#util#Shelljoin(a:000)
let l:import_path = join(a:000, ' ')
endif
let bin_path = go#path#CheckBinPath(g:go_errcheck_bin)
if empty(bin_path)
return
endif
echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None
call go#util#EchoProgress('[errcheck] analysing ...')
redraw
let command = go#util#Shellescape(bin_path) . ' -abspath ' . import_path
let out = go#tool#ExecuteInDir(command)
let [l:out, l:err] = go#util#Exec([go#config#ErrcheckBin(), '-abspath', l:import_path])
let l:listtype = go#list#Type("GoErrCheck")
if go#util#ShellError() != 0
if l:err != 0
let errformat = "%f:%l:%c:\ %m, %f:%l:%c\ %#%m"
" Parse and populate our location list
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'Errcheck')
let errors = go#list#Get(l:listtype)
if empty(errors)
echohl Error | echomsg "GoErrCheck returned error" | echohl None
echo out
let l:errors = go#list#Get(l:listtype)
if empty(l:errors)
call go#util#EchoError(l:out)
return
endif
if !empty(errors)
echohl Error | echomsg "GoErrCheck found errors" | echohl None
call go#list#Populate(l:listtype, errors, 'Errcheck')
call go#list#Window(l:listtype, len(errors))
if !empty(errors)
@ -227,19 +177,18 @@ function! go#lint#Errcheck(...) abort
endif
else
call go#list#Clean(l:listtype)
echon "vim-go: " | echohl Function | echon "[errcheck] PASS" | echohl None
call go#util#EchoSuccess('[errcheck] PASS')
endif
endfunction
function! go#lint#ToggleMetaLinterAutoSave() abort
if get(g:, "go_metalinter_autosave", 0)
let g:go_metalinter_autosave = 0
if go#config#MetalinterAutosave()
call go#config#SetMetalinterAutosave(0)
call go#util#EchoProgress("auto metalinter disabled")
return
end
let g:go_metalinter_autosave = 1
call go#config#SetMetalinterAutosave(1)
call go#util#EchoProgress("auto metalinter enabled")
endfunction
@ -251,7 +200,7 @@ function! s:lint_job(args, autosave)
\ 'exited': 0,
\ 'closed': 0,
\ 'exit_status': 0,
\ 'winnr': winnr(),
\ 'winid': win_getid(winnr()),
\ 'autosave': a:autosave
\ }
@ -308,15 +257,14 @@ function! s:lint_job(args, autosave)
endif
endfunction
function state.show_errors()
let l:winnr = winnr()
let l:winid = win_getid(winnr())
" make sure the current window is the window from which gometalinter was
" run when the listtype is locationlist so that the location list for the
" correct window will be populated.
if self.listtype == 'locationlist'
exe self.winnr . "wincmd w"
call win_gotoid(self.winid)
endif
let l:errorformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m'
@ -331,10 +279,10 @@ function! s:lint_job(args, autosave)
" start of this function avoids the perception that the quickfix window
" steals focus when linting takes a while.
if self.autosave
exe l:winnr . "wincmd w"
call win_gotoid(self.winid)
endif
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
call go#util#EchoSuccess("linting finished")
endif
endfunction
@ -349,7 +297,7 @@ function! s:lint_job(args, autosave)
call job_start(a:args.cmd, start_options)
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
call go#util#EchoProgress("linting started ...")
endif
endfunction

View File

@ -12,11 +12,10 @@ func! Test_Gometa() abort
" call go#lint#ToggleMetaLinterAutoSave from lint.vim so that the file will
" be autoloaded and the default for g:go_metalinter_enabled will be set so
" we can capture it to restore it after the test is run.
call go#lint#ToggleMetaLinterAutoSave()
silent call go#lint#ToggleMetaLinterAutoSave()
" And restore it back to its previous value
call go#lint#ToggleMetaLinterAutoSave()
silent call go#lint#ToggleMetaLinterAutoSave()
let orig_go_metalinter_enabled = g:go_metalinter_enabled
let g:go_metalinter_enabled = ['golint']
call go#lint#Gometa(0, $GOPATH . '/src/foo')
@ -29,7 +28,7 @@ func! Test_Gometa() abort
endwhile
call gotest#assert_quickfix(actual, expected)
let g:go_metalinter_enabled = orig_go_metalinter_enabled
unlet g:go_metalinter_enabled
endfunc
func! Test_GometaWithDisabled() abort
@ -46,11 +45,10 @@ func! Test_GometaWithDisabled() abort
" call go#lint#ToggleMetaLinterAutoSave from lint.vim so that the file will
" be autoloaded and the default for g:go_metalinter_disabled will be set so
" we can capture it to restore it after the test is run.
call go#lint#ToggleMetaLinterAutoSave()
silent call go#lint#ToggleMetaLinterAutoSave()
" And restore it back to its previous value
call go#lint#ToggleMetaLinterAutoSave()
silent call go#lint#ToggleMetaLinterAutoSave()
let orig_go_metalinter_disabled = g:go_metalinter_disabled
let g:go_metalinter_disabled = ['vet']
call go#lint#Gometa(0, $GOPATH . '/src/foo')
@ -63,7 +61,7 @@ func! Test_GometaWithDisabled() abort
endwhile
call gotest#assert_quickfix(actual, expected)
let g:go_metalinter_disabled = orig_go_metalinter_disabled
unlet g:go_metalinter_disabled
endfunc
func! Test_GometaAutoSave() abort
@ -82,11 +80,10 @@ func! Test_GometaAutoSave() abort
" call go#lint#ToggleMetaLinterAutoSave from lint.vim so that the file will
" be autoloaded and the default for g:go_metalinter_autosave_enabled will be
" set so we can capture it to restore it after the test is run.
call go#lint#ToggleMetaLinterAutoSave()
silent call go#lint#ToggleMetaLinterAutoSave()
" And restore it back to its previous value
call go#lint#ToggleMetaLinterAutoSave()
silent call go#lint#ToggleMetaLinterAutoSave()
let orig_go_metalinter_autosave_enabled = g:go_metalinter_autosave_enabled
let g:go_metalinter_autosave_enabled = ['golint']
call go#lint#Gometa(1)
@ -99,7 +96,7 @@ func! Test_GometaAutoSave() abort
endwhile
call gotest#assert_quickfix(actual, expected)
let g:go_metalinter_autosave_enabled = orig_go_metalinter_autosave_enabled
unlet g:go_metalinter_autosave_enabled
endfunc
func! Test_Vet()
@ -108,7 +105,8 @@ func! Test_Vet()
compiler go
let expected = [
\ {'lnum': 7, 'bufnr': bufnr('%'), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'arg str for printf verb %d of wrong type: string'}
\ {'lnum': 7, 'bufnr': bufnr('%'), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '',
\ 'text': 'Printf format %d has arg str of wrong type string'}
\ ]
let winnr = winnr()

View File

@ -1,11 +1,3 @@
if !exists("g:go_list_type")
let g:go_list_type = ""
endif
if !exists("g:go_list_type_commands")
let g:go_list_type_commands = {}
endif
" Window opens the list with the given height up to 10 lines maximum.
" Otherwise g:go_loclist_height is used.
"
@ -22,7 +14,7 @@ function! go#list#Window(listtype, ...) abort
return
endif
let height = get(g:, "go_list_height", 0)
let height = go#config#ListHeight()
if height == 0
" prevent creating a large location height for a large set of numbers
if a:1 > 10
@ -113,7 +105,7 @@ endfunction
" Close closes the location list
function! go#list#Close(listtype) abort
let autoclose_window = get(g:, 'go_list_autoclose', 1)
let autoclose_window = go#config#ListAutoclose()
if !autoclose_window
return
endif
@ -126,13 +118,12 @@ function! go#list#Close(listtype) abort
endfunction
function! s:listtype(listtype) abort
if g:go_list_type == "locationlist"
return "locationlist"
elseif g:go_list_type == "quickfix"
return "quickfix"
let listtype = go#config#ListType()
if empty(listtype)
return a:listtype
endif
return a:listtype
return listtype
endfunction
" s:default_list_type_commands is the defaults that will be used for each of
@ -169,7 +160,7 @@ function! go#list#Type(for) abort
let l:listtype = "quickfix"
endif
return get(g:go_list_type_commands, a:for, l:listtype)
return get(go#config#ListTypeCommands(), a:for, l:listtype)
endfunction
" vim: sw=2 ts=2 et

View File

@ -62,8 +62,8 @@ function! go#package#ImportPath() abort
return s:import_paths[dir]
endif
let out = go#tool#ExecuteInDir("go list")
if go#util#ShellError() != 0
let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list'])
if l:err != 0
return -1
endif
@ -107,10 +107,11 @@ function! go#package#FromPath(arg) abort
endfunction
function! go#package#CompleteMembers(package, member) abort
silent! let content = go#util#System('godoc ' . a:package)
if go#util#ShellError() || !len(content)
let [l:content, l:err] = go#util#Exec(['godoc', a:package])
if l:err || !len(content)
return []
endif
let lines = filter(split(content, "\n"),"v:val !~ '^\\s\\+$'")
try
let mx1 = '^\s\+\(\S+\)\s\+=\s\+.*'

View File

@ -121,13 +121,14 @@ endfunction
" BinPath returns the binary path of installed go tools.
function! go#path#BinPath() abort
let bin_path = ""
let bin_path = go#config#BinPath()
if bin_path != ""
return bin_path
endif
" check if our global custom path is set, if not check if $GOBIN is set so
" we can use it, otherwise use default GOPATH
if exists("g:go_bin_path")
let bin_path = g:go_bin_path
elseif $GOBIN != ""
if $GOBIN != ""
let bin_path = $GOBIN
else
let go_paths = split(go#path#Default(), go#util#PathListSep())
@ -145,7 +146,8 @@ endfunction
function! go#path#CheckBinPath(binpath) abort
" remove whitespaces if user applied something like 'goimports '
let binpath = substitute(a:binpath, '^\s*\(.\{-}\)\s*$', '\1', '')
" save off original path
" save original path
let old_path = $PATH
" check if we have an appropriate bin_path

View File

@ -1,8 +1,3 @@
if !exists("g:go_play_open_browser")
let g:go_play_open_browser = 1
endif
function! go#play#Share(count, line1, line2) abort
if !executable('curl')
echohl ErrorMsg | echomsg "vim-go: require 'curl' command" | echohl None
@ -13,15 +8,16 @@ function! go#play#Share(count, line1, line2) abort
let share_file = tempname()
call writefile(split(content, "\n"), share_file, "b")
let command = "curl -s -X POST https://play.golang.org/share --data-binary '@".share_file."'"
let snippet_id = go#util#System(command)
let l:cmd = ['curl', '-s', '-X', 'POST', 'https://play.golang.org/share',
\ '--data-binary', '@' . l:share_file]
let [l:snippet_id, l:err] = go#util#Exec(l:cmd)
" we can remove the temp file because it's now posted.
call delete(share_file)
if go#util#ShellError() != 0
echo 'A error has occurred. Run this command to see what the problem is:'
echo command
if l:err != 0
echom 'A error has occurred. Run this command to see what the problem is:'
echom go#util#Shelljoin(l:cmd)
return
endif
@ -34,7 +30,7 @@ function! go#play#Share(count, line1, line2) abort
let @+ = url
endif
if g:go_play_open_browser != 0
if go#config#PlayOpenBrowser()
call go#tool#OpenBrowser(url)
endif

View File

@ -1,26 +1,10 @@
if !exists("g:go_gorename_bin")
let g:go_gorename_bin = "gorename"
endif
" Set the default value. A value of "1" is a shortcut for this, for
" compatibility reasons.
function! s:default() abort
if !exists("g:go_gorename_prefill") || g:go_gorename_prefill == 1
let g:go_gorename_prefill = 'expand("<cword>") =~# "^[A-Z]"' .
\ '? go#util#pascalcase(expand("<cword>"))' .
\ ': go#util#camelcase(expand("<cword>"))'
endif
endfunction
call s:default()
function! go#rename#Rename(bang, ...) abort
call s:default()
let to_identifier = ""
if a:0 == 0
let ask = printf("vim-go: rename '%s' to: ", expand("<cword>"))
if g:go_gorename_prefill != ''
let to_identifier = input(ask, eval(g:go_gorename_prefill))
let prefill = go#config#GorenamePrefill()
if prefill != ''
let to_identifier = input(ask, eval(prefill))
else
let to_identifier = input(ask)
endif
@ -33,7 +17,7 @@ function! go#rename#Rename(bang, ...) abort
endif
" return with a warning if the bin doesn't exist
let bin_path = go#path#CheckBinPath(g:go_gorename_bin)
let bin_path = go#path#CheckBinPath(go#config#GorenameBin())
if empty(bin_path)
return
endif
@ -41,19 +25,7 @@ function! go#rename#Rename(bang, ...) abort
let fname = expand('%:p')
let pos = go#util#OffsetCursor()
let offset = printf('%s:#%d', fname, pos)
" no need to escape for job call
let bin_path = go#util#has_job() ? bin_path : shellescape(bin_path)
let offset = go#util#has_job() ? offset : shellescape(offset)
let to_identifier = go#util#has_job() ? to_identifier : shellescape(to_identifier)
let cmd = [bin_path, "-offset", offset, "-to", to_identifier]
" check for any tags
if exists('g:go_build_tags')
let tags = get(g:, 'go_build_tags')
call extend(cmd, ["-tags", tags])
endif
let cmd = [bin_path, "-offset", offset, "-to", to_identifier, '-tags', go#config#BuildTags()]
if go#util#has_job()
call go#util#EchoProgress(printf("renaming to '%s' ...", to_identifier))
@ -64,11 +36,8 @@ function! go#rename#Rename(bang, ...) abort
return
endif
let command = join(cmd, " ")
let out = go#tool#ExecuteInDir(command)
let splitted = split(out, '\n')
call s:parse_errors(go#util#ShellError(), a:bang, splitted)
let [l:out, l:err] = go#tool#ExecuteInDir(l:cmd)
call s:parse_errors(l:err, a:bang, split(l:out, '\n'))
endfunction
function s:rename_job(args)

View File

@ -26,7 +26,7 @@ function! go#statusline#Show() abort
" lazy initialiation of the cleaner
if !s:timer_id
" clean every 60 seconds all statuses
let interval = get(g:, 'go_statusline_duration', 60000)
let interval = go#config#StatuslineDuration()
let s:timer_id = timer_start(interval, function('go#statusline#Clear'), {'repeat': -1})
endif

View File

@ -31,24 +31,22 @@ function! go#tags#run(start, end, offset, mode, fname, test_mode, ...) abort
let args["modified"] = 1
endif
let result = s:create_cmd(args)
let l:result = s:create_cmd(args)
if has_key(result, 'err')
call go#util#EchoError(result.err)
return -1
endif
let command = join(result.cmd, " ")
if &modified
let filename = expand("%:p:gs!\\!/!")
let content = join(go#util#GetLines(), "\n")
let in = filename . "\n" . strlen(content) . "\n" . content
let out = go#util#System(command, in)
let [l:out, l:err] = go#util#Exec(l:result.cmd, in)
else
let out = go#util#System(command)
let [l:out, l:err] = go#util#Exec(l:result.cmd)
endif
if go#util#ShellError() != 0
if l:err != 0
call go#util#EchoError(out)
return
endif
@ -115,19 +113,18 @@ func s:create_cmd(args) abort
if empty(bin_path)
return {'err': "gomodifytags does not exist"}
endif
let bin_path = go#util#Shellescape(bin_path)
let l:start = a:args.start
let l:end = a:args.end
let l:offset = a:args.offset
let l:mode = a:args.mode
let l:cmd_args = a:args.cmd_args
let l:modifytags_transform = get(g:, 'go_addtags_transform', "snakecase")
let l:modifytags_transform = go#config#AddtagsTransform()
" start constructing the command
let cmd = [bin_path]
call extend(cmd, ["-format", "json"])
call extend(cmd, ["-file", go#util#Shellescape(a:args.fname)])
call extend(cmd, ["-file", a:args.fname])
call extend(cmd, ["-transform", l:modifytags_transform])
if has_key(a:args, "modified")

View File

@ -1,7 +1,7 @@
let s:current_file = expand("<sfile>")
function! go#template#create() abort
let l:go_template_use_pkg = get(g:, 'go_template_use_pkg', 0)
let l:go_template_use_pkg = go#config#TemplateUsePkg()
let l:root_dir = fnamemodify(s:current_file, ':h:h:h')
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
@ -19,9 +19,9 @@ function! go#template#create() abort
if l:package_name == -1 && l:go_template_use_pkg != 1
let l:filename = fnamemodify(expand("%"), ':t')
if l:filename =~ "_test.go$"
let l:template_file = get(g:, 'go_template_test_file', "hello_world_test.go")
let l:template_file = go#config#TemplateTestFile()
else
let l:template_file = get(g:, 'go_template_file', "hello_world.go")
let l:template_file = go#config#TemplateFile()
endif
let l:template_path = go#util#Join(l:root_dir, "templates", l:template_file)
silent exe 'keepalt 0r ' . fnameescape(l:template_path)
@ -40,13 +40,13 @@ function! go#template#create() abort
endfunction
function! go#template#ToggleAutoCreate() abort
if get(g:, "go_template_autocreate", 1)
let g:go_template_autocreate = 0
if go#config#TemplateAutocreate()
call go#config#SetTemplateAutocreate(0)
call go#util#EchoProgress("auto template create disabled")
return
end
let g:go_template_autocreate = 1
call go#config#SetTemplateAutocreate(1)
call go#util#EchoProgress("auto template create enabled")
endfunction

View File

@ -1,18 +1,14 @@
if has('nvim') && !exists("g:go_term_mode")
let g:go_term_mode = 'vsplit'
endif
" new creates a new terminal with the given command. Mode is set based on the
" global variable g:go_term_mode, which is by default set to :vsplit
function! go#term#new(bang, cmd) abort
return go#term#newmode(a:bang, a:cmd, g:go_term_mode)
return go#term#newmode(a:bang, a:cmd, go#config#TermMode())
endfunction
" new creates a new terminal with the given command and window mode.
function! go#term#newmode(bang, cmd, mode) abort
let mode = a:mode
if empty(mode)
let mode = g:go_term_mode
let mode = go#config#TermMode()
endif
let state = {
@ -52,8 +48,8 @@ function! go#term#newmode(bang, cmd, mode) abort
execute cd . fnameescape(dir)
" resize new term if needed.
let height = get(g:, 'go_term_height', winheight(0))
let width = get(g:, 'go_term_width', winwidth(0))
let height = go#config#TermHeight()
let width = go#config#TermWidth()
" Adjust the window width or height depending on whether it's a vertical or
" horizontal split.
@ -94,7 +90,11 @@ function! s:on_exit(job_id, exit_status, event) dict abort
call win_gotoid(self.winid)
call go#list#Populate(l:listtype, errors, self.cmd)
let title = self.cmd
if type(title) == v:t_list
let title = join(self.cmd)
endif
call go#list#Populate(l:listtype, errors, title)
call go#list#Window(l:listtype, len(errors))
if !self.bang
call go#list#JumpToFirst(l:listtype)

View File

@ -0,0 +1,11 @@
package main
import (
"io/ioutil"
"testing"
)
func TestSomething(t *testing.T) {
r := struct{}{}
ioutil.ReadAll(r)
}

View File

@ -0,0 +1,7 @@
package main
import "fmt"
func main() {
fmt.Errorf("%v")
}

View File

@ -2,7 +2,7 @@
" compile the tests instead of running them (useful to catch errors in the
" test files). Any other argument is appended to the final `go test` command.
function! go#test#Test(bang, compile, ...) abort
let args = ["test"]
let args = ["test", '-tags', go#config#BuildTags()]
" don't run the test, only compile it. Useful to capture and fix errors.
if a:compile
@ -10,11 +10,6 @@ function! go#test#Test(bang, compile, ...) abort
call extend(args, ["-c", "-o", testfile])
endif
if exists('g:go_build_tags')
let tags = get(g:, 'go_build_tags')
call extend(args, ["-tags", tags])
endif
if a:0
let goargs = a:000
@ -24,18 +19,14 @@ function! go#test#Test(bang, compile, ...) abort
let goargs = map(copy(a:000), "expand(v:val)")
endif
if !(has('nvim') || go#util#has_job())
let goargs = go#util#Shelllist(goargs, 1)
endif
call extend(args, goargs, 1)
else
" only add this if no custom flags are passed
let timeout = get(g:, 'go_test_timeout', '10s')
let timeout = go#config#TestTimeout()
call add(args, printf("-timeout=%s", timeout))
endif
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
if a:compile
call go#util#EchoProgress("compiling tests ...")
else
@ -48,7 +39,7 @@ function! go#test#Test(bang, compile, ...) abort
let job_args = {
\ 'cmd': ['go'] + args,
\ 'bang': a:bang,
\ 'winnr': winnr(),
\ 'winid': win_getid(winnr()),
\ 'dir': getcwd(),
\ 'compile_test': a:compile,
\ 'jobdir': fnameescape(expand("%:p:h")),
@ -58,7 +49,7 @@ function! go#test#Test(bang, compile, ...) abort
return
elseif has('nvim')
" use nvims's job functionality
if get(g:, 'go_term_enabled', 0)
if go#config#TermEnabled()
let id = go#term#new(a:bang, ["go"] + args)
else
let id = go#jobcontrol#Spawn(a:bang, "test", "GoTest", args)
@ -70,8 +61,9 @@ function! go#test#Test(bang, compile, ...) abort
call go#cmd#autowrite()
redraw
let command = "go " . join(args, ' ')
let out = go#tool#ExecuteInDir(command)
let l:cmd = ['go'] + l:args
let [l:out, l:err] = go#tool#ExecuteInDir(l:cmd)
" TODO(bc): When the output is JSON, the JSON should be run through a
" filter to produce lines that are more easily described by errorformat.
@ -81,8 +73,8 @@ function! go#test#Test(bang, compile, ...) abort
let dir = getcwd()
execute cd fnameescape(expand("%:p:h"))
if go#util#ShellError() != 0
call go#list#ParseFormat(l:listtype, s:errorformat(), split(out, '\n'), command)
if l:err != 0
call go#list#ParseFormat(l:listtype, s:errorformat(), split(out, '\n'), l:cmd)
let errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:bang
@ -130,7 +122,7 @@ function! go#test#Func(bang, ...) abort
call extend(args, a:000)
else
" only add this if no custom flags are passed
let timeout = get(g:, 'go_test_timeout', '10s')
let timeout = go#config#TestTimeout()
call add(args, printf("-timeout=%s", timeout))
endif
@ -186,7 +178,7 @@ function! s:test_job(args) abort
let status.state = "failed"
endif
if get(g:, 'go_echo_command_info', 1)
if go#config#EchoCommandInfo()
if a:exitval == 0
if self.compile_test
call go#util#EchoSuccess("[test] SUCCESS")
@ -242,11 +234,16 @@ endfunction
" a quickfix compatible list of errors. It's intended to be used only for go
" test output.
function! s:show_errors(args, exit_val, messages) abort
let l:listtype = go#list#Type("GoTest")
if a:exit_val == 0
call go#list#Clean(l:listtype)
return
endif
let l:winid = win_getid(winnr())
call win_gotoid(a:args.winid)
let l:listtype = go#list#Type("GoTest")
if a:exit_val == 0
call go#list#Clean(l:listtype)
call win_gotoid(l:winid)
return
endif
" TODO(bc): When messages is JSON, the JSON should be run through a
" filter to produce lines that are more easily described by errorformat.
@ -266,20 +263,24 @@ function! s:show_errors(args, exit_val, messages) abort
" failed to parse errors, output the original content
call go#util#EchoError(a:messages)
call go#util#EchoError(a:args.dir)
call win_gotoid(l:winid)
return
endif
if a:args.winnr == winnr()
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:args.bang
call go#list#JumpToFirst(l:listtype)
endif
if a:args.winid != l:winid
call win_gotoid(l:winid)
return
endif
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:args.bang
call go#list#JumpToFirst(l:listtype)
endif
endfunction
let s:efm= ""
let s:go_test_show_name=0
let s:efm = ""
let s:go_test_show_name = 0
function! s:errorformat() abort
" NOTE(arslan): once we get JSON output everything will be easier :).
@ -288,7 +289,7 @@ function! s:errorformat() abort
" https://github.com/golang/go/issues/2981.
let goroot = go#util#goroot()
let show_name=get(g:, 'go_test_show_name', 0)
let show_name = go#config#TestShowName()
if s:efm != "" && s:go_test_show_name == show_name
return s:efm
endif
@ -299,11 +300,8 @@ function! s:errorformat() abort
" (e.g. \%(\)).
let indent = '%\\%( %\\)%#'
" match compiler errors
let format = "%f:%l:%c: %m"
" ignore `go test -v` output for starting tests
let format .= ",%-G=== RUN %.%#"
let format = "%-G=== RUN %.%#"
" ignore `go test -v` output for passing tests
let format .= ",%-G" . indent . "--- PASS: %.%#"
@ -415,6 +413,20 @@ function! s:errorformat() abort
let format .= ",%-CFAIL%\\t%.%#"
"let format .= ",FAIL%\\t%.%#"
" match compiler errors
" These are very smilar to errors from test output, but lack leading tabs
" for the first line of an error, and subsequent lines only have one tab
" instead of two.
let format .= ",%A%f:%l:%c: %m"
let format .= ",%A%f:%l: %m"
" It would be nice if this weren't necessary, but panic lines from tests are
" prefixed with a single leading tab, making them very similar to 2nd and
" later lines of a multi-line compiler error. Swallow it so that it doesn't
" cause a quickfix entry since the next entry can add a quickfix entry for
" 2nd and later lines of a multi-line compiler error.
let format .= ",%-C%\\tpanic: %.%#"
let format .= ",%G%\\t%m"
" Match and ignore everything else in multi-line messages.
let format .= ",%-C%.%#"
" Match and ignore everything else not in a multi-line message:

View File

@ -69,7 +69,23 @@ func! Test_GoTestShowName() abort
let g:go_test_show_name=1
call s:test('showname/showname_test.go', expected)
let g:go_test_show_name=0
unlet g:go_test_show_name
endfunc
func! Test_GoTestVet() abort
let expected = [
\ {'lnum': 6, 'bufnr': 16, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'Errorf format %v reads arg #1, but call has only 0 args'},
\ ]
call s:test('veterror/veterror.go', expected)
endfunc
func! Test_GoTestTestCompilerError() abort
let expected = [
\ {'lnum': 10, 'bufnr': 11, 'col': 16, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'cannot use r (type struct {}) as type io.Reader in argument to ioutil.ReadAll:'},
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'struct {} does not implement io.Reader (missing Read method)'}
\ ]
call s:test('testcompilerror/testcompilerror_test.go', expected)
endfunc
func! s:test(file, expected, ...) abort
@ -94,7 +110,7 @@ func! s:test(file, expected, ...) abort
endif
" run the tests
call call(function('go#test#Test'), args)
silent call call(function('go#test#Test'), args)
let actual = getqflist()
let start = reltime()

View File

@ -1,48 +1,128 @@
if !exists("g:go_textobj_enabled")
let g:go_textobj_enabled = 1
endif
if !exists("g:go_textobj_include_function_doc")
let g:go_textobj_include_function_doc = 1
endif
if !exists("g:go_textobj_include_variable")
let g:go_textobj_include_variable = 1
endif
" ( ) motions
" { } motions
" s for sentence
" p for parapgrah
" p for paragraph
" < >
" t for tag
" Select a function in visual mode.
function! go#textobj#Function(mode) abort
let offset = go#util#OffsetCursor()
function! go#textobj#Comment(mode) abort
let l:fname = expand('%:p')
let fname = shellescape(expand("%:p"))
if &modified
" Write current unsaved buffer to a temp file and use the modified content
let l:tmpname = tempname()
call writefile(go#util#GetLines(), l:tmpname)
let fname = l:tmpname
endif
try
if &modified
let l:tmpname = tempname()
call writefile(go#util#GetLines(), l:tmpname)
let l:fname = l:tmpname
endif
let bin_path = go#path#CheckBinPath('motion')
if empty(bin_path)
let l:cmd = ['motion',
\ '-format', 'json',
\ '-file', l:fname,
\ '-offset', go#util#OffsetCursor(),
\ '-mode', 'comment',
\ ]
let [l:out, l:err] = go#util#Exec(l:cmd)
if l:err
call go#util#EchoError(l:out)
return
endif
finally
if exists("l:tmpname")
call delete(l:tmpname)
endif
endtry
let l:result = json_decode(l:out)
if type(l:result) != 4 || !has_key(l:result, 'comment')
return
endif
let command = printf("%s -format vim -file %s -offset %s", bin_path, fname, offset)
let command .= " -mode enclosing"
let l:info = l:result.comment
call cursor(l:info.startLine, l:info.startCol)
if g:go_textobj_include_function_doc
let command .= " -parse-comments"
" Adjust cursor to exclude start comment markers. Try to be a little bit
" clever when using multi-line '/*' markers.
if a:mode is# 'i'
" trim whitespace so matching below works correctly
let l:line = substitute(getline('.'), '^\s*\(.\{-}\)\s*$', '\1', '')
" //text
if l:line[:2] is# '// '
call cursor(l:info.startLine, l:info.startCol+3)
" // text
elseif l:line[:1] is# '//'
call cursor(l:info.startLine, l:info.startCol+2)
" /*
" text
elseif l:line =~# '^/\* *$'
call cursor(l:info.startLine+1, 0)
" /*
" * text
if getline('.')[:2] is# ' * '
call cursor(l:info.startLine+1, 4)
" /*
" *text
elseif getline('.')[:1] is# ' *'
call cursor(l:info.startLine+1, 3)
endif
" /* text
elseif l:line[:2] is# '/* '
call cursor(l:info.startLine, l:info.startCol+3)
" /*text
elseif l:line[:1] is# '/*'
call cursor(l:info.startLine, l:info.startCol+2)
endif
endif
let out = go#util#System(command)
if go#util#ShellError() != 0
normal! v
" Exclude trailing newline.
if a:mode is# 'i'
let l:info.endCol -= 1
endif
call cursor(l:info.endLine, l:info.endCol)
" Exclude trailing '*/'.
if a:mode is# 'i'
let l:line = getline('.')
" text
" */
if l:line =~# '^ *\*/$'
call cursor(l:info.endLine - 1, len(getline(l:info.endLine - 1)))
" text */
elseif l:line[-3:] is# ' */'
call cursor(l:info.endLine, l:info.endCol - 3)
" text*/
elseif l:line[-2:] is# '*/'
call cursor(l:info.endLine, l:info.endCol - 2)
endif
endif
endfunction
" Select a function in visual mode.
function! go#textobj#Function(mode) abort
let l:fname = expand("%:p")
if &modified
let l:tmpname = tempname()
call writefile(go#util#GetLines(), l:tmpname)
let l:fname = l:tmpname
endif
let l:cmd = ['motion',
\ '-format', 'vim',
\ '-file', l:fname,
\ '-offset', go#util#OffsetCursor(),
\ '-mode', 'enclosing',
\ ]
if go#config#TextobjIncludeFunctionDoc()
let l:cmd += ['-parse-comments']
endif
let [l:out, l:err] = go#util#Exec(l:cmd)
if l:err
call go#util#EchoError(out)
return
endif
@ -63,9 +143,9 @@ function! go#textobj#Function(mode) abort
if a:mode == 'a'
" anonymous functions doesn't have associated doc. Also check if the user
" want's to include doc comments for function declarations
if has_key(info, 'doc') && g:go_textobj_include_function_doc
if has_key(info, 'doc') && go#config#TextobjIncludeFunctionDoc()
call cursor(info.doc.line, info.doc.col)
elseif info['sig']['name'] == '' && g:go_textobj_include_variable
elseif info['sig']['name'] == '' && go#config#TextobjIncludeVariable()
" one liner anonymous functions
if info.lbrace.line == info.rbrace.line
" jump to first nonblack char, to get the correct column
@ -101,36 +181,28 @@ endfunction
" Get the location of the previous or next function.
function! go#textobj#FunctionLocation(direction, cnt) abort
let offset = go#util#OffsetCursor()
let fname = shellescape(expand("%:p"))
let l:fname = expand("%:p")
if &modified
" Write current unsaved buffer to a temp file and use the modified content
let l:tmpname = tempname()
call writefile(go#util#GetLines(), l:tmpname)
let fname = l:tmpname
let l:fname = l:tmpname
endif
let bin_path = go#path#CheckBinPath('motion')
if empty(bin_path)
return
let l:cmd = ['motion',
\ '-format', 'vim',
\ '-file', l:fname,
\ '-offset', go#util#OffsetCursor(),
\ '-shift', a:cnt,
\ '-mode', a:direction,
\ ]
if go#config#TextobjIncludeFunctionDoc()
let l:cmd += ['-parse-comments']
endif
let command = printf("%s -format vim -file %s -offset %s", bin_path, fname, offset)
let command .= ' -shift ' . a:cnt
if a:direction == 'next'
let command .= ' -mode next'
else " 'prev'
let command .= ' -mode prev'
endif
if g:go_textobj_include_function_doc
let command .= " -parse-comments"
endif
let out = go#util#System(command)
if go#util#ShellError() != 0
let [l:out, l:err] = go#util#Exec(l:cmd)
if l:err
call go#util#EchoError(out)
return
endif
@ -190,7 +262,7 @@ function! go#textobj#FunctionJump(mode, direction) abort
endif
if a:mode == 'v' && a:direction == 'prev'
if has_key(info, 'doc') && g:go_textobj_include_function_doc
if has_key(info, 'doc') && go#config#TextobjIncludeFunctionDoc()
keepjumps call cursor(info.doc.line, 1)
else
keepjumps call cursor(info.func.line, 1)

View File

@ -36,8 +36,8 @@ function! go#tool#Files(...) abort
endif
endfor
let out = go#tool#ExecuteInDir('go list -f ' . shellescape(combined))
return split(out, '\n')
let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-f', l:combined])
return split(l:out, '\n')
endfunction
function! go#tool#Deps() abort
@ -46,9 +46,8 @@ function! go#tool#Deps() abort
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')
let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-f', l:format])
return split(l:out, '\n')
endfunction
function! go#tool#Imports() abort
@ -58,16 +57,19 @@ function! go#tool#Imports() abort
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
let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-f', l:format])
if l:err != 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 [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-f', '{{.Name}}', l:package_path])
if l:err != 0
echo out
return imports
endif
let package_name = substitute(l:out, '\n$', '', '')
let imports[package_name] = package_path
endfor
@ -75,7 +77,7 @@ function! go#tool#Imports() abort
endfunction
function! go#tool#Info(auto) abort
let l:mode = get(g:, 'go_info_mode', 'gocode')
let l:mode = go#config#InfoMode()
if l:mode == 'gocode'
call go#complete#Info(a:auto)
elseif l:mode == 'guru'
@ -86,9 +88,8 @@ function! go#tool#Info(auto) abort
endfunction
function! go#tool#PackageName() abort
let command = "go list -f \"{{.Name}}\""
let out = go#tool#ExecuteInDir(command)
if go#util#ShellError() != 0
let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-f', '{{.Name}}'])
if l:err != 0
return -1
endif
@ -117,7 +118,7 @@ function! go#tool#ParseErrors(lines) abort
" Preserve indented lines.
" This comes up especially with multi-line test output.
if match(line, '^\s') >= 0
call add(errors, {"text": line})
call add(errors, {"text": substitute(line, '\r$', '', '')})
endif
endif
endfor
@ -162,67 +163,35 @@ function! go#tool#FilterValids(items) abort
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 ''
return ['', 1]
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)
let [l:out, l:err] = go#util#Exec(a:cmd)
finally
execute cd . fnameescape(dir)
execute cd . fnameescape(l:dir)
endtry
return out
return [l:out, l:err]
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
let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', a:importpath])
if l:err != 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
let l:cmd = go#config#PlayBrowserCommand()
if len(l:cmd) == 0
redraw
echohl WarningMsg
echo "It seems that you don't have general web browser. Open URL below."
@ -230,15 +199,17 @@ function! go#tool#OpenBrowser(url) abort
echo a:url
return
endif
if cmd =~ '^!'
let cmd = substitute(cmd, '%URL%', '\=escape(shellescape(a:url),"#")', 'g')
silent! exec cmd
" if setting starts with a !.
if l:cmd =~ '^!'
let l:cmd = substitute(l:cmd, '%URL%', '\=escape(shellescape(a:url), "#")', 'g')
silent! exec l:cmd
elseif cmd =~ '^:[A-Z]'
let cmd = substitute(cmd, '%URL%', '\=escape(a:url,"#")', 'g')
exec cmd
let l:cmd = substitute(l:cmd, '%URL%', '\=escape(a:url,"#")', 'g')
exec l:cmd
else
let cmd = substitute(cmd, '%URL%', '\=shellescape(a:url)', 'g')
call go#util#System(cmd)
let l:cmd = substitute(l:cmd, '%URL%', '\=shellescape(a:url)', 'g')
call go#util#System(l:cmd)
endif
endfunction

View File

@ -1,8 +1,8 @@
func! Test_ExecuteInDir() abort
let l:tmp = gotest#write_file('a/a.go', ['package a'])
try
let l:out = go#tool#ExecuteInDir("pwd")
call assert_equal(l:tmp . "/src/a\n", l:out)
let l:out = go#tool#ExecuteInDir(['pwd'])
call assert_equal([l:tmp . "/src/a\n", 0], l:out)
finally
call delete(l:tmp, 'rf')
endtry
@ -13,8 +13,8 @@ func! Test_ExecuteInDir_nodir() abort
exe ':e ' . l:tmp . '/new-dir/a'
try
let l:out = go#tool#ExecuteInDir("pwd")
call assert_equal('', l:out)
let l:out = go#tool#ExecuteInDir(['pwd'])
call assert_equal(['', 1], l:out)
finally
call delete(l:tmp, 'rf')
endtry

View File

@ -48,7 +48,7 @@ function! go#util#IsMac() abort
return has('mac') ||
\ has('macunix') ||
\ has('gui_macvim') ||
\ go#util#System('uname') =~? '^darwin'
\ go#util#Exec(['uname'])[0] =~? '^darwin'
endfunction
" Checks if using:
@ -59,7 +59,16 @@ function! go#util#IsUsingCygwinShell()
return go#util#IsWin() && executable('cygpath') && &shell =~ '.*sh.*'
endfunction
function! go#util#has_job() abort
" Check if Vim jobs API is supported.
"
" The (optional) first paramter can be added to indicate the 'cwd' or 'env'
" parameters will be used, which wasn't added until a later version.
function! go#util#has_job(...) abort
" cwd and env parameters to job_start was added in this version.
if a:0 > 0 && a:1 is 1
return has('job') && has("patch-8.0.0902")
endif
" job was introduced in 7.4.xxx however there are multiple bug fixes and one
" of the latest is 8.0.0087 which is required for a stable async API.
return has('job') && has("patch-8.0.0087")
@ -93,25 +102,25 @@ endfunction
" goarch returns 'go env GOARCH'. This is an internal function and shouldn't
" be used. Instead use 'go#util#env("goarch")'
function! go#util#goarch() abort
return substitute(go#util#System('go env GOARCH'), '\n', '', 'g')
return substitute(s:exec(['go', 'env', 'GOARCH'])[0], '\n', '', 'g')
endfunction
" goos returns 'go env GOOS'. This is an internal function and shouldn't
" be used. Instead use 'go#util#env("goos")'
function! go#util#goos() abort
return substitute(go#util#System('go env GOOS'), '\n', '', 'g')
return substitute(s:exec(['go', 'env', 'GOOS'])[0], '\n', '', 'g')
endfunction
" goroot returns 'go env GOROOT'. This is an internal function and shouldn't
" be used. Instead use 'go#util#env("goroot")'
function! go#util#goroot() abort
return substitute(go#util#System('go env GOROOT'), '\n', '', 'g')
return substitute(s:exec(['go', 'env', 'GOROOT'])[0], '\n', '', 'g')
endfunction
" gopath returns 'go env GOPATH'. This is an internal function and shouldn't
" be used. Instead use 'go#util#env("gopath")'
function! go#util#gopath() abort
return substitute(go#util#System('go env GOPATH'), '\n', '', 'g')
return substitute(s:exec(['go', 'env', 'GOPATH'])[0], '\n', '', 'g')
endfunction
function! go#util#osarch() abort
@ -153,16 +162,28 @@ endfunction
function! go#util#Exec(cmd, ...) abort
if len(a:cmd) == 0
call go#util#EchoError("go#util#Exec() called with empty a:cmd")
return
return ['', 1]
endif
let l:bin = a:cmd[0]
" CheckBinPath will show a warning for us.
let l:bin = go#path#CheckBinPath(a:cmd[0])
let l:bin = go#path#CheckBinPath(l:bin)
if empty(l:bin)
return ["", 1]
return ['', 1]
endif
let l:out = call('s:system', [go#util#Shelljoin([l:bin] + a:cmd[1:])] + a:000)
return call('s:exec', [a:cmd] + a:000)
endfunction
function! s:exec(cmd, ...) abort
let l:bin = a:cmd[0]
let l:cmd = go#util#Shelljoin([l:bin] + a:cmd[1:])
if go#util#HasDebug('shell-commands')
call go#util#EchoInfo('shell command: ' . l:cmd)
endif
let l:out = call('s:system', [l:cmd] + a:000)
return [l:out, go#util#ShellError()]
endfunction
@ -259,7 +280,7 @@ endfunction
" snippetcase converts the given word to given preferred snippet setting type
" case.
function! go#util#snippetcase(word) abort
let l:snippet_case = get(g:, 'go_addtags_transform', "snakecase")
let l:snippet_case = go#config#AddtagsTransform()
if l:snippet_case == "snakecase"
return go#util#snakecase(a:word)
elseif l:snippet_case == "camelcase"
@ -397,7 +418,7 @@ endfunction
" Report if the user enabled a debug flag in g:go_debug.
function! go#util#HasDebug(flag)
return index(get(g:, 'go_debug', []), a:flag) >= 0
return index(go#config#Debug(), a:flag) >= 0
endfunction
" vim: sw=2 ts=2 et