mirror of
https://github.com/amix/vimrc
synced 2025-06-16 01:25:00 +08:00
Updated plugins
This commit is contained in:
@ -31,15 +31,12 @@ function! go#cmd#Build(bang, ...) abort
|
||||
\ [".", "errors"]
|
||||
|
||||
" Vim and Neovim async.
|
||||
if go#util#has_job() || has('nvim')
|
||||
if go#config#EchoCommandInfo()
|
||||
call go#util#EchoProgress("building dispatched ...")
|
||||
endif
|
||||
|
||||
if go#util#has_job()
|
||||
call s:cmd_job({
|
||||
\ 'cmd': ['go'] + args,
|
||||
\ 'bang': a:bang,
|
||||
\ 'for': 'GoBuild',
|
||||
\ 'statustype': 'build'
|
||||
\})
|
||||
|
||||
" Vim 7.4 without async
|
||||
@ -195,14 +192,11 @@ 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 go#config#EchoCommandInfo()
|
||||
call go#util#EchoProgress("installing dispatched ...")
|
||||
endif
|
||||
|
||||
call s:cmd_job({
|
||||
\ 'cmd': ['go', 'install', '-tags', go#config#BuildTags()] + goargs,
|
||||
\ 'bang': a:bang,
|
||||
\ 'for': 'GoInstall',
|
||||
\ 'statustype': 'install'
|
||||
\})
|
||||
return
|
||||
endif
|
||||
@ -281,16 +275,7 @@ endfunction
|
||||
" | Vim job callbacks |
|
||||
" ---------------------
|
||||
|
||||
function s:cmd_job(args) abort
|
||||
let status_dir = expand('%:p:h')
|
||||
let started_at = reltime()
|
||||
|
||||
call go#statusline#Update(status_dir, {
|
||||
\ 'desc': "current status",
|
||||
\ 'type': a:args.cmd[1],
|
||||
\ 'state': "started",
|
||||
\})
|
||||
|
||||
function! s:cmd_job(args) abort
|
||||
" autowrite is not enabled for jobs
|
||||
call go#cmd#autowrite()
|
||||
|
||||
|
@ -9,6 +9,15 @@ function! s:gocodeCommand(cmd, args) abort
|
||||
let cmd = [bin_path]
|
||||
let cmd = extend(cmd, ['-sock', socket_type])
|
||||
let cmd = extend(cmd, ['-f', 'vim'])
|
||||
|
||||
if go#config#GocodeProposeBuiltins()
|
||||
let cmd = extend(cmd, ['-builtin'])
|
||||
endif
|
||||
|
||||
if go#config#GocodeProposeSource()
|
||||
let cmd = extend(cmd, ['-source'])
|
||||
endif
|
||||
|
||||
let cmd = extend(cmd, [a:cmd])
|
||||
let cmd = extend(cmd, a:args)
|
||||
|
||||
@ -43,31 +52,7 @@ function! s:sync_gocode(cmd, args, input) abort
|
||||
return l:result
|
||||
endfunction
|
||||
|
||||
let s:optionsEnabled = 0
|
||||
function! s:gocodeEnableOptions() abort
|
||||
if s:optionsEnabled
|
||||
return
|
||||
endif
|
||||
|
||||
let l:bin_path = go#path#CheckBinPath("gocode")
|
||||
if empty(l:bin_path)
|
||||
return
|
||||
endif
|
||||
|
||||
let s:optionsEnabled = 1
|
||||
|
||||
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
|
||||
endfunction
|
||||
|
||||
function! s:gocodeAutocomplete() abort
|
||||
call s:gocodeEnableOptions()
|
||||
|
||||
" use the offset as is, because the cursor position is the position for
|
||||
" which autocomplete candidates are needed.
|
||||
return s:sync_gocode('autocomplete',
|
||||
@ -81,60 +66,36 @@ function! go#complete#GetInfo() abort
|
||||
return s:sync_info(0)
|
||||
endfunction
|
||||
|
||||
function! go#complete#Info() abort
|
||||
function! go#complete#Info(showstatus) abort
|
||||
if go#util#has_job(1)
|
||||
return s:async_info(1)
|
||||
return s:async_info(1, a:showstatus)
|
||||
else
|
||||
return s:sync_info(1)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:async_info(echo)
|
||||
if exists("s:async_info_job")
|
||||
call job_stop(s:async_info_job)
|
||||
unlet s:async_info_job
|
||||
endif
|
||||
function! s:async_info(echo, showstatus)
|
||||
let state = {'echo': a:echo}
|
||||
|
||||
let state = {
|
||||
\ 'exited': 0,
|
||||
\ 'exit_status': 0,
|
||||
\ 'closed': 0,
|
||||
\ 'messages': [],
|
||||
\ 'echo': a:echo
|
||||
\ }
|
||||
|
||||
function! s:callback(chan, msg) dict
|
||||
let l:msg = a:msg
|
||||
if &encoding != 'utf-8'
|
||||
let l:msg = iconv(l:msg, 'utf-8', &encoding)
|
||||
endif
|
||||
call add(self.messages, l:msg)
|
||||
endfunction
|
||||
|
||||
function! s:exit_cb(job, exitval) dict
|
||||
let self.exit_status = a:exitval
|
||||
let self.exited = 1
|
||||
|
||||
if self.closed
|
||||
call self.complete()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:close_cb(ch) dict
|
||||
let self.closed = 1
|
||||
if self.exited
|
||||
call self.complete()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function state.complete() dict
|
||||
if self.exit_status != 0
|
||||
function! s:complete(job, exit_status, messages) abort dict
|
||||
if a:exit_status != 0
|
||||
return
|
||||
endif
|
||||
|
||||
let result = s:info_filter(self.echo, join(self.messages, "\n"))
|
||||
if &encoding != 'utf-8'
|
||||
let i = 0
|
||||
while i < len(a:messages)
|
||||
let a:messages[i] = iconv(a:messages[i], 'utf-8', &encoding)
|
||||
let i += 1
|
||||
endwhile
|
||||
endif
|
||||
|
||||
let result = s:info_filter(self.echo, join(a:messages, "\n"))
|
||||
call s:info_complete(self.echo, result)
|
||||
endfunction
|
||||
" explicitly bind complete to state so that within it, self will
|
||||
" always refer to state. See :help Partial for more information.
|
||||
let state.complete = function('s:complete', [], state)
|
||||
|
||||
" add 1 to the offset, so that the position at the cursor will be included
|
||||
" in gocode's search
|
||||
@ -146,23 +107,32 @@ function! s:async_info(echo)
|
||||
\ "GOROOT": go#util#env("goroot")
|
||||
\ }
|
||||
|
||||
let opts = {
|
||||
\ 'bang': 1,
|
||||
\ 'complete': state.complete,
|
||||
\ 'for': '_',
|
||||
\ }
|
||||
|
||||
if a:showstatus
|
||||
let opts.statustype = 'gocode'
|
||||
endif
|
||||
|
||||
let opts = go#job#Options(l:opts)
|
||||
|
||||
let cmd = s:gocodeCommand('autocomplete',
|
||||
\ [expand('%:p'), offset])
|
||||
|
||||
" TODO(bc): Don't write the buffer to a file; pass the buffer directrly to
|
||||
" TODO(bc): Don't write the buffer to a file; pass the buffer directly to
|
||||
" gocode's stdin. It shouldn't be necessary to use {in_io: 'file', in_name:
|
||||
" s:gocodeFile()}, but unfortunately {in_io: 'buffer', in_buf: bufnr('%')}
|
||||
" should work.
|
||||
let options = {
|
||||
" doesn't work.
|
||||
call extend(opts, {
|
||||
\ 'env': env,
|
||||
\ 'in_io': 'file',
|
||||
\ 'in_name': s:gocodeFile(),
|
||||
\ 'callback': funcref("s:callback", [], state),
|
||||
\ 'exit_cb': funcref("s:exit_cb", [], state),
|
||||
\ 'close_cb': funcref("s:close_cb", [], state)
|
||||
\ }
|
||||
\ })
|
||||
|
||||
let s:async_info_job = job_start(cmd, options)
|
||||
call go#job#Start(cmd, opts)
|
||||
endfunction
|
||||
|
||||
function! s:gocodeFile()
|
||||
|
20
sources_non_forked/vim-go/autoload/go/complete_test.vim
Normal file
20
sources_non_forked/vim-go/autoload/go/complete_test.vim
Normal file
@ -0,0 +1,20 @@
|
||||
func! Test_GetInfo()
|
||||
let l:filename = 'complete/complete.go'
|
||||
let l:tmp = gotest#load_fixture(l:filename)
|
||||
|
||||
call cursor(8, 3)
|
||||
|
||||
let g:go_info_mode = 'gocode'
|
||||
let expected = 'func Example(s string)'
|
||||
let actual = go#complete#GetInfo()
|
||||
call assert_equal(expected, actual)
|
||||
|
||||
let g:go_info_mode = 'guru'
|
||||
call go#config#InfoMode()
|
||||
let actual = go#complete#GetInfo()
|
||||
call assert_equal(expected, actual)
|
||||
|
||||
unlet g:go_info_mode
|
||||
endfunction
|
||||
|
||||
" vim: sw=2 ts=2 et
|
@ -135,10 +135,6 @@ function! go#config#SetGuruScope(scope) abort
|
||||
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)
|
||||
@ -148,8 +144,8 @@ 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)
|
||||
function! go#config#GocodeProposeSource() abort
|
||||
return get(g:, 'go_gocode_propose_source', 1)
|
||||
endfunction
|
||||
|
||||
function! go#config#EchoCommandInfo() abort
|
||||
@ -282,6 +278,14 @@ function! go#config#SetAsmfmtAutosave(value) abort
|
||||
let g:go_asmfmt_autosave = a:value
|
||||
endfunction
|
||||
|
||||
function! go#config#ModFmtAutosave() abort
|
||||
return get(g:, "go_mod_fmt_autosave", 1)
|
||||
endfunction
|
||||
|
||||
function! go#config#SetModFmtAutosave(value) abort
|
||||
let g:go_mod_fmt_autosave = a:value
|
||||
endfunction
|
||||
|
||||
function! go#config#DocMaxHeight() abort
|
||||
return get(g:, "go_doc_max_height", 20)
|
||||
endfunction
|
||||
@ -416,7 +420,7 @@ function! go#config#HighlightVariableDeclarations() abort
|
||||
return get(g:, 'go_highlight_variable_declarations', 0)
|
||||
endfunction
|
||||
|
||||
function go#config#FoldEnable(...) abort
|
||||
function! go#config#FoldEnable(...) abort
|
||||
if a:0 > 0
|
||||
return index(go#config#FoldEnable(), a:1) > -1
|
||||
endif
|
||||
|
@ -44,11 +44,7 @@ function! go#coverage#Buffer(bang, ...) abort
|
||||
let s:toggle = 1
|
||||
let l:tmpname = tempname()
|
||||
|
||||
if go#config#EchoCommandInfo()
|
||||
call go#util#EchoProgress("testing...")
|
||||
endif
|
||||
|
||||
if go#util#has_job() || has('nvim')
|
||||
if go#util#has_job()
|
||||
call s:coverage_job({
|
||||
\ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname] + a:000,
|
||||
\ 'complete': function('s:coverage_callback', [l:tmpname]),
|
||||
@ -59,6 +55,10 @@ function! go#coverage#Buffer(bang, ...) abort
|
||||
return
|
||||
endif
|
||||
|
||||
if go#config#EchoCommandInfo()
|
||||
call go#util#EchoProgress("testing...")
|
||||
endif
|
||||
|
||||
let args = [a:bang, 0, "-coverprofile", l:tmpname]
|
||||
if a:0
|
||||
call extend(args, a:000)
|
||||
@ -89,12 +89,13 @@ endfunction
|
||||
" a new HTML coverage page from that profile in a new browser
|
||||
function! go#coverage#Browser(bang, ...) abort
|
||||
let l:tmpname = tempname()
|
||||
if go#util#has_job() || has('nvim')
|
||||
if go#util#has_job()
|
||||
call s:coverage_job({
|
||||
\ 'cmd': ['go', 'test', '-tags', go#config#BuildTags(), '-coverprofile', l:tmpname],
|
||||
\ 'complete': function('s:coverage_browser_callback', [l:tmpname]),
|
||||
\ 'bang': a:bang,
|
||||
\ 'for': 'GoTest',
|
||||
\ 'statustype': 'coverage',
|
||||
\ })
|
||||
return
|
||||
endif
|
||||
|
@ -25,12 +25,12 @@ function! s:groutineID() abort
|
||||
return s:state['currentThread'].goroutineID
|
||||
endfunction
|
||||
|
||||
function! s:exit(job, status) abort
|
||||
function! s:complete(job, exit_status, data) abort
|
||||
if has_key(s:state, 'job')
|
||||
call remove(s:state, 'job')
|
||||
endif
|
||||
call s:clearState()
|
||||
if a:status > 0
|
||||
if a:exit_status > 0
|
||||
call go#util#EchoError(s:state['message'])
|
||||
endif
|
||||
endfunction
|
||||
@ -567,14 +567,18 @@ function! go#debug#Start(is_test, ...) abort
|
||||
endif
|
||||
let l:cmd += l:args
|
||||
|
||||
call go#util#EchoProgress('Starting GoDebug...')
|
||||
let s:state['message'] = []
|
||||
let s:state['job'] = job_start(l:cmd, {
|
||||
\ 'out_cb': function('s:out_cb'),
|
||||
\ 'err_cb': function('s:err_cb'),
|
||||
\ 'exit_cb': function('s:exit'),
|
||||
\ 'stoponexit': 'kill',
|
||||
\})
|
||||
let l:opts = {
|
||||
\ 'for': '_',
|
||||
\ 'statustype': 'debug',
|
||||
\ 'complete': function('s:complete'),
|
||||
\ }
|
||||
let l:opts = go#job#Options(l:opts)
|
||||
let l:opts.out_cb = function('s:out_cb')
|
||||
let l:opts.err_cb = function('s:err_cb')
|
||||
let l:opts.stoponexit = 'kill'
|
||||
|
||||
let s:state['job'] = go#job#Start(l:cmd, l:opts)
|
||||
catch
|
||||
call go#util#EchoError(v:exception)
|
||||
endtry
|
||||
|
@ -42,20 +42,20 @@ function! go#def#Jump(mode) abort
|
||||
|
||||
call extend(cmd, ["definition", fname . ':#' . go#util#OffsetCursor()])
|
||||
|
||||
if go#util#has_job() || has('nvim')
|
||||
if go#util#has_job()
|
||||
let l:state = {}
|
||||
let l:spawn_args = {
|
||||
\ 'cmd': cmd,
|
||||
\ 'complete': function('s:jump_to_declaration_cb', [a:mode, bin_name]),
|
||||
\ 'complete': function('s:jump_to_declaration_cb', [a:mode, bin_name], l:state),
|
||||
\ 'for': '_',
|
||||
\ 'statustype': 'searching declaration',
|
||||
\ }
|
||||
|
||||
if &modified
|
||||
let l:spawn_args.input = stdin_content
|
||||
endif
|
||||
|
||||
call go#util#EchoProgress("searching declaration ...")
|
||||
|
||||
call s:def_job(spawn_args)
|
||||
call s:def_job(spawn_args, l:state)
|
||||
return
|
||||
endif
|
||||
|
||||
@ -77,13 +77,17 @@ function! go#def#Jump(mode) abort
|
||||
call go#def#jump_to_declaration(out, a:mode, bin_name)
|
||||
endfunction
|
||||
|
||||
function! s:jump_to_declaration_cb(mode, bin_name, job, exit_status, data) abort
|
||||
function! s:jump_to_declaration_cb(mode, bin_name, job, exit_status, data) abort dict
|
||||
if a:exit_status != 0
|
||||
return
|
||||
endif
|
||||
|
||||
call go#def#jump_to_declaration(a:data[0], a:mode, a:bin_name)
|
||||
call go#util#EchoSuccess(fnamemodify(a:data[0], ":t"))
|
||||
|
||||
" capture the active window so that after the exit_cb and close_cb callbacks
|
||||
" can return to it when a:mode caused a split.
|
||||
let self.winid = win_getid(winnr())
|
||||
endfunction
|
||||
|
||||
function! go#def#jump_to_declaration(out, mode, bin_name) abort
|
||||
@ -283,9 +287,26 @@ function! go#def#Stack(...) abort
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function s:def_job(args) abort
|
||||
function s:def_job(args, state) abort
|
||||
let l:start_options = go#job#Options(a:args)
|
||||
|
||||
let l:state = a:state
|
||||
function! s:exit_cb(next, job, exitval) dict
|
||||
call call(a:next, [a:job, a:exitval])
|
||||
if has_key(self, 'winid')
|
||||
call win_gotoid(self.winid)
|
||||
endif
|
||||
endfunction
|
||||
let l:start_options.exit_cb = funcref('s:exit_cb', [l:start_options.exit_cb], l:state)
|
||||
|
||||
function! s:close_cb(next, ch) dict
|
||||
call call(a:next, [a:ch])
|
||||
if has_key(self, 'winid')
|
||||
call win_gotoid(self.winid)
|
||||
endif
|
||||
endfunction
|
||||
let l:start_options.close_cb = funcref('s:close_cb', [l:start_options.close_cb], l:state)
|
||||
|
||||
if &modified
|
||||
let l:tmpname = tempname()
|
||||
call writefile(split(a:args.input, "\n"), l:tmpname, "b")
|
||||
@ -293,7 +314,7 @@ function s:def_job(args) abort
|
||||
let l:start_options.in_name = l:tmpname
|
||||
endif
|
||||
|
||||
call go#job#Start(a:args.cmd, start_options)
|
||||
call go#job#Start(a:args.cmd, l:start_options)
|
||||
endfunction
|
||||
|
||||
" vim: sw=2 ts=2 et
|
||||
|
@ -45,7 +45,7 @@ func! Test_Jump_leaves_lists() abort
|
||||
call setqflist(copy(expected), 'r' )
|
||||
|
||||
let l:bufnr = bufnr('%')
|
||||
call cursor(6, 3)
|
||||
call cursor(6, 7)
|
||||
call go#def#Jump('')
|
||||
|
||||
let start = reltime()
|
||||
|
@ -106,64 +106,6 @@ function! s:sync_guru(args) abort
|
||||
return l:out
|
||||
endfunc
|
||||
|
||||
" use vim or neovim job api as appropriate
|
||||
function! s:job_start(cmd, start_options) abort
|
||||
if go#util#has_job()
|
||||
return job_start(a:cmd, a:start_options)
|
||||
endif
|
||||
|
||||
let opts = {'stdout_buffered': v:true, 'stderr_buffered': v:true}
|
||||
|
||||
let stdout_buf = ""
|
||||
function opts.on_stdout(job_id, data, event) closure
|
||||
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
|
||||
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)
|
||||
endfunction
|
||||
|
||||
" 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', go#util#Shelljoin(a:cmd) . ' <' . a:start_options.in_name]
|
||||
endif
|
||||
|
||||
return jobstart(cmd, opts)
|
||||
endfunction
|
||||
|
||||
" async_guru runs guru in async mode with the given arguments
|
||||
function! s:async_guru(args) abort
|
||||
let result = s:guru_cmd(a:args)
|
||||
@ -172,91 +114,50 @@ 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 .
|
||||
\ " (see ':help go-guru-scope' if this doesn't work)...")
|
||||
endif
|
||||
endif
|
||||
|
||||
let state = {
|
||||
\ 'status_dir': expand('%:p:h'),
|
||||
\ 'statusline_type': printf("%s", a:args.mode),
|
||||
\ 'mode': a:args.mode,
|
||||
\ 'status': {},
|
||||
\ 'exitval': 0,
|
||||
\ 'closed': 0,
|
||||
\ 'exited': 0,
|
||||
\ 'messages': [],
|
||||
\ 'parse' : get(a:args, 'custom_parse', funcref("s:parse_guru_output"))
|
||||
\ }
|
||||
|
||||
function! s:callback(chan, msg) dict
|
||||
call add(self.messages, a:msg)
|
||||
function! s:complete(job, exit_status, messages) dict abort
|
||||
let output = join(a:messages, "\n")
|
||||
call self.parse(a:exit_status, output, self.mode)
|
||||
endfunction
|
||||
" explicitly bind complete to state so that within it, self will
|
||||
" always refer to state. See :help Partial for more information.
|
||||
let state.complete = function('s:complete', [], state)
|
||||
|
||||
function! s:exit_cb(job, exitval) dict
|
||||
let self.exited = 1
|
||||
let opts = {
|
||||
\ 'statustype': get(a:args, 'statustype', a:args.mode),
|
||||
\ 'for': '_',
|
||||
\ 'errorformat': "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m",
|
||||
\ 'complete': state.complete,
|
||||
\ }
|
||||
|
||||
let status = {
|
||||
\ 'desc': 'last status',
|
||||
\ 'type': self.statusline_type,
|
||||
\ 'state': "finished",
|
||||
\ }
|
||||
if has_key(a:args, 'disable_progress')
|
||||
let opts.statustype = ''
|
||||
endif
|
||||
|
||||
if a:exitval
|
||||
let self.exitval = a:exitval
|
||||
let status.state = "failed"
|
||||
endif
|
||||
|
||||
call go#statusline#Update(self.status_dir, status)
|
||||
|
||||
if self.closed
|
||||
call self.complete()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:close_cb(ch) dict
|
||||
let self.closed = 1
|
||||
|
||||
if self.exited
|
||||
call self.complete()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function state.complete() dict
|
||||
let out = join(self.messages, "\n")
|
||||
|
||||
call self.parse(self.exitval, out, self.mode)
|
||||
endfunction
|
||||
|
||||
" explicitly bind the callbacks to state so that self within them always
|
||||
" refers to state. See :help Partial for more information.
|
||||
let start_options = {
|
||||
\ 'callback': function('s:callback', [], state),
|
||||
\ 'exit_cb': function('s:exit_cb', [], state),
|
||||
\ 'close_cb': function('s:close_cb', [], state)
|
||||
\ }
|
||||
let opts = go#job#Options(l:opts)
|
||||
|
||||
if has_key(result, 'stdin_content')
|
||||
let l:tmpname = tempname()
|
||||
call writefile(split(result.stdin_content, "\n"), l:tmpname, "b")
|
||||
let l:start_options.in_io = "file"
|
||||
let l:start_options.in_name = l:tmpname
|
||||
let l:opts.in_io = "file"
|
||||
let l:opts.in_name = l:tmpname
|
||||
endif
|
||||
|
||||
call go#statusline#Update(state.status_dir, {
|
||||
\ 'desc': "current status",
|
||||
\ 'type': state.statusline_type,
|
||||
\ 'state': "analysing",
|
||||
\})
|
||||
call go#job#Start(result.cmd, opts)
|
||||
|
||||
return s:job_start(result.cmd, start_options)
|
||||
if a:args.needs_scope && go#config#EchoCommandInfo() && !has_key(a:args, 'disable_progress')
|
||||
call go#util#EchoProgress("analysing with scope " . result.scope .
|
||||
\ " (see ':help go-guru-scope' if this doesn't work)...")
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" run_guru runs the given guru argument
|
||||
function! s:run_guru(args) abort
|
||||
if has('nvim') || go#util#has_job()
|
||||
if go#util#has_job()
|
||||
let res = s:async_guru(a:args)
|
||||
else
|
||||
let res = s:sync_guru(a:args)
|
||||
@ -320,7 +221,7 @@ function! go#guru#Describe(selected) abort
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
function! go#guru#DescribeInfo() abort
|
||||
function! go#guru#DescribeInfo(showstatus) abort
|
||||
" json_encode() and friends are introduced with this patch (7.4.1304)
|
||||
" vim: https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ
|
||||
" nvim: https://github.com/neovim/neovim/pull/4131
|
||||
@ -411,7 +312,7 @@ function! go#guru#DescribeInfo() abort
|
||||
return
|
||||
endif
|
||||
|
||||
call go#util#EchoInfo(info)
|
||||
echo "vim-go: " | echohl Function | echon info | echohl None
|
||||
endfunction
|
||||
|
||||
let args = {
|
||||
@ -504,7 +405,7 @@ function! go#guru#Referrers(selected) abort
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
function! go#guru#SameIds() abort
|
||||
function! go#guru#SameIds(showstatus) abort
|
||||
" we use matchaddpos() which was introduce with 7.4.330, be sure we have
|
||||
" it: http://ftp.vim.org/vim/patches/7.4/7.4.330
|
||||
if !exists("*matchaddpos")
|
||||
@ -527,6 +428,9 @@ function! go#guru#SameIds() abort
|
||||
\ 'needs_scope': 0,
|
||||
\ 'custom_parse': function('s:same_ids_highlight'),
|
||||
\ }
|
||||
if !a:showstatus
|
||||
let args.disable_progress = 1
|
||||
endif
|
||||
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
@ -65,6 +65,9 @@ function! go#import#SwitchImport(enabled, localname, path, bang) abort
|
||||
let packageline = line
|
||||
let appendline = line
|
||||
|
||||
elseif linestr =~# '^import\s\+(\+)'
|
||||
let appendline = line
|
||||
let appendstr = qlocalpath
|
||||
elseif linestr =~# '^import\s\+('
|
||||
let appendstr = qlocalpath
|
||||
let indentstr = 1
|
||||
@ -161,8 +164,16 @@ function! go#import#SwitchImport(enabled, localname, path, bang) abort
|
||||
let linesdelta += 3
|
||||
let appendstr = qlocalpath
|
||||
let indentstr = 1
|
||||
call append(appendline, appendstr)
|
||||
elseif getline(appendline) =~# '^import\s\+(\+)'
|
||||
call setline(appendline, 'import (')
|
||||
call append(appendline + 0, appendstr)
|
||||
call append(appendline + 1, ')')
|
||||
let linesdelta -= 1
|
||||
let indentstr = 1
|
||||
else
|
||||
call append(appendline, appendstr)
|
||||
endif
|
||||
call append(appendline, appendstr)
|
||||
execute appendline + 1
|
||||
if indentstr
|
||||
execute 'normal! >>'
|
||||
|
22
sources_non_forked/vim-go/autoload/go/indent_test.vim
Normal file
22
sources_non_forked/vim-go/autoload/go/indent_test.vim
Normal file
@ -0,0 +1,22 @@
|
||||
func! Test_indent_raw_string() abort
|
||||
try
|
||||
let l:dir= gotest#write_file('indent/indent.go', [
|
||||
\ 'package main',
|
||||
\ '',
|
||||
\ 'import "fmt"',
|
||||
\ '',
|
||||
\ 'func main() {',
|
||||
\ "\t\x1fconst msg = `",
|
||||
\ '`',
|
||||
\ '\tfmt.Println(msg)',
|
||||
\ '}'])
|
||||
|
||||
silent execute "normal o" . "not indented\<Esc>"
|
||||
let l:indent = indent(line('.'))
|
||||
call assert_equal(0, l:indent)
|
||||
finally
|
||||
call delete(l:dir, 'rf')
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
" vim: sw=2 ts=2 et
|
@ -33,7 +33,10 @@ endfunction
|
||||
" function will be passed three arguments: the job, its exit code, and the
|
||||
" list of messages received from the channel. The default is a no-op. A
|
||||
" custom value can modify the messages before they are processed by the
|
||||
" returned exit_cb and close_cb callbacks.
|
||||
" returned exit_cb and close_cb callbacks. When the function is called,
|
||||
" the current window will be the window that was hosting the buffer when
|
||||
" the job was started. After it returns, the current window will be
|
||||
" restored to what it was before the function was called.
|
||||
|
||||
" The return value is a dictionary with these keys:
|
||||
" 'callback':
|
||||
@ -87,14 +90,27 @@ function! go#job#Options(args)
|
||||
|
||||
" do nothing in state.complete by default.
|
||||
function state.complete(job, exit_status, data)
|
||||
if has_key(self, 'custom_complete')
|
||||
let l:winid = win_getid(winnr())
|
||||
" Always set the active window to the window that was active when the job
|
||||
" was started. Among other things, this makes sure that the correct
|
||||
" window's location list will be populated when the list type is
|
||||
" 'location' and the user has moved windows since starting the job.
|
||||
call win_gotoid(self.winid)
|
||||
call self.custom_complete(a:job, a:exit_status, a:data)
|
||||
call win_gotoid(l:winid)
|
||||
endif
|
||||
|
||||
call self.show_errors(a:job, a:exit_status, a:data)
|
||||
endfunction
|
||||
|
||||
function state.show_status(job, exit_status) dict
|
||||
if self.statustype == ''
|
||||
return
|
||||
endif
|
||||
|
||||
if go#config#EchoCommandInfo()
|
||||
let prefix = ""
|
||||
if self.statustype != ''
|
||||
let prefix = '[' . self.statustype . '] '
|
||||
endif
|
||||
let prefix = '[' . self.statustype . '] '
|
||||
if a:exit_status == 0
|
||||
call go#util#EchoSuccess(prefix . "SUCCESS")
|
||||
else
|
||||
@ -102,10 +118,6 @@ function! go#job#Options(args)
|
||||
endif
|
||||
endif
|
||||
|
||||
if self.statustype == ''
|
||||
return
|
||||
endif
|
||||
|
||||
let status = {
|
||||
\ 'desc': 'last status',
|
||||
\ 'type': self.statustype,
|
||||
@ -127,10 +139,15 @@ function! go#job#Options(args)
|
||||
endfunction
|
||||
|
||||
if has_key(a:args, 'complete')
|
||||
let state.complete = a:args.complete
|
||||
let state.custom_complete = a:args.complete
|
||||
endif
|
||||
|
||||
function! s:start(args) dict
|
||||
if go#config#EchoCommandInfo() && self.statustype != ""
|
||||
let prefix = '[' . self.statustype . '] '
|
||||
call go#util#EchoSuccess(prefix . "dispatched")
|
||||
endif
|
||||
|
||||
if self.statustype != ''
|
||||
let status = {
|
||||
\ 'desc': 'current status',
|
||||
@ -164,7 +181,6 @@ function! go#job#Options(args)
|
||||
|
||||
if self.closed || has('nvim')
|
||||
call self.complete(a:job, self.exit_status, self.messages)
|
||||
call self.show_errors(a:job, self.exit_status, self.messages)
|
||||
endif
|
||||
endfunction
|
||||
" explicitly bind exit_cb to state so that within it, self will always refer
|
||||
@ -177,7 +193,6 @@ function! go#job#Options(args)
|
||||
if self.exited
|
||||
let job = ch_getjob(a:ch)
|
||||
call self.complete(job, self.exit_status, self.messages)
|
||||
call self.show_errors(job, self.exit_status, self.messages)
|
||||
endif
|
||||
endfunction
|
||||
" explicitly bind close_cb to state so that within it, self will
|
||||
@ -225,7 +240,7 @@ function! go#job#Options(args)
|
||||
|
||||
if empty(errors)
|
||||
" failed to parse errors, output the original content
|
||||
call go#util#EchoError(self.messages + [self.dir])
|
||||
call go#util#EchoError([self.dir] + self.messages)
|
||||
call win_gotoid(l:winid)
|
||||
return
|
||||
endif
|
||||
@ -254,10 +269,21 @@ function! go#job#Start(cmd, options)
|
||||
let l:options = s:neooptions(l:options)
|
||||
endif
|
||||
|
||||
" Verify that the working directory for the job actually exists. Return
|
||||
" early if the directory does not exist. This helps avoid errors when
|
||||
" working with plugins that use virtual files that don't actually exist on
|
||||
" the file system.
|
||||
let filedir = expand("%:p:h")
|
||||
if has_key(l:options, 'cwd') && !isdirectory(l:options.cwd)
|
||||
return
|
||||
elseif !isdirectory(filedir)
|
||||
return
|
||||
endif
|
||||
|
||||
if !has_key(l:options, 'cwd')
|
||||
" pre start
|
||||
let dir = getcwd()
|
||||
execute l:cd fnameescape(expand("%:p:h"))
|
||||
execute l:cd fnameescape(filedir)
|
||||
endif
|
||||
|
||||
if has_key(l:options, '_start')
|
||||
@ -267,11 +293,10 @@ function! go#job#Start(cmd, options)
|
||||
unlet l:options._start
|
||||
endif
|
||||
|
||||
|
||||
if has('nvim')
|
||||
let l:input = []
|
||||
if has_key(l:options, 'in_io') && l:options.in_io ==# 'file' && !empty(l:options.in_name)
|
||||
let l:input = readfile(l:options.in_name, 1)
|
||||
if has_key(a:options, 'in_io') && a:options.in_io ==# 'file' && !empty(a:options.in_name)
|
||||
let l:input = readfile(a:options.in_name, "b")
|
||||
endif
|
||||
|
||||
let job = jobstart(a:cmd, l:options)
|
||||
@ -306,49 +331,77 @@ function! s:neooptions(options)
|
||||
continue
|
||||
endif
|
||||
|
||||
" dealing with the channel lines of Neovim sucks. The docs (:help
|
||||
" channel-lines) say:
|
||||
" stream event handlers may receive partial (incomplete) lines. For a
|
||||
" given invocation of on_stdout etc, `a:data` is not guaranteed to end
|
||||
" with a newline.
|
||||
" - `abcdefg` may arrive as `['abc']`, `['defg']`.
|
||||
" - `abc\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`,
|
||||
" `['','efg']`, or even `['ab']`, `['c','efg']`.
|
||||
if key == 'callback'
|
||||
let l:options['callback'] = a:options['callback']
|
||||
|
||||
if !has_key(a:options, 'out_cb')
|
||||
let l:options['stdout_buffered'] = v:true
|
||||
|
||||
function! s:callback2on_stdout(ch, data, event) dict
|
||||
let l:data = a:data
|
||||
let l:data[0] = self.stdout_buf . l:data[0]
|
||||
let self.stdout_buf = ""
|
||||
" a single empty string means EOF was reached.
|
||||
if len(a:data) == 1 && a:data[0] == ''
|
||||
" when there's nothing buffered, return early so that an
|
||||
" erroneous message will not be added.
|
||||
if self.stdout_buf == ''
|
||||
return
|
||||
endif
|
||||
|
||||
if l:data[-1] != ""
|
||||
let l:data = [self.stdout_buf]
|
||||
let self.stdout_buf = ''
|
||||
else
|
||||
let l:data = copy(a:data)
|
||||
let l:data[0] = self.stdout_buf . l:data[0]
|
||||
|
||||
" The last element may be a partial line; save it for next time.
|
||||
let self.stdout_buf = l:data[-1]
|
||||
|
||||
let l:data = l:data[:-2]
|
||||
|
||||
if len(l:data) == 0
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:data = l:data[:-2]
|
||||
if len(l:data) == 0
|
||||
return
|
||||
endif
|
||||
|
||||
call self.callback(a:ch, join(l:data, "\n"))
|
||||
for l:msg in l:data
|
||||
call self.callback(a:ch, l:msg)
|
||||
endfor
|
||||
endfunction
|
||||
let l:options['on_stdout'] = function('s:callback2on_stdout', [], l:options)
|
||||
endif
|
||||
|
||||
if !has_key(a:options, 'err_cb')
|
||||
let l:options['stderr_buffered'] = v:true
|
||||
|
||||
function! s:callback2on_stderr(ch, data, event) dict
|
||||
let l:data = a:data
|
||||
let l:data[0] = self.stderr_buf . l:data[0]
|
||||
let self.stderr_buf = ""
|
||||
" a single empty string means EOF was reached.
|
||||
if len(a:data) == 1 && a:data[0] == ''
|
||||
" when there's nothing buffered, return early so that an
|
||||
" erroneous message will not be added.
|
||||
if self.stderr_buf == ''
|
||||
return
|
||||
endif
|
||||
let l:data = [self.stderr_buf]
|
||||
let self.stderr_buf = ''
|
||||
else
|
||||
let l:data = copy(a:data)
|
||||
let l:data[0] = self.stderr_buf . l:data[0]
|
||||
|
||||
if l:data[-1] != ""
|
||||
" The last element may be a partial line; save it for next time.
|
||||
let self.stderr_buf = l:data[-1]
|
||||
|
||||
let l:data = l:data[:-2]
|
||||
if len(l:data) == 0
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:data = l:data[:-2]
|
||||
if len(l:data) == 0
|
||||
return
|
||||
endif
|
||||
|
||||
call self.callback(a:ch, join(l:data, "\n"))
|
||||
for l:msg in l:data
|
||||
call self.callback(a:ch, l:msg)
|
||||
endfor
|
||||
endfunction
|
||||
let l:options['on_stderr'] = function('s:callback2on_stderr', [], l:options)
|
||||
endif
|
||||
@ -358,22 +411,32 @@ function! s:neooptions(options)
|
||||
|
||||
if key == 'out_cb'
|
||||
let l:options['out_cb'] = a:options['out_cb']
|
||||
let l:options['stdout_buffered'] = v:true
|
||||
function! s:on_stdout(ch, data, event) dict
|
||||
let l:data = a:data
|
||||
let l:data[0] = self.stdout_buf . l:data[0]
|
||||
let self.stdout_buf = ""
|
||||
" a single empty string means EOF was reached.
|
||||
if len(a:data) == 1 && a:data[0] == ''
|
||||
" when there's nothing buffered, return early so that an
|
||||
" erroneous message will not be added.
|
||||
if self.stdout_buf == ''
|
||||
return
|
||||
endif
|
||||
let l:data = [self.stdout_buf]
|
||||
let self.stdout_buf = ''
|
||||
else
|
||||
let l:data = copy(a:data)
|
||||
let l:data[0] = self.stdout_buf . l:data[0]
|
||||
|
||||
if l:data[-1] != ""
|
||||
" The last element may be a partial line; save it for next time.
|
||||
let self.stdout_buf = l:data[-1]
|
||||
|
||||
let l:data = l:data[:-2]
|
||||
if len(l:data) == 0
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:data = l:data[:-2]
|
||||
if len(l:data) == 0
|
||||
return
|
||||
endif
|
||||
|
||||
call self.out_cb(a:ch, join(l:data, "\n"))
|
||||
for l:msg in l:data
|
||||
call self.out_cb(a:ch, l:msg)
|
||||
endfor
|
||||
endfunction
|
||||
let l:options['on_stdout'] = function('s:on_stdout', [], l:options)
|
||||
|
||||
@ -382,22 +445,32 @@ function! s:neooptions(options)
|
||||
|
||||
if key == 'err_cb'
|
||||
let l:options['err_cb'] = a:options['err_cb']
|
||||
let l:options['stderr_buffered'] = v:true
|
||||
function! s:on_stderr(ch, data, event) dict
|
||||
let l:data = a:data
|
||||
let l:data[0] = self.stderr_buf . l:data[0]
|
||||
let self.stderr_buf = ""
|
||||
" a single empty string means EOF was reached.
|
||||
if len(a:data) == 1 && a:data[0] == ''
|
||||
" when there's nothing buffered, return early so that an
|
||||
" erroneous message will not be added.
|
||||
if self.stderr_buf == ''
|
||||
return
|
||||
endif
|
||||
let l:data = [self.stderr_buf]
|
||||
let self.stderr_buf = ''
|
||||
else
|
||||
let l:data = copy(a:data)
|
||||
let l:data[0] = self.stderr_buf . l:data[0]
|
||||
|
||||
if l:data[-1] != ""
|
||||
" The last element may be a partial line; save it for next time.
|
||||
let self.stderr_buf = l:data[-1]
|
||||
|
||||
let l:data = l:data[:-2]
|
||||
if len(l:data) == 0
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:data = l:data[:-2]
|
||||
if len(l:data) == 0
|
||||
return
|
||||
endif
|
||||
|
||||
call self.err_cb(a:ch, join(l:data, "\n"))
|
||||
for l:msg in l:data
|
||||
call self.err_cb(a:ch, l:msg)
|
||||
endfor
|
||||
endfunction
|
||||
let l:options['on_stderr'] = function('s:on_stderr', [], l:options)
|
||||
|
||||
@ -418,6 +491,12 @@ function! s:neooptions(options)
|
||||
continue
|
||||
endif
|
||||
|
||||
if key == 'stoponexit'
|
||||
if a:options['stoponexit'] == ''
|
||||
let l:options['detach'] = 1
|
||||
endif
|
||||
continue
|
||||
endif
|
||||
endfor
|
||||
return l:options
|
||||
endfunction
|
||||
|
@ -42,7 +42,7 @@ function! go#lint#Gometa(autosave, ...) abort
|
||||
|
||||
" Include only messages for the active buffer for autosave.
|
||||
let include = [printf('--include=^%s:.*$', fnamemodify(expand('%:p'), ":."))]
|
||||
if go#util#has_job() || has('nvim')
|
||||
if go#util#has_job()
|
||||
let include = [printf('--include=^%s:.*$', expand('%:p:t'))]
|
||||
endif
|
||||
let cmd += include
|
||||
@ -56,7 +56,7 @@ function! go#lint#Gometa(autosave, ...) abort
|
||||
|
||||
let cmd += goargs
|
||||
|
||||
if go#util#has_job() || has('nvim')
|
||||
if go#util#has_job()
|
||||
call s:lint_job({'cmd': cmd}, a:autosave)
|
||||
return
|
||||
endif
|
||||
@ -207,36 +207,10 @@ function! s:lint_job(args, autosave)
|
||||
let l:opts.for = "GoMetaLinterAutoSave"
|
||||
endif
|
||||
|
||||
let l:cbs = go#job#Options(l:opts)
|
||||
|
||||
if a:autosave
|
||||
" move to the window that was active before processing the errors, because
|
||||
" the user may have moved around within the window or even moved to a
|
||||
" different window since saving. Moving back to current window as of the
|
||||
" start of this function avoids the perception that the quickfix window
|
||||
" steals focus when linting takes a while.
|
||||
|
||||
function! s:exit_cb(next, job, exitval)
|
||||
let l:winid = win_getid(winnr())
|
||||
call call(a:next, [a:job, a:exitval])
|
||||
call win_gotoid(l:winid)
|
||||
endfunction
|
||||
" wrap l:cbs.exit_cb in s:exit_cb.
|
||||
let l:cbs.exit_cb = funcref('s:exit_cb', [l:cbs.exit_cb])
|
||||
|
||||
function! s:close_cb(next, ch)
|
||||
let l:winid = win_getid(winnr())
|
||||
call call(a:next, [a:ch])
|
||||
call win_gotoid(l:winid)
|
||||
endfunction
|
||||
" wrap l:cbs.close_cb in s:close_cb.
|
||||
let l:cbs.close_cb = funcref('s:close_cb', [l:cbs.close_cb])
|
||||
endif
|
||||
|
||||
" autowrite is not enabled for jobs
|
||||
call go#cmd#autowrite()
|
||||
|
||||
call go#job#Start(a:args.cmd, l:cbs)
|
||||
call go#job#Spawn(a:args.cmd, l:opts)
|
||||
endfunction
|
||||
|
||||
" vim: sw=2 ts=2 et
|
||||
|
@ -141,6 +141,7 @@ let s:default_list_type_commands = {
|
||||
\ "GoLint": "quickfix",
|
||||
\ "GoMetaLinter": "quickfix",
|
||||
\ "GoMetaLinterAutoSave": "locationlist",
|
||||
\ "GoModFmt": "locationlist",
|
||||
\ "GoModifyTags": "locationlist",
|
||||
\ "GoRename": "quickfix",
|
||||
\ "GoRun": "quickfix",
|
||||
|
140
sources_non_forked/vim-go/autoload/go/mod.vim
Normal file
140
sources_non_forked/vim-go/autoload/go/mod.vim
Normal file
@ -0,0 +1,140 @@
|
||||
let s:go_major_version = ""
|
||||
|
||||
function! go#mod#Format() abort
|
||||
" go mod only exists in `v1.11`
|
||||
if empty(s:go_major_version)
|
||||
let tokens = matchlist(go#util#System("go version"), '\d\+.\(\d\+\) ')
|
||||
let s:go_major_version = str2nr(tokens[1])
|
||||
endif
|
||||
|
||||
if s:go_major_version < "11"
|
||||
call go#util#EchoError("Go v1.11 is required to format go.mod file")
|
||||
return
|
||||
endif
|
||||
|
||||
let fname = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||
|
||||
" Save cursor position and many other things.
|
||||
let l:curw = winsaveview()
|
||||
|
||||
" Write current unsaved buffer to a temp file
|
||||
let l:tmpname = tempname() . '.mod'
|
||||
call writefile(go#util#GetLines(), l:tmpname)
|
||||
if go#util#IsWin()
|
||||
let l:tmpname = tr(l:tmpname, '\', '/')
|
||||
endif
|
||||
|
||||
let current_col = col('.')
|
||||
let l:args = ['go', 'mod', 'edit', '--fmt', l:tmpname]
|
||||
let [l:out, l:err] = go#util#Exec(l:args)
|
||||
let diff_offset = len(readfile(l:tmpname)) - line('$')
|
||||
|
||||
if l:err == 0
|
||||
call go#mod#update_file(l:tmpname, fname)
|
||||
else
|
||||
let errors = s:parse_errors(fname, l:out)
|
||||
call s:show_errors(errors)
|
||||
endif
|
||||
|
||||
" We didn't use the temp file, so clean up
|
||||
call delete(l:tmpname)
|
||||
|
||||
" Restore our cursor/windows positions.
|
||||
call winrestview(l:curw)
|
||||
|
||||
" be smart and jump to the line the new statement was added/removed
|
||||
call cursor(line('.') + diff_offset, current_col)
|
||||
|
||||
" Syntax highlighting breaks less often.
|
||||
syntax sync fromstart
|
||||
endfunction
|
||||
|
||||
" update_file updates the target file with the given formatted source
|
||||
function! go#mod#update_file(source, target)
|
||||
" remove undo point caused via BufWritePre
|
||||
try | silent undojoin | catch | endtry
|
||||
|
||||
let old_fileformat = &fileformat
|
||||
if exists("*getfperm")
|
||||
" save file permissions
|
||||
let original_fperm = getfperm(a:target)
|
||||
endif
|
||||
|
||||
call rename(a:source, a:target)
|
||||
|
||||
" restore file permissions
|
||||
if exists("*setfperm") && original_fperm != ''
|
||||
call setfperm(a:target , original_fperm)
|
||||
endif
|
||||
|
||||
" reload buffer to reflect latest changes
|
||||
silent edit!
|
||||
|
||||
let &fileformat = old_fileformat
|
||||
let &syntax = &syntax
|
||||
|
||||
let l:listtype = go#list#Type("GoModFmt")
|
||||
|
||||
" the title information was introduced with 7.4-2200
|
||||
" https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640
|
||||
if has('patch-7.4.2200')
|
||||
" clean up previous list
|
||||
if l:listtype == "quickfix"
|
||||
let l:list_title = getqflist({'title': 1})
|
||||
else
|
||||
let l:list_title = getloclist(0, {'title': 1})
|
||||
endif
|
||||
else
|
||||
" can't check the title, so assume that the list was for go fmt.
|
||||
let l:list_title = {'title': 'Format'}
|
||||
endif
|
||||
|
||||
if has_key(l:list_title, "title") && l:list_title['title'] == "Format"
|
||||
call go#list#Clean(l:listtype)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" parse_errors parses the given errors and returns a list of parsed errors
|
||||
function! s:parse_errors(filename, content) abort
|
||||
let splitted = split(a:content, '\n')
|
||||
|
||||
" list of errors to be put into location list
|
||||
let errors = []
|
||||
for line in splitted
|
||||
let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\s*\(.*\)')
|
||||
if !empty(tokens)
|
||||
call add(errors,{
|
||||
\"filename": a:filename,
|
||||
\"lnum": tokens[2],
|
||||
\"text": tokens[3],
|
||||
\ })
|
||||
endif
|
||||
endfor
|
||||
|
||||
return errors
|
||||
endfunction
|
||||
|
||||
" show_errors opens a location list and shows the given errors. If the given
|
||||
" errors is empty, it closes the the location list
|
||||
function! s:show_errors(errors) abort
|
||||
let l:listtype = go#list#Type("GoModFmt")
|
||||
if !empty(a:errors)
|
||||
call go#list#Populate(l:listtype, a:errors, 'Format')
|
||||
call go#util#EchoError("GoModFmt returned error")
|
||||
endif
|
||||
|
||||
" this closes the window if there are no errors or it opens
|
||||
" it if there is any
|
||||
call go#list#Window(l:listtype, len(a:errors))
|
||||
endfunction
|
||||
|
||||
function! go#mod#ToggleModFmtAutoSave() abort
|
||||
if go#config#ModFmtAutosave()
|
||||
call go#config#SetModFmtAutosave(0)
|
||||
call go#util#EchoProgress("auto mod fmt disabled")
|
||||
return
|
||||
end
|
||||
|
||||
call go#config#SetModFmtAutosave(1)
|
||||
call go#util#EchoProgress("auto mod fmt enabled")
|
||||
endfunction
|
@ -27,8 +27,7 @@ function! go#rename#Rename(bang, ...) abort
|
||||
let offset = printf('%s:#%d', fname, pos)
|
||||
let cmd = [bin_path, "-offset", offset, "-to", to_identifier, '-tags', go#config#BuildTags()]
|
||||
|
||||
if go#util#has_job() || has('nvim')
|
||||
call go#util#EchoProgress(printf("renaming to '%s' ...", to_identifier))
|
||||
if go#util#has_job()
|
||||
call s:rename_job({
|
||||
\ 'cmd': cmd,
|
||||
\ 'bang': a:bang,
|
||||
|
@ -0,0 +1,9 @@
|
||||
package complete
|
||||
|
||||
type T struct {
|
||||
V string
|
||||
}
|
||||
|
||||
func Example(s string) {
|
||||
Example("")
|
||||
}
|
@ -26,19 +26,11 @@ function! go#test#Test(bang, compile, ...) abort
|
||||
call add(args, printf("-timeout=%s", timeout))
|
||||
endif
|
||||
|
||||
if go#config#EchoCommandInfo()
|
||||
if a:compile
|
||||
call go#util#EchoProgress("compiling tests ...")
|
||||
else
|
||||
call go#util#EchoProgress("testing...")
|
||||
endif
|
||||
endif
|
||||
|
||||
if has('nvim') && go#config#TermEnabled()
|
||||
call go#term#new(a:bang, ["go"] + args)
|
||||
endif
|
||||
|
||||
if go#util#has_job() || has('nvim')
|
||||
if go#util#has_job()
|
||||
" use vim's job functionality to call it asynchronously
|
||||
let job_options = {
|
||||
\ 'bang': a:bang,
|
||||
@ -55,6 +47,14 @@ function! go#test#Test(bang, compile, ...) abort
|
||||
return
|
||||
endif
|
||||
|
||||
if go#config#EchoCommandInfo()
|
||||
if a:compile
|
||||
call go#util#EchoProgress("compiling tests ...")
|
||||
else
|
||||
call go#util#EchoProgress("testing...")
|
||||
endif
|
||||
endif
|
||||
|
||||
call go#cmd#autowrite()
|
||||
redraw
|
||||
|
||||
@ -152,12 +152,12 @@ function! s:errorformat() abort
|
||||
" each level of test indents the test output 4 spaces. Capturing groups
|
||||
" (e.g. \(\)) cannot be used in an errorformat, but non-capturing groups can
|
||||
" (e.g. \%(\)).
|
||||
let indent = '%\\%( %\\)%#'
|
||||
let indent = '%\\%( %\\)'
|
||||
|
||||
" ignore `go test -v` output for starting tests
|
||||
let format = "%-G=== RUN %.%#"
|
||||
" ignore `go test -v` output for passing tests
|
||||
let format .= ",%-G" . indent . "--- PASS: %.%#"
|
||||
let format .= ",%-G" . indent . "%#--- PASS: %.%#"
|
||||
|
||||
" Match failure lines.
|
||||
"
|
||||
@ -167,24 +167,25 @@ function! s:errorformat() abort
|
||||
" e.g.:
|
||||
" '--- FAIL: TestSomething (0.00s)'
|
||||
if show_name
|
||||
let format .= ",%G" . indent . "--- FAIL: %m (%.%#)"
|
||||
let format .= ",%G" . indent . "%#--- FAIL: %m (%.%#)"
|
||||
else
|
||||
let format .= ",%-G" . indent . "--- FAIL: %.%#"
|
||||
let format .= ",%-G" . indent . "%#--- FAIL: %.%#"
|
||||
endif
|
||||
|
||||
" Go 1.10 test output {{{1
|
||||
" Matches test output lines.
|
||||
"
|
||||
" All test output lines start with the test indentation and a tab, followed
|
||||
" by the filename, a colon, the line number, another colon, a space, and the
|
||||
" message. e.g.:
|
||||
" '\ttime_test.go:30: Likely problem: the time zone files have not been installed.'
|
||||
let format .= ",%A" . indent . "%\\t%\\+%f:%l: %m"
|
||||
let format .= ",%A" . indent . "%#%\\t%\\+%f:%l: %m"
|
||||
" also match lines that don't have a message (i.e. the message begins with a
|
||||
" newline or is the empty string):
|
||||
" e.g.:
|
||||
" t.Errorf("\ngot %v; want %v", actual, expected)
|
||||
" t.Error("")
|
||||
let format .= ",%A" . indent . "%\\t%\\+%f:%l: "
|
||||
let format .= ",%A" . indent . "%#%\\t%\\+%f:%l: "
|
||||
|
||||
" Match the 2nd and later lines of multi-line output. These lines are
|
||||
" indented the number of spaces for the level of nesting of the test,
|
||||
@ -197,7 +198,17 @@ function! s:errorformat() abort
|
||||
" indicate that they're multiple lines of output, but in that case the lines
|
||||
" get concatenated in the quickfix list, which is not what users typically
|
||||
" want when writing a newline into their test output.
|
||||
let format .= ",%G" . indent . "%\\t%\\{2}%m"
|
||||
let format .= ",%G" . indent . "%#%\\t%\\{2}%m"
|
||||
" }}}1
|
||||
|
||||
" Go 1.11 test output {{{1
|
||||
" Match test output lines similarly to Go 1.10 test output lines, but they
|
||||
" use an indent level where the Go 1.10 test output uses tabs, so they'll
|
||||
" always have at least one level indentation...
|
||||
let format .= ",%A" . indent . "%\\+%f:%l: %m"
|
||||
let format .= ",%A" . indent . "%\\+%f:%l: "
|
||||
let format .= ",%G" . indent . "%\\{2\\,}%m"
|
||||
" }}}1
|
||||
|
||||
" set the format for panics.
|
||||
|
||||
@ -261,16 +272,16 @@ function! s:errorformat() abort
|
||||
let format .= ",%-Cexit status %[0-9]%\\+"
|
||||
"let format .= ",exit status %[0-9]%\\+"
|
||||
|
||||
" Match and ignore exit failure lines whether part of a multi-line message
|
||||
" Match and ignore failure lines whether part of a multi-line message
|
||||
" or not, because these lines sometimes come before and sometimes after
|
||||
" panic stacktraces.
|
||||
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.
|
||||
" match compiler errors.
|
||||
" These are very smilar to errors from <=go1.10 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
|
||||
|
@ -74,7 +74,7 @@ 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'},
|
||||
\ {'lnum': 6, 'bufnr': 16, 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'Errorf format %v reads arg #1, but call has 0 args'},
|
||||
\ ]
|
||||
call s:test('veterror/veterror.go', expected)
|
||||
endfunc
|
||||
|
@ -76,12 +76,12 @@ function! go#tool#Imports() abort
|
||||
return imports
|
||||
endfunction
|
||||
|
||||
function! go#tool#Info() abort
|
||||
function! go#tool#Info(showstatus) abort
|
||||
let l:mode = go#config#InfoMode()
|
||||
if l:mode == 'gocode'
|
||||
call go#complete#Info()
|
||||
call go#complete#Info(a:showstatus)
|
||||
elseif l:mode == 'guru'
|
||||
call go#guru#DescribeInfo()
|
||||
call go#guru#DescribeInfo(a:showstatus)
|
||||
else
|
||||
call go#util#EchoError('go_info_mode value: '. l:mode .' is not valid. Valid values are: [gocode, guru]')
|
||||
endif
|
||||
|
@ -64,6 +64,10 @@ endfunction
|
||||
" The (optional) first parameter 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
|
||||
if has('nvim')
|
||||
return 1
|
||||
endif
|
||||
|
||||
" 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")
|
||||
|
Reference in New Issue
Block a user