mirror of
https://github.com/amix/vimrc
synced 2025-06-16 01:25:00 +08:00
Updated plugins
This commit is contained in:
@ -14,12 +14,12 @@ else
|
||||
let g:ctrlp_ext_vars = [s:go_decls_var]
|
||||
endif
|
||||
|
||||
function! ctrlp#decls#init()
|
||||
function! ctrlp#decls#init() abort
|
||||
cal s:enable_syntax()
|
||||
return s:decls
|
||||
endfunction
|
||||
|
||||
function! ctrlp#decls#exit()
|
||||
function! ctrlp#decls#exit() abort
|
||||
unlet! s:decls s:current_dir s:target
|
||||
endfunction
|
||||
|
||||
@ -28,7 +28,7 @@ endfunction
|
||||
" a:mode the mode that has been chosen by pressing <cr> <c-v> <c-t> or <c-x>
|
||||
" the values are 'e', 'v', 't' and 'h', respectively
|
||||
" a:str the selected string
|
||||
function! ctrlp#decls#accept(mode, str)
|
||||
function! ctrlp#decls#accept(mode, str) abort
|
||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||
let dir = getcwd()
|
||||
try
|
||||
@ -56,7 +56,7 @@ function! ctrlp#decls#accept(mode, str)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! ctrlp#decls#enter()
|
||||
function! ctrlp#decls#enter() abort
|
||||
let s:current_dir = fnameescape(expand('%:p:h'))
|
||||
let s:decls = []
|
||||
|
||||
@ -130,7 +130,7 @@ function! ctrlp#decls#enter()
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
function! s:enable_syntax()
|
||||
function! s:enable_syntax() abort
|
||||
if !(has('syntax') && exists('g:syntax_on'))
|
||||
return
|
||||
endif
|
||||
@ -148,7 +148,7 @@ endfunction
|
||||
|
||||
let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
|
||||
|
||||
function! ctrlp#decls#cmd(mode, ...)
|
||||
function! ctrlp#decls#cmd(mode, ...) abort
|
||||
let s:mode = a:mode
|
||||
if a:0 && !empty(a:1)
|
||||
let s:target = a:1
|
||||
|
@ -4,7 +4,7 @@ if !exists("g:go_alternate_mode")
|
||||
endif
|
||||
|
||||
" Test alternates between the implementation of code and the test code.
|
||||
function! go#alternate#Switch(bang, cmd)
|
||||
function! go#alternate#Switch(bang, cmd) abort
|
||||
let file = expand('%')
|
||||
if empty(file)
|
||||
call go#util#EchoError("no buffer name")
|
||||
|
@ -11,7 +11,7 @@
|
||||
"
|
||||
" Options:
|
||||
"
|
||||
" g:go_asmfmt_autosave [default=1]
|
||||
" g:go_asmfmt_autosave [default=0]
|
||||
"
|
||||
" Flag to automatically call :Fmt when file is saved.
|
||||
|
||||
@ -19,7 +19,7 @@ let s:got_fmt_error = 0
|
||||
|
||||
" This is a trimmed-down version of the logic in fmt.vim.
|
||||
|
||||
function! go#asmfmt#Format()
|
||||
function! go#asmfmt#Format() abort
|
||||
" Save state.
|
||||
let l:curw = winsaveview()
|
||||
|
||||
@ -55,15 +55,15 @@ function! go#asmfmt#Format()
|
||||
call winrestview(l:curw)
|
||||
endfunction
|
||||
|
||||
function! go#asmfmt#ToggleAsmFmtAutoSave()
|
||||
if get(g:, "go_asmfmt_autosave", 1)
|
||||
let g:go_asmfmt_autosave = 0
|
||||
call go#util#EchoProgress("auto asmfmt disabled")
|
||||
function! go#asmfmt#ToggleAsmFmtAutoSave() abort
|
||||
if get(g:, "go_asmfmt_autosave", 0)
|
||||
let g:go_asmfmt_autosave = 1
|
||||
call go#util#EchoProgress("auto asmfmt enabled")
|
||||
return
|
||||
end
|
||||
|
||||
let g:go_asmfmt_autosave = 1
|
||||
call go#util#EchoProgress("auto asmfmt enabled")
|
||||
let g:go_asmfmt_autosave = 0
|
||||
call go#util#EchoProgress("auto asmfmt disabled")
|
||||
endfunction
|
||||
|
||||
" vim: sw=2 ts=2 et
|
||||
|
@ -1,19 +1,14 @@
|
||||
if !exists("g:go_dispatch_enabled")
|
||||
let g:go_dispatch_enabled = 0
|
||||
endif
|
||||
|
||||
function! go#cmd#autowrite()
|
||||
function! go#cmd#autowrite() abort
|
||||
if &autowrite == 1
|
||||
silent wall
|
||||
silent! wall
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
" Build builds the source code without producting any output binary. We live in
|
||||
" an editor so the best is to build it to catch errors and fix them. By
|
||||
" default it tries to call simply 'go build', but it first tries to get all
|
||||
" dependent files for the current folder and passes it to go build.
|
||||
function! go#cmd#Build(bang, ...)
|
||||
function! go#cmd#Build(bang, ...) abort
|
||||
" expand all wildcards(i.e: '%' to the current file name)
|
||||
let goargs = map(copy(a:000), "expand(v:val)")
|
||||
|
||||
@ -26,8 +21,18 @@ function! go#cmd#Build(bang, ...)
|
||||
" placeholder with the current folder (indicated with '.')
|
||||
let args = ["build"] + goargs + [".", "errors"]
|
||||
|
||||
" if we have nvim, call it asynchronously and return early ;)
|
||||
if has('nvim')
|
||||
if go#util#has_job()
|
||||
if get(g:, 'go_echo_command_info', 1)
|
||||
call go#util#EchoProgress("building dispatched ...")
|
||||
endif
|
||||
|
||||
call s:cmd_job({
|
||||
\ 'cmd': ['go'] + args,
|
||||
\ 'bang': a:bang,
|
||||
\})
|
||||
return
|
||||
elseif has('nvim')
|
||||
" if we have nvim, call it asynchronously and return early ;)
|
||||
call go#util#EchoProgress("building dispatched ...")
|
||||
call go#jobcontrol#Spawn(a:bang, "build", args)
|
||||
return
|
||||
@ -45,10 +50,7 @@ function! go#cmd#Build(bang, ...)
|
||||
let dir = getcwd()
|
||||
try
|
||||
execute cd . fnameescape(expand("%:p:h"))
|
||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
||||
call go#util#EchoProgress("building dispatched ...")
|
||||
silent! exe 'Make'
|
||||
elseif l:listtype == "locationlist"
|
||||
if l:listtype == "locationlist"
|
||||
silent! exe 'lmake!'
|
||||
else
|
||||
silent! exe 'make!'
|
||||
@ -60,11 +62,8 @@ function! go#cmd#Build(bang, ...)
|
||||
|
||||
let errors = go#list#Get(l:listtype)
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
|
||||
if !empty(errors)
|
||||
if !a:bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
endif
|
||||
if !empty(errors) && !a:bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
else
|
||||
call go#util#EchoSuccess("[build] SUCCESS")
|
||||
endif
|
||||
@ -75,7 +74,7 @@ endfunction
|
||||
|
||||
|
||||
" Run runs the current file (and their dependencies if any) in a new terminal.
|
||||
function! go#cmd#RunTerm(bang, mode, files)
|
||||
function! go#cmd#RunTerm(bang, mode, files) abort
|
||||
if empty(a:files)
|
||||
let cmd = "go run ". go#util#Shelljoin(go#tool#Files())
|
||||
else
|
||||
@ -88,12 +87,18 @@ endfunction
|
||||
" This is intented to test small programs and play with them. It's not
|
||||
" suitable for long running apps, because vim is blocking by default and
|
||||
" calling long running apps will block the whole UI.
|
||||
function! go#cmd#Run(bang, ...)
|
||||
function! go#cmd#Run(bang, ...) abort
|
||||
if has('nvim')
|
||||
call go#cmd#RunTerm(a:bang, '', a:000)
|
||||
return
|
||||
endif
|
||||
|
||||
if go#util#has_job()
|
||||
" NOTE(arslan): 'term': 'open' case is not implement for +jobs. This means
|
||||
" executions waiting for stdin will not work. That's why we don't do
|
||||
" anything. Once this is implemented we're going to make :GoRun async
|
||||
endif
|
||||
|
||||
let old_gopath = $GOPATH
|
||||
let $GOPATH = go#path#Detect()
|
||||
|
||||
@ -119,9 +124,7 @@ function! go#cmd#Run(bang, ...)
|
||||
|
||||
let l:listtype = go#list#Type("quickfix")
|
||||
|
||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
||||
silent! exe 'Make'
|
||||
elseif l:listtype == "locationlist"
|
||||
if l:listtype == "locationlist"
|
||||
exe 'lmake!'
|
||||
else
|
||||
exe 'make!'
|
||||
@ -130,7 +133,7 @@ function! go#cmd#Run(bang, ...)
|
||||
let items = go#list#Get(l:listtype)
|
||||
let errors = go#tool#FilterValids(items)
|
||||
|
||||
call go#list#Populate(l:listtype, errors)
|
||||
call go#list#Populate(l:listtype, errors, &makeprg)
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
if !empty(errors) && !a:bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
@ -141,9 +144,28 @@ function! go#cmd#Run(bang, ...)
|
||||
endfunction
|
||||
|
||||
" Install installs the package by simple calling 'go install'. If any argument
|
||||
" is given(which are passed directly to 'go install') it tries to install those
|
||||
" packages. Errors are populated in the location window.
|
||||
function! go#cmd#Install(bang, ...)
|
||||
" is given(which are passed directly to 'go install') it tries to install
|
||||
" those packages. Errors are populated in the location window.
|
||||
function! go#cmd#Install(bang, ...) abort
|
||||
" use vim's job functionality to call it asynchronously
|
||||
if go#util#has_job()
|
||||
" expand all wildcards(i.e: '%' to the current file name)
|
||||
let goargs = map(copy(a:000), "expand(v:val)")
|
||||
|
||||
" escape all shell arguments before we pass it to make
|
||||
let goargs = go#util#Shelllist(goargs, 1)
|
||||
|
||||
if get(g:, 'go_echo_command_info', 1)
|
||||
call go#util#EchoProgress("installing dispatched ...")
|
||||
endif
|
||||
|
||||
call s:cmd_job({
|
||||
\ 'cmd': ['go', 'install'] + goargs,
|
||||
\ 'bang': a:bang,
|
||||
\})
|
||||
return
|
||||
endif
|
||||
|
||||
let old_gopath = $GOPATH
|
||||
let $GOPATH = go#path#Detect()
|
||||
let default_makeprg = &makeprg
|
||||
@ -159,10 +181,7 @@ function! go#cmd#Install(bang, ...)
|
||||
let dir = getcwd()
|
||||
try
|
||||
execute cd . fnameescape(expand("%:p:h"))
|
||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
||||
call go#util#EchoProgress("building dispatched ...")
|
||||
silent! exe 'Make'
|
||||
elseif l:listtype == "locationlist"
|
||||
if l:listtype == "locationlist"
|
||||
silent! exe 'lmake!'
|
||||
else
|
||||
silent! exe 'make!'
|
||||
@ -174,12 +193,10 @@ function! go#cmd#Install(bang, ...)
|
||||
|
||||
let errors = go#list#Get(l:listtype)
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
if !empty(errors)
|
||||
if !a:bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
endif
|
||||
if !empty(errors) && !a:bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
else
|
||||
redraws! | echon "vim-go: " | echohl Function | echon "installed to ". $GOPATH | echohl None
|
||||
call go#util#EchoSuccess("installed to ". $GOPATH)
|
||||
endif
|
||||
|
||||
let $GOPATH = old_gopath
|
||||
@ -189,7 +206,7 @@ endfunction
|
||||
" Test runs `go test` in the current directory. If compile is true, it'll
|
||||
" compile the tests instead of running them (useful to catch errors in the
|
||||
" test files). Any other argument is appendend to the final `go test` command
|
||||
function! go#cmd#Test(bang, compile, ...)
|
||||
function! go#cmd#Test(bang, compile, ...) abort
|
||||
let args = ["test"]
|
||||
|
||||
" don't run the test, only compile it. Useful to capture and fix errors.
|
||||
@ -199,9 +216,15 @@ function! go#cmd#Test(bang, compile, ...)
|
||||
endif
|
||||
|
||||
if a:0
|
||||
" expand all wildcards(i.e: '%' to the current file name)
|
||||
let goargs = map(copy(a:000), "expand(v:val)")
|
||||
if !has('nvim')
|
||||
let goargs = a:000
|
||||
|
||||
" do not expand for coverage mode as we're passing the arg ourself
|
||||
if a:1 != '-coverprofile'
|
||||
" expand all wildcards(i.e: '%' to the current file name)
|
||||
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
|
||||
|
||||
@ -212,13 +235,29 @@ function! go#cmd#Test(bang, compile, ...)
|
||||
call add(args, printf("-timeout=%s", timeout))
|
||||
endif
|
||||
|
||||
if a:compile
|
||||
echon "vim-go: " | echohl Identifier | echon "compiling tests ..." | echohl None
|
||||
else
|
||||
echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None
|
||||
if get(g:, 'go_echo_command_info', 1)
|
||||
if a:compile
|
||||
echon "vim-go: " | echohl Identifier | echon "compiling tests ..." | echohl None
|
||||
else
|
||||
echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None
|
||||
endif
|
||||
endif
|
||||
|
||||
if has('nvim')
|
||||
if go#util#has_job()
|
||||
" use vim's job functionality to call it asynchronously
|
||||
let job_args = {
|
||||
\ 'cmd': ['go'] + args,
|
||||
\ 'bang': a:bang,
|
||||
\ }
|
||||
|
||||
if a:compile
|
||||
let job_args['custom_cb'] = function('s:test_compile', [compile_file])
|
||||
endif
|
||||
|
||||
call s:cmd_job(job_args)
|
||||
return
|
||||
elseif has('nvim')
|
||||
" use nvims's job functionality
|
||||
if get(g:, 'go_term_enabled', 0)
|
||||
let id = go#term#new(a:bang, ["go"] + args)
|
||||
else
|
||||
@ -252,7 +291,7 @@ function! go#cmd#Test(bang, compile, ...)
|
||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
||||
let errors = go#tool#FilterValids(errors)
|
||||
|
||||
call go#list#Populate(l:listtype, errors)
|
||||
call go#list#Populate(l:listtype, errors, command)
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
if !empty(errors) && !a:bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
@ -276,7 +315,7 @@ endfunction
|
||||
|
||||
" Testfunc runs a single test that surrounds the current cursor position.
|
||||
" Arguments are passed to the `go test` command.
|
||||
function! go#cmd#TestFunc(bang, ...)
|
||||
function! go#cmd#TestFunc(bang, ...) abort
|
||||
" search flags legend (used only)
|
||||
" 'b' search backward instead of forward
|
||||
" 'c' accept a match at the cursor position
|
||||
@ -304,7 +343,7 @@ function! go#cmd#TestFunc(bang, ...)
|
||||
endfunction
|
||||
|
||||
" Generate runs 'go generate' in similar fashion to go#cmd#Build()
|
||||
function! go#cmd#Generate(bang, ...)
|
||||
function! go#cmd#Generate(bang, ...) abort
|
||||
let default_makeprg = &makeprg
|
||||
|
||||
let old_gopath = $GOPATH
|
||||
@ -322,9 +361,7 @@ function! go#cmd#Generate(bang, ...)
|
||||
let l:listtype = go#list#Type("quickfix")
|
||||
|
||||
echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None
|
||||
if g:go_dispatch_enabled && exists(':Make') == 2
|
||||
silent! exe 'Make'
|
||||
elseif l:listtype == "locationlist"
|
||||
if l:listtype == "locationlist"
|
||||
silent! exe 'lmake!'
|
||||
else
|
||||
silent! exe 'make!'
|
||||
@ -346,12 +383,79 @@ function! go#cmd#Generate(bang, ...)
|
||||
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",
|
||||
\})
|
||||
|
||||
" autowrite is not enabled for jobs
|
||||
call go#cmd#autowrite()
|
||||
|
||||
function! s:error_info_cb(job, exit_status, data) closure abort
|
||||
let status = {
|
||||
\ 'desc': 'last status',
|
||||
\ 'type': a:args.cmd[1],
|
||||
\ 'state': "success",
|
||||
\ }
|
||||
|
||||
if a:exit_status
|
||||
let status.state = "failed"
|
||||
endif
|
||||
|
||||
let elapsed_time = reltimestr(reltime(started_at))
|
||||
" strip whitespace
|
||||
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||
let status.state .= printf(" (%ss)", elapsed_time)
|
||||
|
||||
call go#statusline#Update(status_dir, status)
|
||||
endfunction
|
||||
|
||||
let a:args.error_info_cb = function('s:error_info_cb')
|
||||
let callbacks = go#job#Spawn(a:args)
|
||||
|
||||
let start_options = {
|
||||
\ 'callback': callbacks.callback,
|
||||
\ 'close_cb': callbacks.close_cb,
|
||||
\ }
|
||||
|
||||
" modify GOPATH if needed
|
||||
let old_gopath = $GOPATH
|
||||
let $GOPATH = go#path#Detect()
|
||||
|
||||
" pre start
|
||||
let dir = getcwd()
|
||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||
let jobdir = fnameescape(expand("%:p:h"))
|
||||
execute cd . jobdir
|
||||
|
||||
call job_start(a:args.cmd, start_options)
|
||||
|
||||
" post start
|
||||
execute cd . fnameescape(dir)
|
||||
let $GOPATH = old_gopath
|
||||
endfunction
|
||||
|
||||
|
||||
" test_compile is called when a GoTestCompile call is finished
|
||||
function! s:test_compile(test_file, job, exit_status, data) abort
|
||||
call delete(a:test_file)
|
||||
endfunction
|
||||
|
||||
" -----------------------
|
||||
" | Neovim job handlers |
|
||||
" -----------------------
|
||||
let s:test_compile_handlers = {}
|
||||
|
||||
function! s:test_compile_handler(job, exit_status, data)
|
||||
function! s:test_compile_handler(job, exit_status, data) abort
|
||||
if !has_key(s:test_compile_handlers, a:job.id)
|
||||
return
|
||||
endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
let s:sock_type = (has('win32') || has('win64')) ? 'tcp' : 'unix'
|
||||
|
||||
function! s:gocodeCurrentBuffer()
|
||||
function! s:gocodeCurrentBuffer() abort
|
||||
let buf = getline(1, '$')
|
||||
if &encoding != 'utf-8'
|
||||
let buf = map(buf, 'iconv(v:val, &encoding, "utf-8")')
|
||||
@ -16,7 +16,7 @@ function! s:gocodeCurrentBuffer()
|
||||
return file
|
||||
endfunction
|
||||
|
||||
function! s:gocodeCommand(cmd, preargs, args)
|
||||
function! s:gocodeCommand(cmd, preargs, args) abort
|
||||
for i in range(0, len(a:args) - 1)
|
||||
let a:args[i] = go#util#Shellescape(a:args[i])
|
||||
endfor
|
||||
@ -59,12 +59,12 @@ function! s:gocodeCommand(cmd, preargs, args)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:gocodeCurrentBufferOpt(filename)
|
||||
function! s:gocodeCurrentBufferOpt(filename) abort
|
||||
return '-in=' . a:filename
|
||||
endfunction
|
||||
|
||||
let s:optionsEnabled = 0
|
||||
function! s:gocodeEnableOptions()
|
||||
function! s:gocodeEnableOptions() abort
|
||||
if s:optionsEnabled
|
||||
return
|
||||
endif
|
||||
@ -78,14 +78,14 @@ function! s:gocodeEnableOptions()
|
||||
|
||||
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', 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))))
|
||||
endfunction
|
||||
|
||||
function! s:toBool(val)
|
||||
function! s:toBool(val) abort
|
||||
if a:val | return 'true ' | else | return 'false' | endif
|
||||
endfunction
|
||||
|
||||
function! s:gocodeAutocomplete()
|
||||
function! s:gocodeAutocomplete() abort
|
||||
call s:gocodeEnableOptions()
|
||||
|
||||
let filename = s:gocodeCurrentBuffer()
|
||||
@ -96,7 +96,7 @@ function! s:gocodeAutocomplete()
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! go#complete#GetInfo()
|
||||
function! go#complete#GetInfo() abort
|
||||
let offset = go#util#OffsetCursor()+1
|
||||
let filename = s:gocodeCurrentBuffer()
|
||||
let result = s:gocodeCommand('autocomplete',
|
||||
@ -137,7 +137,7 @@ function! go#complete#GetInfo()
|
||||
return ""
|
||||
endfunction
|
||||
|
||||
function! go#complete#Info(auto)
|
||||
function! go#complete#Info(auto) abort
|
||||
" auto is true if we were called by g:go_auto_type_info's autocmd
|
||||
let result = go#complete#GetInfo()
|
||||
if !empty(result)
|
||||
@ -147,12 +147,12 @@ function! go#complete#Info(auto)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:trim_bracket(val)
|
||||
function! s:trim_bracket(val) abort
|
||||
let a:val.word = substitute(a:val.word, '[(){}\[\]]\+$', '', '')
|
||||
return a:val
|
||||
endfunction
|
||||
|
||||
function! go#complete#Complete(findstart, base)
|
||||
function! go#complete#Complete(findstart, base) abort
|
||||
"findstart = 1 when we need to get the text length
|
||||
if a:findstart == 1
|
||||
execute "silent let g:gocomplete_completions = " . s:gocodeAutocomplete()
|
||||
@ -167,7 +167,7 @@ function! go#complete#Complete(findstart, base)
|
||||
endif
|
||||
endf
|
||||
|
||||
function! go#complete#ToggleAutoTypeInfo()
|
||||
function! go#complete#ToggleAutoTypeInfo() abort
|
||||
if get(g:, "go_auto_type_info", 0)
|
||||
let g:go_auto_type_info = 0
|
||||
call go#util#EchoProgress("auto type info disabled")
|
||||
|
@ -3,7 +3,7 @@ let s:toggle = 0
|
||||
" Buffer creates a new cover profile with 'go test -coverprofile' and changes
|
||||
" the current buffers highlighting to show covered and uncovered sections of
|
||||
" the code. If run again it clears the annotation.
|
||||
function! go#coverage#BufferToggle(bang, ...)
|
||||
function! go#coverage#BufferToggle(bang, ...) abort
|
||||
if s:toggle
|
||||
call go#coverage#Clear()
|
||||
return
|
||||
@ -20,7 +20,7 @@ endfunction
|
||||
" teh current buffers highlighting to show covered and uncovered sections of
|
||||
" the code. Calling it again reruns the tests and shows the last updated
|
||||
" coverage.
|
||||
function! go#coverage#Buffer(bang, ...)
|
||||
function! go#coverage#Buffer(bang, ...) 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")
|
||||
@ -43,8 +43,17 @@ function! go#coverage#Buffer(bang, ...)
|
||||
|
||||
let s:toggle = 1
|
||||
let l:tmpname = tempname()
|
||||
let args = [a:bang, 0, "-coverprofile", l:tmpname]
|
||||
|
||||
if go#util#has_job()
|
||||
call s:coverage_job({
|
||||
\ 'cmd': ['go', 'test', '-coverprofile', l:tmpname],
|
||||
\ 'custom_cb': function('s:coverage_callback', [l:tmpname]),
|
||||
\ 'bang': a:bang,
|
||||
\ })
|
||||
return
|
||||
endif
|
||||
|
||||
let args = [a:bang, 0, "-coverprofile", l:tmpname]
|
||||
if a:0
|
||||
call extend(args, a:000)
|
||||
endif
|
||||
@ -75,11 +84,8 @@ function! go#coverage#Buffer(bang, ...)
|
||||
endfunction
|
||||
|
||||
" Clear clears and resets the buffer annotation matches
|
||||
function! go#coverage#Clear()
|
||||
" only reset the syntax if the user has syntax enabled
|
||||
if !empty(&syntax)
|
||||
if exists("g:syntax_on") | syntax enable | endif
|
||||
endif
|
||||
function! go#coverage#Clear() abort
|
||||
call clearmatches()
|
||||
|
||||
if exists("s:toggle") | let s:toggle = 0 | endif
|
||||
|
||||
@ -87,25 +93,34 @@ function! go#coverage#Clear()
|
||||
if exists("#BufWinLeave#<buffer>")
|
||||
autocmd! BufWinLeave <buffer>
|
||||
endif
|
||||
|
||||
call clearmatches()
|
||||
endfunction
|
||||
|
||||
" Browser creates a new cover profile with 'go test -coverprofile' and opens
|
||||
" a new HTML coverage page from that profile in a new browser
|
||||
function! go#coverage#Browser(bang, ...)
|
||||
function! go#coverage#Browser(bang, ...) abort
|
||||
let l:tmpname = tempname()
|
||||
let args = [a:bang, 0, "-coverprofile", l:tmpname]
|
||||
if go#util#has_job()
|
||||
call s:coverage_job({
|
||||
\ 'cmd': ['go', 'test', '-coverprofile', l:tmpname],
|
||||
\ 'custom_cb': function('s:coverage_browser_callback', [l:tmpname]),
|
||||
\ 'bang': a:bang,
|
||||
\ })
|
||||
return
|
||||
endif
|
||||
|
||||
let args = [a:bang, 0, "-coverprofile", l:tmpname]
|
||||
if a:0
|
||||
call extend(args, a:000)
|
||||
endif
|
||||
|
||||
let id = call('go#cmd#Test', args)
|
||||
if has('nvim')
|
||||
call go#jobcontrol#AddHandler(function('s:coverage_browser_handler'))
|
||||
let s:coverage_browser_handler_jobs[id] = l:tmpname
|
||||
return
|
||||
endif
|
||||
|
||||
|
||||
if go#util#ShellError() == 0
|
||||
let openHTML = 'go tool cover -html='.l:tmpname
|
||||
call go#tool#ExecuteInDir(openHTML)
|
||||
@ -116,7 +131,7 @@ endfunction
|
||||
|
||||
" Parses a single line from the cover file generated via go test -coverprofile
|
||||
" and returns a single coverage profile block.
|
||||
function! go#coverage#parsegocoverline(line)
|
||||
function! go#coverage#parsegocoverline(line) abort
|
||||
" file:startline.col,endline.col numstmt count
|
||||
let mx = '\([^:]\+\):\(\d\+\)\.\(\d\+\),\(\d\+\)\.\(\d\+\)\s\(\d\+\)\s\(\d\+\)'
|
||||
let tokens = matchlist(a:line, mx)
|
||||
@ -133,7 +148,7 @@ endfunction
|
||||
|
||||
" Generates matches to be added to matchaddpos for the given coverage profile
|
||||
" block
|
||||
function! go#coverage#genmatch(cov)
|
||||
function! go#coverage#genmatch(cov) abort
|
||||
let color = 'goCoverageCovered'
|
||||
if a:cov.cnt == 0
|
||||
let color = 'goCoverageUncover'
|
||||
@ -183,7 +198,7 @@ function! go#coverage#genmatch(cov)
|
||||
endfunction
|
||||
|
||||
" Reads the given coverprofile file and annotates the current buffer
|
||||
function! go#coverage#overlay(file)
|
||||
function! go#coverage#overlay(file) abort
|
||||
if !filereadable(a:file)
|
||||
return
|
||||
endif
|
||||
@ -204,7 +219,7 @@ function! go#coverage#overlay(file)
|
||||
let cnt += 1
|
||||
endwhile
|
||||
|
||||
let fname = expand('%:t')
|
||||
let fname = expand('%')
|
||||
|
||||
" when called for a _test.go file, run the coverage for the actuall file
|
||||
" file
|
||||
@ -221,6 +236,9 @@ function! go#coverage#overlay(file)
|
||||
exe ":edit ". fnamemodify(fname, ":p")
|
||||
endif
|
||||
|
||||
" cov.file includes only the filename itself, without full path
|
||||
let fname = fnamemodify(fname, ":t")
|
||||
|
||||
for line in lines[1:]
|
||||
let cov = go#coverage#parsegocoverline(line)
|
||||
|
||||
@ -233,8 +251,6 @@ function! go#coverage#overlay(file)
|
||||
call extend(matches, go#coverage#genmatch(cov))
|
||||
endfor
|
||||
|
||||
syntax manual
|
||||
|
||||
" clear the matches if we leave the buffer
|
||||
autocmd BufWinLeave <buffer> call go#coverage#Clear()
|
||||
|
||||
@ -244,6 +260,78 @@ function! go#coverage#overlay(file)
|
||||
endfunction
|
||||
|
||||
|
||||
" ---------------------
|
||||
" | Vim job callbacks |
|
||||
" ---------------------
|
||||
"
|
||||
function s:coverage_job(args)
|
||||
" autowrite is not enabled for jobs
|
||||
call go#cmd#autowrite()
|
||||
|
||||
let status_dir = expand('%:p:h')
|
||||
function! s:error_info_cb(job, exit_status, data) closure
|
||||
let status = {
|
||||
\ 'desc': 'last status',
|
||||
\ 'type': "coverage",
|
||||
\ 'state': "finished",
|
||||
\ }
|
||||
|
||||
if a:exit_status
|
||||
let status.state = "failed"
|
||||
endif
|
||||
|
||||
call go#statusline#Update(status_dir, status)
|
||||
endfunction
|
||||
|
||||
let a:args.error_info_cb = function('s:error_info_cb')
|
||||
let callbacks = go#job#Spawn(a:args)
|
||||
|
||||
let start_options = {
|
||||
\ 'callback': callbacks.callback,
|
||||
\ 'close_cb': callbacks.close_cb,
|
||||
\ }
|
||||
|
||||
" modify GOPATH if needed
|
||||
let old_gopath = $GOPATH
|
||||
let $GOPATH = go#path#Detect()
|
||||
|
||||
" pre start
|
||||
let dir = getcwd()
|
||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||
let jobdir = fnameescape(expand("%:p:h"))
|
||||
execute cd . jobdir
|
||||
|
||||
call go#statusline#Update(status_dir, {
|
||||
\ 'desc': "current status",
|
||||
\ 'type': "coverage",
|
||||
\ 'state': "started",
|
||||
\})
|
||||
|
||||
call job_start(a:args.cmd, start_options)
|
||||
|
||||
" post start
|
||||
execute cd . fnameescape(dir)
|
||||
let $GOPATH = old_gopath
|
||||
endfunction
|
||||
|
||||
" coverage_callback is called when the coverage execution is finished
|
||||
function! s:coverage_callback(coverfile, job, exit_status, data)
|
||||
if a:exit_status == 0
|
||||
call go#coverage#overlay(a:coverfile)
|
||||
endif
|
||||
|
||||
call delete(a:coverfile)
|
||||
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)
|
||||
endif
|
||||
|
||||
call delete(a:coverfile)
|
||||
endfunction
|
||||
|
||||
" -----------------------
|
||||
" | Neovim job handlers |
|
||||
" -----------------------
|
||||
@ -251,7 +339,7 @@ endfunction
|
||||
let s:coverage_handler_jobs = {}
|
||||
let s:coverage_browser_handler_jobs = {}
|
||||
|
||||
function! s:coverage_handler(job, exit_status, data)
|
||||
function! s:coverage_handler(job, exit_status, data) abort
|
||||
if !has_key(s:coverage_handler_jobs, a:job.id)
|
||||
return
|
||||
endif
|
||||
@ -264,7 +352,7 @@ function! s:coverage_handler(job, exit_status, data)
|
||||
unlet s:coverage_handler_jobs[a:job.id]
|
||||
endfunction
|
||||
|
||||
function! s:coverage_browser_handler(job, exit_status, data)
|
||||
function! s:coverage_browser_handler(job, exit_status, data) abort
|
||||
if !has_key(s:coverage_browser_handler_jobs, a:job.id)
|
||||
return
|
||||
endif
|
||||
@ -279,4 +367,5 @@ function! s:coverage_browser_handler(job, exit_status, data)
|
||||
unlet s:coverage_browser_handler_jobs[a:job.id]
|
||||
endfunction
|
||||
|
||||
|
||||
" vim: sw=2 ts=2 et
|
||||
|
@ -1,7 +1,7 @@
|
||||
let s:go_stack = []
|
||||
let s:go_stack_level = 0
|
||||
|
||||
function! go#def#Jump(mode)
|
||||
function! go#def#Jump(mode) abort
|
||||
let old_gopath = $GOPATH
|
||||
let $GOPATH = go#path#Detect()
|
||||
|
||||
@ -27,42 +27,53 @@ function! go#def#Jump(mode)
|
||||
endif
|
||||
let command = printf("%s -f=%s -o=%s -t", bin_path, fname, go#util#OffsetCursor())
|
||||
let out = go#util#System(command)
|
||||
|
||||
" append the type information to the same line so our
|
||||
" jump_to_declaration() function can parse it. This makes it
|
||||
" compatible with guru definition as well too
|
||||
let out = join(split(out, '\n'), ':')
|
||||
if exists("l:tmpname")
|
||||
call delete(l:tmpname)
|
||||
endif
|
||||
|
||||
elseif bin_name == 'guru'
|
||||
let flags = ""
|
||||
let in = ""
|
||||
|
||||
if &modified
|
||||
let sep = go#util#LineEnding()
|
||||
let content = join(getline(1, '$'), sep)
|
||||
let in = fname . "\n" . strlen(content) . "\n" . content
|
||||
let flags .= " -modified"
|
||||
endif
|
||||
|
||||
let bin_path = go#path#CheckBinPath("guru")
|
||||
if empty(bin_path)
|
||||
let $GOPATH = old_gopath
|
||||
return
|
||||
endif
|
||||
|
||||
if exists('g:go_guru_tags')
|
||||
let tags = get(g:, 'go_guru_tags')
|
||||
let flags .= printf(" -tags %s", tags)
|
||||
endif
|
||||
|
||||
let fname = shellescape(fname.':#'.go#util#OffsetCursor())
|
||||
let command = printf("%s %s definition %s", bin_path, flags, fname)
|
||||
let cmd = [bin_path]
|
||||
let stdin_content = ""
|
||||
|
||||
if &modified
|
||||
let out = go#util#System(command, in)
|
||||
let sep = go#util#LineEnding()
|
||||
let content = join(getline(1, '$'), sep)
|
||||
let stdin_content = fname . "\n" . strlen(content) . "\n" . content
|
||||
call add(cmd, "-modified")
|
||||
endif
|
||||
|
||||
if exists('g:go_guru_tags')
|
||||
let tags = get(g:, 'go_guru_tags')
|
||||
call extend(cmd, ["-tags", tags])
|
||||
endif
|
||||
|
||||
let fname = fname.':#'.go#util#OffsetCursor()
|
||||
call extend(cmd, ["definition", fname])
|
||||
|
||||
if go#util#has_job()
|
||||
let l:spawn_args = {
|
||||
\ 'cmd': cmd,
|
||||
\ 'custom_cb': function('s:jump_to_declaration_cb', [a:mode, bin_name]),
|
||||
\ }
|
||||
|
||||
if &modified
|
||||
let l:spawn_args.input = stdin_content
|
||||
endif
|
||||
|
||||
call go#util#EchoProgress("searching declaration ...")
|
||||
|
||||
call s:def_job(spawn_args)
|
||||
return
|
||||
endif
|
||||
|
||||
let command = join(cmd, " ")
|
||||
if &modified
|
||||
let out = go#util#System(command, stdin_content)
|
||||
else
|
||||
let out = go#util#System(command)
|
||||
endif
|
||||
@ -76,13 +87,28 @@ function! go#def#Jump(mode)
|
||||
return
|
||||
endif
|
||||
|
||||
call s:jump_to_declaration(out, a:mode)
|
||||
call s:jump_to_declaration(out, a:mode, bin_name)
|
||||
let $GOPATH = old_gopath
|
||||
endfunction
|
||||
|
||||
function! s:jump_to_declaration(out, mode)
|
||||
function! s:jump_to_declaration_cb(mode, bin_name, job, exit_status, data) abort
|
||||
if a:exit_status != 0
|
||||
return
|
||||
endif
|
||||
|
||||
call s:jump_to_declaration(a:data[0], a:mode, a:bin_name)
|
||||
endfunction
|
||||
|
||||
function! s:jump_to_declaration(out, mode, bin_name) abort
|
||||
let final_out = a:out
|
||||
if a:bin_name == "godef"
|
||||
" append the type information to the same line so our we can parse it.
|
||||
" This makes it compatible with guru output.
|
||||
let final_out = join(split(a:out, '\n'), ':')
|
||||
endif
|
||||
|
||||
" strip line ending
|
||||
let out = split(a:out, go#util#LineEnding())[0]
|
||||
let out = split(final_out, go#util#LineEnding())[0]
|
||||
if go#util#IsWin()
|
||||
let parts = split(out, '\(^[a-zA-Z]\)\@<!:')
|
||||
else
|
||||
@ -120,19 +146,27 @@ function! s:jump_to_declaration(out, mode)
|
||||
if get(g:, 'go_def_reuse_buffer', 0) && bufloaded(filename) != 0 && bufwinnr(filename) != -1
|
||||
" jumpt to existing buffer if it exists
|
||||
execute bufwinnr(filename) . 'wincmd w'
|
||||
elseif a:mode == "tab"
|
||||
let &switchbuf = "usetab"
|
||||
if bufloaded(filename) == 0
|
||||
tab split
|
||||
else
|
||||
if &modified
|
||||
let cmd = 'hide edit'
|
||||
else
|
||||
let cmd = 'edit'
|
||||
endif
|
||||
elseif a:mode == "split"
|
||||
split
|
||||
elseif a:mode == "vsplit"
|
||||
vsplit
|
||||
endif
|
||||
|
||||
" open the file and jump to line and column
|
||||
exec 'edit' filename
|
||||
if a:mode == "tab"
|
||||
let &switchbuf = "usetab"
|
||||
if bufloaded(filename) == 0
|
||||
tab split
|
||||
endif
|
||||
elseif a:mode == "split"
|
||||
split
|
||||
elseif a:mode == "vsplit"
|
||||
vsplit
|
||||
endif
|
||||
|
||||
" open the file and jump to line and column
|
||||
exec cmd filename
|
||||
endif
|
||||
endif
|
||||
call cursor(line, col)
|
||||
|
||||
@ -142,7 +176,7 @@ function! s:jump_to_declaration(out, mode)
|
||||
let &switchbuf = old_switchbuf
|
||||
endfunction
|
||||
|
||||
function! go#def#SelectStackEntry()
|
||||
function! go#def#SelectStackEntry() abort
|
||||
let target_window = go#ui#GetReturnWindow()
|
||||
if empty(target_window)
|
||||
let target_window = winnr()
|
||||
@ -157,7 +191,7 @@ function! go#def#SelectStackEntry()
|
||||
call go#ui#CloseWindow()
|
||||
endfunction
|
||||
|
||||
function! go#def#StackUI()
|
||||
function! go#def#StackUI() abort
|
||||
if len(s:go_stack) == 0
|
||||
call go#util#EchoError("godef stack empty")
|
||||
return
|
||||
@ -192,12 +226,12 @@ function! go#def#StackUI()
|
||||
noremap <buffer> <silent> q :<C-U>call go#ui#CloseWindow()<CR>
|
||||
endfunction
|
||||
|
||||
function! go#def#StackClear(...)
|
||||
function! go#def#StackClear(...) abort
|
||||
let s:go_stack = []
|
||||
let s:go_stack_level = 0
|
||||
endfunction
|
||||
|
||||
function! go#def#StackPop(...)
|
||||
function! go#def#StackPop(...) abort
|
||||
if len(s:go_stack) == 0
|
||||
call go#util#EchoError("godef stack empty")
|
||||
return
|
||||
@ -218,7 +252,7 @@ function! go#def#StackPop(...)
|
||||
call go#def#Stack(newLevel + 1)
|
||||
endfunction
|
||||
|
||||
function! go#def#Stack(...)
|
||||
function! go#def#Stack(...) abort
|
||||
if len(s:go_stack) == 0
|
||||
call go#util#EchoError("godef stack empty")
|
||||
return
|
||||
@ -246,7 +280,13 @@ function! go#def#Stack(...)
|
||||
let target = s:go_stack[s:go_stack_level]
|
||||
|
||||
" jump
|
||||
exec 'edit' target["file"]
|
||||
if expand('%:p') != target["file"]
|
||||
if &modified
|
||||
exec 'hide edit' target["file"]
|
||||
else
|
||||
exec 'edit' target["file"]
|
||||
endif
|
||||
endif
|
||||
call cursor(target["line"], target["col"])
|
||||
normal! zz
|
||||
else
|
||||
@ -254,4 +294,27 @@ function! go#def#Stack(...)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function s:def_job(args) abort
|
||||
function! s:error_info_cb(job, exit_status, data) closure
|
||||
" do not print anything during async definition search&jump
|
||||
endfunction
|
||||
|
||||
let a:args.error_info_cb = function('s:error_info_cb')
|
||||
let callbacks = go#job#Spawn(a:args)
|
||||
|
||||
let start_options = {
|
||||
\ 'callback': callbacks.callback,
|
||||
\ 'close_cb': callbacks.close_cb,
|
||||
\ }
|
||||
|
||||
if &modified
|
||||
let l:tmpname = tempname()
|
||||
call writefile(split(a:args.input, "\n"), l:tmpname, "b")
|
||||
let l:start_options.in_io = "file"
|
||||
let l:start_options.in_name = l:tmpname
|
||||
endif
|
||||
|
||||
call job_start(a:args.cmd, start_options)
|
||||
endfunction
|
||||
|
||||
" vim: sw=2 ts=2 et
|
||||
|
@ -12,57 +12,39 @@ if !exists("g:go_doc_options")
|
||||
let g:go_doc_options = ""
|
||||
endif
|
||||
|
||||
" returns the package and exported name. exported name might be empty.
|
||||
" ie: fmt and Println
|
||||
" ie: github.com/fatih/set and New
|
||||
function! s:godocWord(args)
|
||||
if !executable('godoc')
|
||||
let msg = "godoc command not found."
|
||||
let msg .= " install with: go get golang.org/x/tools/cmd/godoc"
|
||||
call go#util#EchoWarning(msg)
|
||||
return []
|
||||
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
|
||||
call go#util#EchoError(json_out)
|
||||
return
|
||||
endif
|
||||
|
||||
let out = json_decode(json_out)
|
||||
if type(out) != type({})
|
||||
call go#util#EchoError("gogetdoc output is malformed")
|
||||
endif
|
||||
|
||||
let import = out["import"]
|
||||
let name = out["name"]
|
||||
|
||||
" if import is empty, it means we selected a package name
|
||||
if import ==# ""
|
||||
let godoc_url = "https://godoc.org/" . name
|
||||
else
|
||||
let godoc_url = "https://godoc.org/" . import . "#" . name
|
||||
endif
|
||||
|
||||
echo godoc_url
|
||||
|
||||
call go#tool#OpenBrowser(godoc_url)
|
||||
return
|
||||
endif
|
||||
|
||||
if !len(a:args)
|
||||
let oldiskeyword = &iskeyword
|
||||
setlocal iskeyword+=.
|
||||
let word = expand('<cword>')
|
||||
let &iskeyword = oldiskeyword
|
||||
let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g')
|
||||
let words = split(word, '\.\ze[^./]\+$')
|
||||
else
|
||||
let words = a:args
|
||||
endif
|
||||
|
||||
if !len(words)
|
||||
return []
|
||||
endif
|
||||
|
||||
let pkg = words[0]
|
||||
if len(words) == 1
|
||||
let exported_name = ""
|
||||
else
|
||||
let exported_name = words[1]
|
||||
endif
|
||||
|
||||
let packages = go#tool#Imports()
|
||||
|
||||
if has_key(packages, pkg)
|
||||
let pkg = packages[pkg]
|
||||
endif
|
||||
|
||||
return [pkg, exported_name]
|
||||
endfunction
|
||||
|
||||
function! s:godocNotFound(content)
|
||||
if len(a:content) == 0
|
||||
return 1
|
||||
endif
|
||||
|
||||
return a:content =~# '^.*: no such file or directory\n$'
|
||||
endfunction
|
||||
|
||||
function! go#doc#OpenBrowser(...)
|
||||
let pkgs = s:godocWord(a:000)
|
||||
if empty(pkgs)
|
||||
return
|
||||
@ -76,7 +58,7 @@ function! go#doc#OpenBrowser(...)
|
||||
call go#tool#OpenBrowser(godoc_url)
|
||||
endfunction
|
||||
|
||||
function! go#doc#Open(newmode, mode, ...)
|
||||
function! go#doc#Open(newmode, mode, ...) abort
|
||||
if len(a:000)
|
||||
" check if we have 'godoc' and use it automatically
|
||||
let bin_path = go#path#CheckBinPath('godoc')
|
||||
@ -87,34 +69,7 @@ function! go#doc#Open(newmode, mode, ...)
|
||||
let command = printf("%s %s", bin_path, join(a:000, ' '))
|
||||
let out = go#util#System(command)
|
||||
else
|
||||
" check if we have 'gogetdoc' and use it automatically
|
||||
let bin_path = go#path#CheckBinPath('gogetdoc')
|
||||
if empty(bin_path)
|
||||
return
|
||||
endif
|
||||
|
||||
let offset = go#util#OffsetCursor()
|
||||
let fname = expand("%:p:gs!\\!/!")
|
||||
let pos = shellescape(fname.':#'.offset)
|
||||
let command = printf("%s -pos %s", bin_path, pos)
|
||||
|
||||
if &modified
|
||||
" gogetdoc supports the same archive format as guru for dealing with
|
||||
" modified buffers.
|
||||
" use the -modified flag
|
||||
" write each archive entry on stdin as:
|
||||
" filename followed by newline
|
||||
" file size followed by newline
|
||||
" file contents
|
||||
let in = ""
|
||||
let sep = go#util#LineEnding()
|
||||
let content = join(getline(1, '$'), sep)
|
||||
let in = fname . "\n" . strlen(content) . "\n" . content
|
||||
let command .= " -modified"
|
||||
let out = go#util#System(command, in)
|
||||
else
|
||||
let out = go#util#System(command)
|
||||
endif
|
||||
let out = s:gogetdoc(0)
|
||||
endif
|
||||
|
||||
if go#util#ShellError() != 0
|
||||
@ -125,7 +80,7 @@ function! go#doc#Open(newmode, mode, ...)
|
||||
call s:GodocView(a:newmode, a:mode, out)
|
||||
endfunction
|
||||
|
||||
function! s:GodocView(newposition, position, content)
|
||||
function! s:GodocView(newposition, position, content) abort
|
||||
" reuse existing buffer window if it exists otherwise create a new one
|
||||
if !bufexists(s:buf_nr)
|
||||
execute a:newposition
|
||||
@ -169,4 +124,96 @@ function! s:GodocView(newposition, position, content)
|
||||
noremap <buffer> <silent> <Esc> :<C-U>close<CR>
|
||||
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 = [bin_path]
|
||||
|
||||
let offset = go#util#OffsetCursor()
|
||||
let fname = expand("%:p:gs!\\!/!")
|
||||
let pos = shellescape(fname.':#'.offset)
|
||||
|
||||
let cmd += ["-pos", pos]
|
||||
if a:json
|
||||
let cmd += ["-json"]
|
||||
endif
|
||||
|
||||
let command = join(cmd, " ")
|
||||
|
||||
if &modified
|
||||
" gogetdoc supports the same archive format as guru for dealing with
|
||||
" modified buffers.
|
||||
" use the -modified flag
|
||||
" write each archive entry on stdin as:
|
||||
" filename followed by newline
|
||||
" file size followed by newline
|
||||
" file contents
|
||||
let in = ""
|
||||
let sep = go#util#LineEnding()
|
||||
let content = join(getline(1, '$'), sep)
|
||||
let in = fname . "\n" . strlen(content) . "\n" . content
|
||||
let command .= " -modified"
|
||||
let out = go#util#System(command, in)
|
||||
else
|
||||
let out = go#util#System(command)
|
||||
endif
|
||||
|
||||
return out
|
||||
endfunction
|
||||
|
||||
" returns the package and exported name. exported name might be empty.
|
||||
" ie: fmt and Println
|
||||
" ie: github.com/fatih/set and New
|
||||
function! s:godocWord(args) abort
|
||||
if !executable('godoc')
|
||||
let msg = "godoc command not found."
|
||||
let msg .= " install with: go get golang.org/x/tools/cmd/godoc"
|
||||
call go#util#EchoWarning(msg)
|
||||
return []
|
||||
endif
|
||||
|
||||
if !len(a:args)
|
||||
let oldiskeyword = &iskeyword
|
||||
setlocal iskeyword+=.
|
||||
let word = expand('<cword>')
|
||||
let &iskeyword = oldiskeyword
|
||||
let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g')
|
||||
let words = split(word, '\.\ze[^./]\+$')
|
||||
else
|
||||
let words = a:args
|
||||
endif
|
||||
|
||||
if !len(words)
|
||||
return []
|
||||
endif
|
||||
|
||||
let pkg = words[0]
|
||||
if len(words) == 1
|
||||
let exported_name = ""
|
||||
else
|
||||
let exported_name = words[1]
|
||||
endif
|
||||
|
||||
let packages = go#tool#Imports()
|
||||
|
||||
if has_key(packages, pkg)
|
||||
let pkg = packages[pkg]
|
||||
endif
|
||||
|
||||
return [pkg, exported_name]
|
||||
endfunction
|
||||
|
||||
function! s:godocNotFound(content) abort
|
||||
if len(a:content) == 0
|
||||
return 1
|
||||
endif
|
||||
|
||||
return a:content =~# '^.*: no such file or directory\n$'
|
||||
endfunction
|
||||
|
||||
|
||||
" vim: sw=2 ts=2 et
|
||||
|
@ -51,7 +51,7 @@ endif
|
||||
" it doesn't undo changes and break undo history. If you are here reading
|
||||
" this and have VimL experience, please look at the function for
|
||||
" improvements, patches are welcome :)
|
||||
function! go#fmt#Format(withGoimport)
|
||||
function! go#fmt#Format(withGoimport) abort
|
||||
if g:go_fmt_experimental == 1
|
||||
" Using winsaveview to save/restore cursor state has the problem of
|
||||
" closing folds on save:
|
||||
@ -185,7 +185,7 @@ function! go#fmt#Format(withGoimport)
|
||||
% | " Couldn't detect gofmt error format, output errors
|
||||
endif
|
||||
if !empty(errors)
|
||||
call go#list#Populate(l:listtype, errors)
|
||||
call go#list#Populate(l:listtype, errors, 'Format')
|
||||
echohl Error | echomsg "Gofmt returned error" | echohl None
|
||||
endif
|
||||
|
||||
@ -215,7 +215,7 @@ function! go#fmt#Format(withGoimport)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#fmt#ToggleFmtAutoSave()
|
||||
function! go#fmt#ToggleFmtAutoSave() abort
|
||||
if get(g:, "go_fmt_autosave", 1)
|
||||
let g:go_fmt_autosave = 0
|
||||
call go#util#EchoProgress("auto fmt disabled")
|
||||
|
@ -1,47 +1,63 @@
|
||||
" guru.vim -- Vim integration for the Go guru.
|
||||
|
||||
func! s:RunGuru(mode, format, selected, needs_scope) range abort
|
||||
" guru_cmd returns a dict that contains the command to execute guru. option
|
||||
" is dict with following options:
|
||||
" mode : guru mode, such as 'implements'
|
||||
" format : output format, either 'plain' or 'json'
|
||||
" needs_scope : if 1, adds the current package to the scope
|
||||
" selected : if 1, means it's a range of selection, otherwise it picks up the
|
||||
" offset under the cursor
|
||||
" example output:
|
||||
" {'cmd' : ['guru', '-json', 'implements', 'demo/demo.go:#66']}
|
||||
function! s:guru_cmd(args) range abort
|
||||
let mode = a:args.mode
|
||||
let format = a:args.format
|
||||
let needs_scope = a:args.needs_scope
|
||||
let selected = a:args.selected
|
||||
|
||||
let result = {}
|
||||
let dirname = expand('%:p:h')
|
||||
let pkg = go#package#ImportPath(dirname)
|
||||
|
||||
" 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")
|
||||
if empty(bin_path)
|
||||
return {'err': "bin path not found"}
|
||||
endif
|
||||
|
||||
let dirname = expand('%:p:h')
|
||||
let pkg = go#package#ImportPath(dirname)
|
||||
|
||||
" this is important, check it!
|
||||
if pkg == -1 && a:needs_scope
|
||||
return {'err': "current directory is not inside of a valid GOPATH"}
|
||||
endif
|
||||
|
||||
" start constructing the 'command' variable
|
||||
let command = bin_path
|
||||
" start constructing the command
|
||||
let cmd = [bin_path]
|
||||
|
||||
let filename = fnamemodify(expand("%"), ':p:gs?\\?/?')
|
||||
let in = ""
|
||||
let stdin_content = ""
|
||||
if &modified
|
||||
let sep = go#util#LineEnding()
|
||||
let content = join(getline(1, '$'), sep )
|
||||
let in = filename . "\n" . strlen(content) . "\n" . content
|
||||
let command .= " -modified"
|
||||
let result.stdin_content = filename . "\n" . strlen(content) . "\n" . content
|
||||
call add(cmd, "-modified")
|
||||
endif
|
||||
|
||||
" enable outputting in json format
|
||||
if a:format == "json"
|
||||
let command .= " -json"
|
||||
if format == "json"
|
||||
call add(cmd, "-json")
|
||||
endif
|
||||
|
||||
" check for any tags
|
||||
if exists('g:go_guru_tags')
|
||||
let tags = get(g:, 'go_guru_tags')
|
||||
let command .= printf(" -tags %s", 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 a:needs_scope
|
||||
if needs_scope
|
||||
let scopes = [pkg]
|
||||
endif
|
||||
|
||||
@ -66,274 +82,421 @@ func! s:RunGuru(mode, format, selected, needs_scope) range abort
|
||||
let scopes = go#util#StripTrailingSlash(scopes)
|
||||
|
||||
" create shell-safe entries of the list
|
||||
let scopes = go#util#Shelllist(scopes)
|
||||
if !go#util#has_job() | let scopes = go#util#Shelllist(scopes) | endif
|
||||
|
||||
" guru expect a comma-separated list of patterns, construct it
|
||||
let l:scope = join(scopes, ",")
|
||||
let command .= printf(" -scope %s", l:scope)
|
||||
let result.scope = l:scope
|
||||
call extend(cmd, ["-scope", l:scope])
|
||||
endif
|
||||
|
||||
let pos = printf("#%s", go#util#OffsetCursor())
|
||||
if a:selected != -1
|
||||
if selected != -1
|
||||
" means we have a range, get it
|
||||
let pos1 = go#util#Offset(line("'<"), col("'<"))
|
||||
let pos2 = go#util#Offset(line("'>"), col("'>"))
|
||||
let pos = printf("#%s,#%s", pos1, pos2)
|
||||
endif
|
||||
|
||||
" this is our final command
|
||||
let filename .= ':'.pos
|
||||
let command .= printf(' %s %s', a:mode, shellescape(filename))
|
||||
call extend(cmd, [mode, filename])
|
||||
|
||||
let result.cmd = cmd
|
||||
return result
|
||||
endfunction
|
||||
|
||||
" sync_guru runs guru in sync mode with the given arguments
|
||||
function! s:sync_guru(args) abort
|
||||
let result = s:guru_cmd(a:args)
|
||||
if has_key(result, 'err')
|
||||
call go#util#EchoError(result.err)
|
||||
return -1
|
||||
endif
|
||||
|
||||
if !has_key(a:args, 'disable_progress')
|
||||
if a:args.needs_scope
|
||||
call go#util#EchoProgress("analysing with scope ". result.scope . " ...")
|
||||
elseif a:args.mode !=# 'what'
|
||||
" the query might take time, let us give some feedback
|
||||
call go#util#EchoProgress("analysing ...")
|
||||
endif
|
||||
endif
|
||||
|
||||
let old_gopath = $GOPATH
|
||||
let $GOPATH = go#path#Detect()
|
||||
|
||||
if a:needs_scope
|
||||
call go#util#EchoProgress("analysing with scope ". l:scope . " ...")
|
||||
elseif a:mode !=# 'what'
|
||||
" the query might take time, let us give some feedback
|
||||
call go#util#EchoProgress("analysing ...")
|
||||
endif
|
||||
|
||||
" run, forrest run!!!
|
||||
let command = join(result.cmd, " ")
|
||||
if &modified
|
||||
let out = go#util#System(command, in)
|
||||
let out = go#util#System(command, result.stdin_content)
|
||||
else
|
||||
let out = go#util#System(command)
|
||||
endif
|
||||
|
||||
let $GOPATH = old_gopath
|
||||
if go#util#ShellError() != 0
|
||||
" the output contains the error message
|
||||
return {'err' : out}
|
||||
|
||||
if has_key(a:args, 'custom_parse')
|
||||
call a:args.custom_parse(go#util#ShellError(), out)
|
||||
else
|
||||
call s:parse_guru_output(go#util#ShellError(), out, a:args.mode)
|
||||
endif
|
||||
|
||||
return {'out': out}
|
||||
return out
|
||||
endfunc
|
||||
|
||||
" This uses Vim's errorformat to parse the output from Guru's 'plain output
|
||||
" and put it into location list. I believe using errorformat is much more
|
||||
" easier to use. If we need more power we can always switch back to parse it
|
||||
" via regex.
|
||||
func! s:loclistSecond(output)
|
||||
" backup users errorformat, will be restored once we are finished
|
||||
let old_errorformat = &errorformat
|
||||
|
||||
" match two possible styles of errorformats:
|
||||
"
|
||||
" 'file:line.col-line2.col2: message'
|
||||
" 'file:line:col: message'
|
||||
"
|
||||
" We discard line2 and col2 for the first errorformat, because it's not
|
||||
" useful and location only has the ability to show one line and column
|
||||
" number
|
||||
let errformat = "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m"
|
||||
call go#list#ParseFormat("locationlist", errformat, split(a:output, "\n"))
|
||||
|
||||
let errors = go#list#Get("locationlist")
|
||||
call go#list#Window("locationlist", len(errors))
|
||||
endfun
|
||||
|
||||
|
||||
function! go#guru#Scope(...)
|
||||
if a:0
|
||||
if a:0 == 1 && a:1 == '""'
|
||||
unlet g:go_guru_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
|
||||
|
||||
" async_guru runs guru in async mode with the given arguments
|
||||
function! s:async_guru(args) abort
|
||||
let result = s:guru_cmd(a:args)
|
||||
if has_key(result, 'err')
|
||||
call go#util#EchoError(result.err)
|
||||
return
|
||||
endif
|
||||
|
||||
if !exists('g:go_guru_scope')
|
||||
call go#util#EchoError("guru scope is not set")
|
||||
else
|
||||
call go#util#EchoSuccess("current guru scope: ". join(g:go_guru_scope, ","))
|
||||
let status_dir = expand('%:p:h')
|
||||
let statusline_type = printf("%s", a:args.mode)
|
||||
|
||||
if !has_key(a:args, 'disable_progress')
|
||||
if a:args.needs_scope
|
||||
call go#util#EchoProgress("analysing with scope ". result.scope . " ...")
|
||||
endif
|
||||
endif
|
||||
|
||||
function! s:close_cb(chan) closure
|
||||
let messages = []
|
||||
while ch_status(a:chan, {'part': 'out'}) == 'buffered'
|
||||
let msg = ch_read(a:chan, {'part': 'out'})
|
||||
call add(messages, msg)
|
||||
endwhile
|
||||
|
||||
while ch_status(a:chan, {'part': 'err'}) == 'buffered'
|
||||
let msg = ch_read(a:chan, {'part': 'err'})
|
||||
call add(messages, msg)
|
||||
endwhile
|
||||
|
||||
let l:job = ch_getjob(a:chan)
|
||||
let l:info = job_info(l:job)
|
||||
|
||||
let out = join(messages, "\n")
|
||||
|
||||
let status = {
|
||||
\ 'desc': 'last status',
|
||||
\ 'type': statusline_type,
|
||||
\ 'state': "finished",
|
||||
\ }
|
||||
|
||||
if l:info.exitval
|
||||
let status.state = "failed"
|
||||
endif
|
||||
|
||||
call go#statusline#Update(status_dir, status)
|
||||
|
||||
if has_key(a:args, 'custom_parse')
|
||||
call a:args.custom_parse(l:info.exitval, out)
|
||||
else
|
||||
call s:parse_guru_output(l:info.exitval, out, a:args.mode)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let start_options = {
|
||||
\ 'close_cb': function("s:close_cb"),
|
||||
\ }
|
||||
|
||||
if &modified
|
||||
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
|
||||
endif
|
||||
|
||||
call go#statusline#Update(status_dir, {
|
||||
\ 'desc': "current status",
|
||||
\ 'type': statusline_type,
|
||||
\ 'state': "analysing",
|
||||
\})
|
||||
|
||||
return job_start(result.cmd, start_options)
|
||||
endfunc
|
||||
|
||||
" run_guru runs the given guru argument
|
||||
function! s:run_guru(args) abort
|
||||
if go#util#has_job()
|
||||
return s:async_guru(a:args)
|
||||
endif
|
||||
|
||||
return s:sync_guru(a:args)
|
||||
endfunction
|
||||
|
||||
function! go#guru#Tags(...)
|
||||
if a:0
|
||||
if a:0 == 1 && a:1 == '""'
|
||||
unlet g:go_guru_tags
|
||||
call go#util#EchoSuccess("guru tags is cleared")
|
||||
else
|
||||
let g:go_guru_tags = a:1
|
||||
call go#util#EchoSuccess("guru tags changed to: ". a:1)
|
||||
endif
|
||||
" Show 'implements' relation for selected package
|
||||
function! go#guru#Implements(selected) abort
|
||||
let args = {
|
||||
\ 'mode': 'implements',
|
||||
\ 'format': 'plain',
|
||||
\ 'selected': a:selected,
|
||||
\ 'needs_scope': 1,
|
||||
\ }
|
||||
|
||||
return
|
||||
endif
|
||||
|
||||
if !exists('g:go_guru_tags')
|
||||
call go#util#EchoSuccess("guru tags is not set")
|
||||
else
|
||||
call go#util#EchoSuccess("current guru tags: ". a:1)
|
||||
endif
|
||||
call s:run_guru(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)
|
||||
let out = s:RunGuru('whicherrs', 'plain', a:selected, 1)
|
||||
if has_key(out, 'err')
|
||||
call go#util#EchoError(out.err)
|
||||
return
|
||||
endif
|
||||
function! go#guru#Whicherrs(selected) abort
|
||||
let args = {
|
||||
\ 'mode': 'whicherrs',
|
||||
\ 'format': 'plain',
|
||||
\ 'selected': a:selected,
|
||||
\ 'needs_scope': 1,
|
||||
\ }
|
||||
|
||||
if empty(out.out)
|
||||
call go#util#EchoSuccess("no error variables found. Try to change the scope with :GoGuruScope")
|
||||
return
|
||||
endif
|
||||
|
||||
call s:loclistSecond(out.out)
|
||||
endfunction
|
||||
|
||||
" Show 'implements' relation for selected package
|
||||
function! go#guru#Implements(selected)
|
||||
let out = s:RunGuru('implements', 'plain', a:selected, 1)
|
||||
if has_key(out, 'err')
|
||||
call go#util#EchoError(out.err)
|
||||
return
|
||||
endif
|
||||
|
||||
call s:loclistSecond(out.out)
|
||||
" TODO(arslan): handle empty case for both sync/async
|
||||
" if empty(out.out)
|
||||
" call go#util#EchoSuccess("no error variables found. Try to change the scope with :GoGuruScope")
|
||||
" return
|
||||
" endif
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
" Describe selected syntax: definition, methods, etc
|
||||
function! go#guru#Describe(selected)
|
||||
let out = s:RunGuru('describe', 'plain', a:selected, 0)
|
||||
if has_key(out, 'err')
|
||||
call go#util#EchoError(out.err)
|
||||
function! go#guru#Describe(selected) abort
|
||||
let args = {
|
||||
\ 'mode': 'describe',
|
||||
\ 'format': 'plain',
|
||||
\ 'selected': a:selected,
|
||||
\ 'needs_scope': 1,
|
||||
\ }
|
||||
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
function! go#guru#DescribeInfo() 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
|
||||
if !exists("*json_decode")
|
||||
call go#util#EchoError("requires 'json_decode'. Update your Vim/Neovim version.")
|
||||
return
|
||||
endif
|
||||
|
||||
call s:loclistSecond(out.out)
|
||||
function! s:info(exit_val, output)
|
||||
if a:exit_val != 0
|
||||
return
|
||||
endif
|
||||
|
||||
if a:output[0] !=# '{'
|
||||
return
|
||||
endif
|
||||
|
||||
if empty(a:output) || type(a:output) != type("")
|
||||
return
|
||||
endif
|
||||
|
||||
let result = json_decode(a:output)
|
||||
if type(result) != type({})
|
||||
call go#util#EchoError(printf("malformed output from guru: %s", a:output))
|
||||
return
|
||||
endif
|
||||
|
||||
if !has_key(result, 'detail')
|
||||
" if there is no detail check if there is a description and print it
|
||||
if has_key(result, "desc")
|
||||
call go#util#EchoInfo(result["desc"])
|
||||
return
|
||||
endif
|
||||
|
||||
call go#util#EchoError("detail key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let detail = result['detail']
|
||||
let info = ""
|
||||
|
||||
" guru gives different information based on the detail mode. Let try to
|
||||
" extract the most useful information
|
||||
|
||||
if detail == "value"
|
||||
if !has_key(result, 'value')
|
||||
call go#util#EchoError("value key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let val = result["value"]
|
||||
if !has_key(val, 'type')
|
||||
call go#util#EchoError("type key is missing (value.type). Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let info = val["type"]
|
||||
elseif detail == "type"
|
||||
if !has_key(result, 'type')
|
||||
call go#util#EchoError("type key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let type = result["type"]
|
||||
if !has_key(type, 'type')
|
||||
call go#util#EchoError("type key is missing (type.type). Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let info = type["type"]
|
||||
elseif detail == "package"
|
||||
if !has_key(result, 'package')
|
||||
call go#util#EchoError("package key is missing. Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let package = result["package"]
|
||||
if !has_key(package, 'path')
|
||||
call go#util#EchoError("path key is missing (package.path). Please open a bug report on vim-go repo.")
|
||||
return
|
||||
endif
|
||||
|
||||
let info = printf("package %s", package["path"])
|
||||
elseif detail == "unknown"
|
||||
let info = result["desc"]
|
||||
else
|
||||
call go#util#EchoError(printf("unknown detail mode found '%s'. Please open a bug report on vim-go repo", detail))
|
||||
return
|
||||
endif
|
||||
|
||||
call go#util#EchoInfo(info)
|
||||
endfunction
|
||||
|
||||
let args = {
|
||||
\ 'mode': 'describe',
|
||||
\ 'format': 'json',
|
||||
\ 'selected': -1,
|
||||
\ 'needs_scope': 1,
|
||||
\ 'custom_parse': function('s:info'),
|
||||
\ 'disable_progress': 1,
|
||||
\ }
|
||||
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
" Show possible targets of selected function call
|
||||
function! go#guru#Callees(selected)
|
||||
let out = s:RunGuru('callees', 'plain', a:selected, 1)
|
||||
if has_key(out, 'err')
|
||||
call go#util#EchoError(out.err)
|
||||
return
|
||||
endif
|
||||
function! go#guru#Callees(selected) abort
|
||||
let args = {
|
||||
\ 'mode': 'callees',
|
||||
\ 'format': 'plain',
|
||||
\ 'selected': a:selected,
|
||||
\ 'needs_scope': 1,
|
||||
\ }
|
||||
|
||||
call s:loclistSecond(out.out)
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
" Show possible callers of selected function
|
||||
function! go#guru#Callers(selected)
|
||||
let out = s:RunGuru('callers', 'plain', a:selected, 1)
|
||||
if has_key(out, 'err')
|
||||
call go#util#EchoError(out.err)
|
||||
return
|
||||
endif
|
||||
function! go#guru#Callers(selected) abort
|
||||
let args = {
|
||||
\ 'mode': 'callers',
|
||||
\ 'format': 'plain',
|
||||
\ 'selected': a:selected,
|
||||
\ 'needs_scope': 1,
|
||||
\ }
|
||||
|
||||
call s:loclistSecond(out.out)
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
" Show path from callgraph root to selected function
|
||||
function! go#guru#Callstack(selected)
|
||||
let out = s:RunGuru('callstack', 'plain', a:selected, 1)
|
||||
if has_key(out, 'err')
|
||||
call go#util#EchoError(out.err)
|
||||
return
|
||||
endif
|
||||
function! go#guru#Callstack(selected) abort
|
||||
let args = {
|
||||
\ 'mode': 'callstack',
|
||||
\ 'format': 'plain',
|
||||
\ 'selected': a:selected,
|
||||
\ 'needs_scope': 1,
|
||||
\ }
|
||||
|
||||
call s:loclistSecond(out.out)
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
" Show free variables of selection
|
||||
function! go#guru#Freevars(selected)
|
||||
function! go#guru#Freevars(selected) abort
|
||||
" Freevars requires a selection
|
||||
if a:selected == -1
|
||||
call go#util#EchoError("GoFreevars requires a selection (range) of code")
|
||||
return
|
||||
endif
|
||||
|
||||
let out = s:RunGuru('freevars', 'plain', a:selected, 0)
|
||||
if has_key(out, 'err')
|
||||
call go#util#EchoError(out.err)
|
||||
return
|
||||
endif
|
||||
let args = {
|
||||
\ 'mode': 'freevars',
|
||||
\ 'format': 'plain',
|
||||
\ 'selected': 1,
|
||||
\ 'needs_scope': 0,
|
||||
\ }
|
||||
|
||||
call s:loclistSecond(out.out)
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
" Show send/receive corresponding to selected channel op
|
||||
function! go#guru#ChannelPeers(selected)
|
||||
let out = s:RunGuru('peers', 'plain', a:selected, 1)
|
||||
if has_key(out, 'err')
|
||||
call go#util#EchoError(out.err)
|
||||
return
|
||||
endif
|
||||
function! go#guru#ChannelPeers(selected) abort
|
||||
let args = {
|
||||
\ 'mode': 'peers',
|
||||
\ 'format': 'plain',
|
||||
\ 'selected': a:selected,
|
||||
\ 'needs_scope': 1,
|
||||
\ }
|
||||
|
||||
call s:loclistSecond(out.out)
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
" Show all refs to entity denoted by selected identifier
|
||||
function! go#guru#Referrers(selected)
|
||||
let out = s:RunGuru('referrers', 'plain', a:selected, 0)
|
||||
if has_key(out, 'err')
|
||||
call go#util#EchoError(out.err)
|
||||
function! go#guru#Referrers(selected) abort
|
||||
let args = {
|
||||
\ 'mode': 'referrers',
|
||||
\ 'format': 'plain',
|
||||
\ 'selected': a:selected,
|
||||
\ 'needs_scope': 0,
|
||||
\ }
|
||||
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
function! go#guru#SameIdsTimer() abort
|
||||
call timer_start(200, function('go#guru#SameIds'), {'repeat': -1})
|
||||
endfunction
|
||||
|
||||
function! go#guru#SameIds() 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")
|
||||
call go#util#EchoError("GoSameIds requires 'matchaddpos'. Update your Vim/Neovim version.")
|
||||
return
|
||||
endif
|
||||
|
||||
call s:loclistSecond(out.out)
|
||||
endfunction
|
||||
|
||||
function! go#guru#What(selected)
|
||||
" 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
|
||||
if !exists("*json_decode")
|
||||
return {'err': "GoWhat is not supported due old version of Vim/Neovim"}
|
||||
endif
|
||||
|
||||
let out = s:RunGuru('what', 'json', a:selected, 0)
|
||||
if has_key(out, 'err')
|
||||
return {'err': out.err}
|
||||
endif
|
||||
|
||||
let result = json_decode(out.out)
|
||||
|
||||
if type(result) != type({})
|
||||
return {'err': "malformed output from guru"}
|
||||
endif
|
||||
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! go#guru#AutoToogleSameIds()
|
||||
if get(g:, "go_auto_sameids", 0)
|
||||
call go#util#EchoProgress("sameids auto highlighting disabled")
|
||||
call go#guru#ClearSameIds()
|
||||
let g:go_auto_sameids = 0
|
||||
call go#util#EchoError("GoSameIds requires 'json_decode'. Update your Vim/Neovim version.")
|
||||
return
|
||||
endif
|
||||
|
||||
call go#util#EchoSuccess("sameids auto highlighting enabled")
|
||||
let g:go_auto_sameids = 1
|
||||
let args = {
|
||||
\ 'mode': 'what',
|
||||
\ 'format': 'json',
|
||||
\ 'selected': -1,
|
||||
\ 'needs_scope': 0,
|
||||
\ 'custom_parse': function('s:same_ids_highlight'),
|
||||
\ }
|
||||
|
||||
call s:run_guru(args)
|
||||
endfunction
|
||||
|
||||
function! go#guru#SameIds(selected)
|
||||
" 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")
|
||||
call go#util#EchoError("GoSameIds is supported with Vim version 7.4-330 or later")
|
||||
return
|
||||
endif
|
||||
|
||||
let result = go#guru#What(a:selected)
|
||||
|
||||
function! s:same_ids_highlight(exit_val, output) abort
|
||||
call go#guru#ClearSameIds() " run after calling guru to reduce flicker.
|
||||
if has_key(result, 'err') && !get(g:, 'go_auto_sameids', 0)
|
||||
" only echo if it's called via `:GoSameIds, but not if it's in automode
|
||||
call go#util#EchoError(result.err)
|
||||
|
||||
if a:output[0] !=# '{'
|
||||
if !get(g:, 'go_auto_sameids', 0)
|
||||
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)
|
||||
call go#util#EchoError("malformed output from guru")
|
||||
return
|
||||
endif
|
||||
|
||||
@ -367,11 +530,11 @@ function! go#guru#SameIds(selected)
|
||||
if get(g:, "go_auto_sameids", 0)
|
||||
" re-apply SameIds at the current cursor position at the time the buffer
|
||||
" is redisplayed: e.g. :edit, :GoRename, etc.
|
||||
autocmd BufWinEnter <buffer> nested call go#guru#SameIds(-1)
|
||||
autocmd BufWinEnter <buffer> nested call go#guru#SameIds()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#guru#ClearSameIds()
|
||||
function! go#guru#ClearSameIds() abort
|
||||
let m = getmatches()
|
||||
for item in m
|
||||
if item['group'] == 'goSameId'
|
||||
@ -385,11 +548,94 @@ function! go#guru#ClearSameIds()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#guru#ToggleSameIds(selected)
|
||||
function! go#guru#ToggleSameIds() abort
|
||||
if len(getmatches()) != 0
|
||||
call go#guru#ClearSameIds()
|
||||
else
|
||||
call go#guru#SameIds(a:selected)
|
||||
call go#guru#SameIds()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#guru#AutoToogleSameIds() abort
|
||||
if get(g:, "go_auto_sameids", 0)
|
||||
call go#util#EchoProgress("sameids auto highlighting disabled")
|
||||
call go#guru#ClearSameIds()
|
||||
let g:go_auto_sameids = 0
|
||||
return
|
||||
endif
|
||||
|
||||
call go#util#EchoSuccess("sameids auto highlighting enabled")
|
||||
let g:go_auto_sameids = 1
|
||||
endfunction
|
||||
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""
|
||||
"" HELPER FUNCTIONS
|
||||
""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
" This uses Vim's errorformat to parse the output from Guru's 'plain output
|
||||
" and put it into location list. I believe using errorformat is much more
|
||||
" easier to use. If we need more power we can always switch back to parse it
|
||||
" via regex. Match two possible styles of errorformats:
|
||||
"
|
||||
" 'file:line.col-line2.col2: message'
|
||||
" 'file:line:col: message'
|
||||
"
|
||||
" We discard line2 and col2 for the first errorformat, because it's not
|
||||
" useful and location only has the ability to show one line and column
|
||||
" number
|
||||
function! s:parse_guru_output(exit_val, output, title) abort
|
||||
if a:exit_val
|
||||
call go#util#EchoError(a:output)
|
||||
return
|
||||
endif
|
||||
|
||||
let old_errorformat = &errorformat
|
||||
let errformat = "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m"
|
||||
call go#list#ParseFormat("locationlist", errformat, a:output, a:title)
|
||||
let &errorformat = old_errorformat
|
||||
|
||||
let errors = go#list#Get("locationlist")
|
||||
call go#list#Window("locationlist", len(errors))
|
||||
endfun
|
||||
|
||||
function! go#guru#Scope(...) abort
|
||||
if a:0
|
||||
if a:0 == 1 && a:1 == '""'
|
||||
unlet g:go_guru_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')
|
||||
call go#util#EchoError("guru scope is not set")
|
||||
else
|
||||
call go#util#EchoSuccess("current guru scope: ". join(g:go_guru_scope, ","))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#guru#Tags(...) abort
|
||||
if a:0
|
||||
if a:0 == 1 && a:1 == '""'
|
||||
unlet g:go_guru_tags
|
||||
call go#util#EchoSuccess("guru tags is cleared")
|
||||
else
|
||||
let g:go_guru_tags = a:1
|
||||
call go#util#EchoSuccess("guru tags changed to: ". a:1)
|
||||
endif
|
||||
|
||||
return
|
||||
endif
|
||||
|
||||
if !exists('g:go_guru_tags')
|
||||
call go#util#EchoSuccess("guru tags is not set")
|
||||
else
|
||||
call go#util#EchoSuccess("current guru tags: ". a:1)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
function! go#impl#Impl(...)
|
||||
function! go#impl#Impl(...) abort
|
||||
let binpath = go#path#CheckBinPath('impl')
|
||||
if empty(binpath)
|
||||
return
|
||||
@ -69,7 +69,7 @@ else
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:root_dirs()
|
||||
function! s:root_dirs() abort
|
||||
let dirs = []
|
||||
let root = go#util#goroot()
|
||||
if root !=# '' && isdirectory(root)
|
||||
@ -88,7 +88,7 @@ function! s:root_dirs()
|
||||
return dirs
|
||||
endfunction
|
||||
|
||||
function! s:go_packages(dirs)
|
||||
function! s:go_packages(dirs) abort
|
||||
let pkgs = []
|
||||
for d in a:dirs
|
||||
let pkg_root = expand(d . '/pkg/' . go#util#osarch())
|
||||
@ -97,7 +97,7 @@ function! s:go_packages(dirs)
|
||||
return map(pkgs, "fnamemodify(v:val, ':t:r')")
|
||||
endfunction
|
||||
|
||||
function! s:interface_list(pkg)
|
||||
function! s:interface_list(pkg) abort
|
||||
let contents = split(go#util#System('go doc ' . a:pkg), "\n")
|
||||
if go#util#ShellError()
|
||||
return []
|
||||
@ -108,7 +108,7 @@ function! s:interface_list(pkg)
|
||||
endfunction
|
||||
|
||||
" Complete package and interface for {interface}
|
||||
function! go#impl#Complete(arglead, cmdline, cursorpos)
|
||||
function! go#impl#Complete(arglead, cmdline, cursorpos) abort
|
||||
let words = split(a:cmdline, '\s\+', 1)
|
||||
if words[-1] ==# ''
|
||||
return s:uniq(sort(s:go_packages(s:root_dirs())))
|
||||
|
@ -4,7 +4,7 @@
|
||||
"
|
||||
" Check out the docs for more information at /doc/vim-go.txt
|
||||
"
|
||||
function! go#import#SwitchImport(enabled, localname, path, bang)
|
||||
function! go#import#SwitchImport(enabled, localname, path, bang) abort
|
||||
let view = winsaveview()
|
||||
let path = substitute(a:path, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||
|
||||
@ -205,7 +205,7 @@ function! go#import#SwitchImport(enabled, localname, path, bang)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:Error(s)
|
||||
function! s:Error(s) abort
|
||||
echohl Error | echo a:s | echohl None
|
||||
endfunction
|
||||
|
||||
|
109
sources_non_forked/vim-go/autoload/go/job.vim
Normal file
109
sources_non_forked/vim-go/autoload/go/job.vim
Normal file
@ -0,0 +1,109 @@
|
||||
" Spawn returns callbacks to be used with job_start. It's abstracted to be
|
||||
" used with various go command, such as build, test, install, etc.. This avoid
|
||||
" us to write the same callback over and over for some commands. It's fully
|
||||
" customizable so each command can change it to it's own logic.
|
||||
function go#job#Spawn(args)
|
||||
let cbs = {
|
||||
\ 'winnr': winnr(),
|
||||
\ 'dir': getcwd(),
|
||||
\ 'jobdir': fnameescape(expand("%:p:h")),
|
||||
\ 'messages': [],
|
||||
\ 'args': a:args.cmd,
|
||||
\ 'bang': 0,
|
||||
\ }
|
||||
|
||||
if has_key(a:args, 'bang')
|
||||
let cbs.bang = a:args.bang
|
||||
endif
|
||||
|
||||
" add final callback to be called if async job is finished
|
||||
" The signature should be in form: func(job, exit_status, messages)
|
||||
if has_key(a:args, 'custom_cb')
|
||||
let cbs.custom_cb = a:args.custom_cb
|
||||
endif
|
||||
|
||||
if has_key(a:args, 'error_info_cb')
|
||||
let cbs.error_info_cb = a:args.error_info_cb
|
||||
endif
|
||||
|
||||
function cbs.callback(chan, msg) dict
|
||||
call add(self.messages, a:msg)
|
||||
endfunction
|
||||
|
||||
function cbs.close_cb(chan) dict
|
||||
let l:job = ch_getjob(a:chan)
|
||||
let l:status = job_status(l:job)
|
||||
|
||||
" the job might be in fail status, we assume by default it's failed.
|
||||
" However if it's dead, we can use the real exitval
|
||||
let exitval = 1
|
||||
if l:status == "dead"
|
||||
let l:info = job_info(l:job)
|
||||
let exitval = l:info.exitval
|
||||
endif
|
||||
|
||||
if has_key(self, 'custom_cb')
|
||||
call self.custom_cb(l:job, exitval, self.messages)
|
||||
endif
|
||||
|
||||
if has_key(self, 'error_info_cb')
|
||||
call self.error_info_cb(l:job, exitval, self.messages)
|
||||
endif
|
||||
|
||||
if get(g:, 'go_echo_command_info', 1)
|
||||
if exitval == 0
|
||||
call go#util#EchoSuccess("SUCCESS")
|
||||
else
|
||||
call go#util#EchoError("FAILED")
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:listtype = go#list#Type("quickfix")
|
||||
if exitval == 0
|
||||
call go#list#Clean(l:listtype)
|
||||
call go#list#Window(l:listtype)
|
||||
return
|
||||
endif
|
||||
|
||||
call self.show_errors(l:listtype)
|
||||
endfunction
|
||||
|
||||
function cbs.show_errors(listtype) dict
|
||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||
try
|
||||
execute cd self.jobdir
|
||||
let errors = go#tool#ParseErrors(self.messages)
|
||||
let errors = go#tool#FilterValids(errors)
|
||||
finally
|
||||
execute cd . fnameescape(self.dir)
|
||||
endtry
|
||||
|
||||
if !len(errors)
|
||||
" failed to parse errors, output the original content
|
||||
call go#util#EchoError(join(self.messages, " "))
|
||||
call go#util#EchoError(self.dir)
|
||||
return
|
||||
endif
|
||||
|
||||
if self.winnr == winnr()
|
||||
call go#list#Populate(a:listtype, errors, join(self.args))
|
||||
call go#list#Window(a:listtype, len(errors))
|
||||
if !empty(errors) && !self.bang
|
||||
call go#list#JumpToFirst(a:listtype)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" override callback handler if user provided it
|
||||
if has_key(a:args, 'callback')
|
||||
let cbs.callback = a:args.callback
|
||||
endif
|
||||
|
||||
" override close callback handler if user provided it
|
||||
if has_key(a:args, 'close_cb')
|
||||
let cbs.close_cb = a:args.close_cb
|
||||
endif
|
||||
|
||||
return cbs
|
||||
endfunction
|
||||
" vim: sw=2 ts=2 et
|
@ -9,7 +9,7 @@ let s:handlers = {}
|
||||
" Spawn is a wrapper around s:spawn. It can be executed by other files and
|
||||
" scripts if needed. Desc defines the description for printing the status
|
||||
" during the job execution (useful for statusline integration).
|
||||
function! go#jobcontrol#Spawn(bang, desc, args)
|
||||
function! go#jobcontrol#Spawn(bang, desc, args) abort
|
||||
" autowrite is not enabled for jobs
|
||||
call go#cmd#autowrite()
|
||||
|
||||
@ -17,31 +17,8 @@ function! go#jobcontrol#Spawn(bang, desc, args)
|
||||
return job.id
|
||||
endfunction
|
||||
|
||||
" Statusline returns the current status of the job
|
||||
function! go#jobcontrol#Statusline() abort
|
||||
if empty(s:jobs)
|
||||
return ''
|
||||
endif
|
||||
|
||||
let import_path = go#package#ImportPath(expand('%:p:h'))
|
||||
|
||||
for job in values(s:jobs)
|
||||
if job.importpath != import_path
|
||||
continue
|
||||
endif
|
||||
|
||||
if job.state == "SUCCESS"
|
||||
return ''
|
||||
endif
|
||||
|
||||
return printf("%s ... [%s]", job.desc, job.state)
|
||||
endfor
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
" AddHandler adds a on_exit callback handler and returns the id.
|
||||
function! go#jobcontrol#AddHandler(handler)
|
||||
function! go#jobcontrol#AddHandler(handler) abort
|
||||
let i = len(s:handlers)
|
||||
while has_key(s:handlers, string(i))
|
||||
let i += 1
|
||||
@ -52,7 +29,7 @@ function! go#jobcontrol#AddHandler(handler)
|
||||
endfunction
|
||||
|
||||
" RemoveHandler removes a callback handler by id.
|
||||
function! go#jobcontrol#RemoveHandler(id)
|
||||
function! go#jobcontrol#RemoveHandler(id) abort
|
||||
unlet s:handlers[a:id]
|
||||
endfunction
|
||||
|
||||
@ -60,10 +37,10 @@ endfunction
|
||||
" a job is started a reference will be stored inside s:jobs. spawn changes the
|
||||
" GOPATH when g:go_autodetect_gopath is enabled. The job is started inside the
|
||||
" current files folder.
|
||||
function! s:spawn(bang, desc, args)
|
||||
let job = {
|
||||
\ 'desc': a:desc,
|
||||
\ 'bang': a:bang,
|
||||
function! s:spawn(bang, desc, args) abort
|
||||
let job = {
|
||||
\ 'desc': a:desc,
|
||||
\ 'bang': a:bang,
|
||||
\ 'winnr': winnr(),
|
||||
\ 'importpath': go#package#ImportPath(expand('%:p:h')),
|
||||
\ 'state': "RUNNING",
|
||||
@ -113,7 +90,7 @@ endfunction
|
||||
" references and also displaying errors in the quickfix window collected by
|
||||
" 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)
|
||||
function! s:on_exit(job_id, exit_status, event) dict abort
|
||||
let std_combined = self.stderr + self.stdout
|
||||
|
||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||
@ -122,9 +99,10 @@ function! s:on_exit(job_id, exit_status)
|
||||
|
||||
call s:callback_handlers_on_exit(s:jobs[a:job_id], a:exit_status, std_combined)
|
||||
|
||||
let l:listtype = go#list#Type("quickfix")
|
||||
if a:exit_status == 0
|
||||
call go#list#Clean(0)
|
||||
call go#list#Window(0)
|
||||
call go#list#Clean(l:listtype)
|
||||
call go#list#Window(l:listtype)
|
||||
|
||||
let self.state = "SUCCESS"
|
||||
call go#util#EchoSuccess("SUCCESS")
|
||||
@ -149,8 +127,7 @@ function! s:on_exit(job_id, exit_status)
|
||||
|
||||
" if we are still in the same windows show the list
|
||||
if self.winnr == winnr()
|
||||
let l:listtype = "locationlist"
|
||||
call go#list#Populate(l:listtype, errors)
|
||||
call go#list#Populate(l:listtype, errors, self.desc)
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
if !empty(errors) && !self.bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
@ -159,7 +136,7 @@ function! s:on_exit(job_id, exit_status)
|
||||
endfunction
|
||||
|
||||
" callback_handlers_on_exit runs all handlers for job on exit event.
|
||||
function! s:callback_handlers_on_exit(job, exit_status, data)
|
||||
function! s:callback_handlers_on_exit(job, exit_status, data) abort
|
||||
if empty(s:handlers)
|
||||
return
|
||||
endif
|
||||
@ -170,45 +147,15 @@ function! s:callback_handlers_on_exit(job, exit_status, data)
|
||||
endfunction
|
||||
|
||||
" on_stdout is the stdout handler for jobstart(). It collects the output of
|
||||
" stderr and stores them to the jobs internal stdout list.
|
||||
function! s:on_stdout(job_id, data)
|
||||
" stderr and stores them to the jobs internal stdout list.
|
||||
function! s:on_stdout(job_id, data) dict abort
|
||||
call extend(self.stdout, a:data)
|
||||
endfunction
|
||||
|
||||
" on_stderr is the stderr handler for jobstart(). It collects the output of
|
||||
" stderr and stores them to the jobs internal stderr list.
|
||||
function! s:on_stderr(job_id, data)
|
||||
function! s:on_stderr(job_id, data) dict abort
|
||||
call extend(self.stderr, a:data)
|
||||
endfunction
|
||||
|
||||
" abort_all aborts all current jobs created with s:spawn()
|
||||
function! s:abort_all()
|
||||
if empty(s:jobs)
|
||||
return
|
||||
endif
|
||||
|
||||
for id in keys(s:jobs)
|
||||
if id > 0
|
||||
silent! call jobstop(id)
|
||||
endif
|
||||
endfor
|
||||
|
||||
let s:jobs = {}
|
||||
endfunction
|
||||
|
||||
" abort aborts the job with the given name, where name is the first argument
|
||||
" passed to s:spawn()
|
||||
function! s:abort(path)
|
||||
if empty(s:jobs)
|
||||
return
|
||||
endif
|
||||
|
||||
for job in values(s:jobs)
|
||||
if job.importpath == path && job.id > 0
|
||||
silent! call jobstop(job.id)
|
||||
unlet s:jobs['job.id']
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" vim: sw=2 ts=2 et
|
||||
|
@ -29,37 +29,42 @@ function! go#lint#Gometa(autosave, ...) abort
|
||||
let goargs = go#util#Shelljoin(a:000)
|
||||
endif
|
||||
|
||||
let meta_command = "gometalinter --disable-all"
|
||||
let bin_path = go#path#CheckBinPath("gometalinter")
|
||||
if empty(bin_path)
|
||||
return
|
||||
endif
|
||||
|
||||
let cmd = [bin_path]
|
||||
let cmd += ["--disable-all"]
|
||||
|
||||
if a:autosave || empty(g:go_metalinter_command)
|
||||
let bin_path = go#path#CheckBinPath("gometalinter")
|
||||
if empty(bin_path)
|
||||
return
|
||||
endif
|
||||
|
||||
if a:autosave
|
||||
" include only messages for the active buffer
|
||||
let meta_command .= " --include='^" . expand('%:p') . ".*$'"
|
||||
endif
|
||||
|
||||
" linters
|
||||
let linters = a:autosave ? g:go_metalinter_autosave_enabled : g:go_metalinter_enabled
|
||||
for linter in linters
|
||||
let meta_command .= " --enable=".linter
|
||||
let cmd += ["--enable=".linter]
|
||||
endfor
|
||||
|
||||
" deadline
|
||||
let meta_command .= " --deadline=" . g:go_metalinter_deadline
|
||||
|
||||
" path
|
||||
let meta_command .= " " . goargs
|
||||
let cmd += [expand('%:p:h')]
|
||||
else
|
||||
" the user wants something else, let us use it.
|
||||
let meta_command = g:go_metalinter_command
|
||||
let cmd += [split(g:go_metalinter_command, " ")]
|
||||
endif
|
||||
|
||||
" comment out the following two lines for debugging
|
||||
" echo meta_command
|
||||
" return
|
||||
if go#util#has_job() && has('lambda')
|
||||
call s:lint_job({'cmd': cmd})
|
||||
return
|
||||
endif
|
||||
|
||||
" we add deadline only for sync mode
|
||||
let cmd += ["--deadline=" . g:go_metalinter_deadline]
|
||||
if a:autosave
|
||||
" include only messages for the active buffer
|
||||
let cmd += ["--include='^" . expand('%:p') . ".*$'"]
|
||||
endif
|
||||
|
||||
|
||||
let meta_command = join(cmd, " ")
|
||||
|
||||
let out = go#tool#ExecuteInDir(meta_command)
|
||||
|
||||
@ -77,7 +82,7 @@ function! go#lint#Gometa(autosave, ...) abort
|
||||
let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m"
|
||||
|
||||
" Parse and populate our location list
|
||||
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"))
|
||||
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'GoMetaLinter')
|
||||
|
||||
let errors = go#list#Get(l:listtype)
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
@ -117,7 +122,7 @@ endfunction
|
||||
|
||||
" Vet calls 'go vet' on the current directory. Any warnings are populated in
|
||||
" the location list
|
||||
function! go#lint#Vet(bang, ...)
|
||||
function! go#lint#Vet(bang, ...) abort
|
||||
call go#cmd#autowrite()
|
||||
echon "vim-go: " | echohl Identifier | echon "calling vet..." | echohl None
|
||||
if a:0 == 0
|
||||
@ -129,7 +134,7 @@ function! go#lint#Vet(bang, ...)
|
||||
let l:listtype = "quickfix"
|
||||
if go#util#ShellError() != 0
|
||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
||||
call go#list#Populate(l:listtype, errors)
|
||||
call go#list#Populate(l:listtype, errors, 'Vet')
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
if !empty(errors) && !a:bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
@ -171,7 +176,7 @@ function! go#lint#Errcheck(...) abort
|
||||
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"))
|
||||
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'Errcheck')
|
||||
|
||||
let errors = go#list#Get(l:listtype)
|
||||
|
||||
@ -182,7 +187,7 @@ function! go#lint#Errcheck(...) abort
|
||||
endif
|
||||
|
||||
if !empty(errors)
|
||||
call go#list#Populate(l:listtype, errors)
|
||||
call go#list#Populate(l:listtype, errors, 'Errcheck')
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
if !empty(errors)
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
@ -196,7 +201,7 @@ function! go#lint#Errcheck(...) abort
|
||||
|
||||
endfunction
|
||||
|
||||
function! go#lint#ToggleMetaLinterAutoSave()
|
||||
function! go#lint#ToggleMetaLinterAutoSave() abort
|
||||
if get(g:, "go_metalinter_autosave", 0)
|
||||
let g:go_metalinter_autosave = 0
|
||||
call go#util#EchoProgress("auto metalinter disabled")
|
||||
@ -207,4 +212,88 @@ function! go#lint#ToggleMetaLinterAutoSave()
|
||||
call go#util#EchoProgress("auto metalinter enabled")
|
||||
endfunction
|
||||
|
||||
function s:lint_job(args)
|
||||
let status_dir = expand('%:p:h')
|
||||
let started_at = reltime()
|
||||
|
||||
call go#statusline#Update(status_dir, {
|
||||
\ 'desc': "current status",
|
||||
\ 'type': "gometalinter",
|
||||
\ 'state': "analysing",
|
||||
\})
|
||||
|
||||
" autowrite is not enabled for jobs
|
||||
call go#cmd#autowrite()
|
||||
|
||||
let l:listtype = go#list#Type("quickfix")
|
||||
let l:errformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m'
|
||||
|
||||
function! s:callback(chan, msg) closure
|
||||
let old_errorformat = &errorformat
|
||||
let &errorformat = l:errformat
|
||||
caddexpr a:msg
|
||||
let &errorformat = old_errorformat
|
||||
|
||||
" TODO(arslan): cursor still jumps to first error even If I don't want
|
||||
" it. Seems like there is a regression somewhere, but not sure where.
|
||||
copen
|
||||
endfunction
|
||||
|
||||
function! s:close_cb(chan) closure
|
||||
let l:job = ch_getjob(a:chan)
|
||||
let l:status = job_status(l:job)
|
||||
|
||||
let exitval = 1
|
||||
if l:status == "dead"
|
||||
let l:info = job_info(l:job)
|
||||
let exitval = l:info.exitval
|
||||
endif
|
||||
|
||||
let status = {
|
||||
\ 'desc': 'last status',
|
||||
\ 'type': "gometaliner",
|
||||
\ 'state': "finished",
|
||||
\ }
|
||||
|
||||
if exitval
|
||||
let status.state = "failed"
|
||||
endif
|
||||
|
||||
let elapsed_time = reltimestr(reltime(started_at))
|
||||
" strip whitespace
|
||||
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||
let status.state .= printf(" (%ss)", elapsed_time)
|
||||
|
||||
call go#statusline#Update(status_dir, status)
|
||||
|
||||
let errors = go#list#Get(l:listtype)
|
||||
if empty(errors)
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
elseif has("patch-7.4.2200")
|
||||
if l:listtype == 'quickfix'
|
||||
call setqflist([], 'a', {'title': 'GoMetaLinter'})
|
||||
else
|
||||
call setloclist(0, [], 'a', {'title': 'GoMetaLinter'})
|
||||
endif
|
||||
endif
|
||||
|
||||
if get(g:, 'go_echo_command_info', 1)
|
||||
call go#util#EchoSuccess("linting finished")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let start_options = {
|
||||
\ 'callback': function("s:callback"),
|
||||
\ 'close_cb': function("s:close_cb"),
|
||||
\ }
|
||||
|
||||
call job_start(a:args.cmd, start_options)
|
||||
|
||||
call go#list#Clean(l:listtype)
|
||||
|
||||
if get(g:, 'go_echo_command_info', 1)
|
||||
call go#util#EchoProgress("linting started ...")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" vim: sw=2 ts=2 et
|
||||
|
@ -5,7 +5,7 @@ endif
|
||||
" Window opens the list with the given height up to 10 lines maximum.
|
||||
" Otherwise g:go_loclist_height is used. If no or zero height is given it
|
||||
" closes the window
|
||||
function! go#list#Window(listtype, ...)
|
||||
function! go#list#Window(listtype, ...) abort
|
||||
let l:listtype = go#list#Type(a:listtype)
|
||||
" we don't use lwindow to close the location list as we need also the
|
||||
" ability to resize the window. So, we are going to use lopen and lclose
|
||||
@ -40,7 +40,7 @@ endfunction
|
||||
|
||||
|
||||
" Get returns the current list of items from the location list
|
||||
function! go#list#Get(listtype)
|
||||
function! go#list#Get(listtype) abort
|
||||
let l:listtype = go#list#Type(a:listtype)
|
||||
if l:listtype == "locationlist"
|
||||
return getloclist(0)
|
||||
@ -50,22 +50,27 @@ function! go#list#Get(listtype)
|
||||
endfunction
|
||||
|
||||
" Populate populate the location list with the given items
|
||||
function! go#list#Populate(listtype, items)
|
||||
function! go#list#Populate(listtype, items, title) abort
|
||||
let l:listtype = go#list#Type(a:listtype)
|
||||
if l:listtype == "locationlist"
|
||||
call setloclist(0, a:items, 'r')
|
||||
|
||||
" The last argument ({what}) is introduced with 7.4.2200:
|
||||
" https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640
|
||||
if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif
|
||||
else
|
||||
call setqflist(a:items, 'r')
|
||||
if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#list#PopulateWin(winnr, items)
|
||||
function! go#list#PopulateWin(winnr, items) abort
|
||||
call setloclist(a:winnr, a:items, 'r')
|
||||
endfunction
|
||||
|
||||
" Parse parses the given items based on the specified errorformat nad
|
||||
" populates the location list.
|
||||
function! go#list#ParseFormat(listtype, errformat, items)
|
||||
function! go#list#ParseFormat(listtype, errformat, items, title) abort
|
||||
let l:listtype = go#list#Type(a:listtype)
|
||||
" backup users errorformat, will be restored once we are finished
|
||||
let old_errorformat = &errorformat
|
||||
@ -74,8 +79,10 @@ function! go#list#ParseFormat(listtype, errformat, items)
|
||||
let &errorformat = a:errformat
|
||||
if l:listtype == "locationlist"
|
||||
lgetexpr a:items
|
||||
if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif
|
||||
else
|
||||
cgetexpr a:items
|
||||
if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif
|
||||
endif
|
||||
|
||||
"restore back
|
||||
@ -84,7 +91,7 @@ endfunction
|
||||
|
||||
" Parse parses the given items based on the global errorformat and
|
||||
" populates the location list.
|
||||
function! go#list#Parse(listtype, items)
|
||||
function! go#list#Parse(listtype, items) abort
|
||||
let l:listtype = go#list#Type(a:listtype)
|
||||
if l:listtype == "locationlist"
|
||||
lgetexpr a:items
|
||||
@ -94,7 +101,7 @@ function! go#list#Parse(listtype, items)
|
||||
endfunction
|
||||
|
||||
" JumpToFirst jumps to the first item in the location list
|
||||
function! go#list#JumpToFirst(listtype)
|
||||
function! go#list#JumpToFirst(listtype) abort
|
||||
let l:listtype = go#list#Type(a:listtype)
|
||||
if l:listtype == "locationlist"
|
||||
ll 1
|
||||
@ -104,7 +111,7 @@ function! go#list#JumpToFirst(listtype)
|
||||
endfunction
|
||||
|
||||
" Clean cleans the location list
|
||||
function! go#list#Clean(listtype)
|
||||
function! go#list#Clean(listtype) abort
|
||||
let l:listtype = go#list#Type(a:listtype)
|
||||
if l:listtype == "locationlist"
|
||||
lex []
|
||||
@ -113,7 +120,7 @@ function! go#list#Clean(listtype)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#list#Type(listtype)
|
||||
function! go#list#Type(listtype) abort
|
||||
if g:go_list_type == "locationlist"
|
||||
return "locationlist"
|
||||
elseif g:go_list_type == "quickfix"
|
||||
|
@ -28,7 +28,7 @@ if len(s:goarch) == 0
|
||||
endif
|
||||
endif
|
||||
|
||||
function! go#package#Paths()
|
||||
function! go#package#Paths() abort
|
||||
let dirs = []
|
||||
|
||||
if !exists("s:goroot")
|
||||
@ -54,7 +54,7 @@ function! go#package#Paths()
|
||||
return dirs
|
||||
endfunction
|
||||
|
||||
function! go#package#ImportPath(arg)
|
||||
function! go#package#ImportPath(arg) abort
|
||||
let path = fnamemodify(resolve(a:arg), ':p')
|
||||
let dirs = go#package#Paths()
|
||||
|
||||
@ -77,7 +77,7 @@ function! go#package#ImportPath(arg)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#package#FromPath(arg)
|
||||
function! go#package#FromPath(arg) abort
|
||||
let path = fnamemodify(resolve(a:arg), ':p')
|
||||
let dirs = go#package#Paths()
|
||||
|
||||
@ -99,7 +99,7 @@ function! go#package#FromPath(arg)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#package#CompleteMembers(package, member)
|
||||
function! go#package#CompleteMembers(package, member) abort
|
||||
silent! let content = go#util#System('godoc ' . a:package)
|
||||
if go#util#ShellError() || !len(content)
|
||||
return []
|
||||
@ -118,7 +118,7 @@ function! go#package#CompleteMembers(package, member)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! go#package#Complete(ArgLead, CmdLine, CursorPos)
|
||||
function! go#package#Complete(ArgLead, CmdLine, CursorPos) abort
|
||||
let words = split(a:CmdLine, '\s\+', 1)
|
||||
|
||||
" do not complete package members for these commands
|
||||
|
@ -8,7 +8,7 @@ let s:initial_go_path = ""
|
||||
" echoes the current GOPATH, if an argument is passed it replaces the current
|
||||
" GOPATH with it. If two double quotes are passed (the empty string in go),
|
||||
" it'll clear the GOPATH and will restore to the initial GOPATH.
|
||||
function! go#path#GoPath(...)
|
||||
function! go#path#GoPath(...) abort
|
||||
" we have an argument, replace GOPATH
|
||||
if len(a:000)
|
||||
" clears the current manually set GOPATH and restores it to the
|
||||
@ -35,7 +35,7 @@ endfunction
|
||||
" Default returns the default GOPATH. If there is a single GOPATH it returns
|
||||
" it. For multiple GOPATHS separated with a the OS specific separator, only
|
||||
" the first one is returned
|
||||
function! go#path#Default()
|
||||
function! go#path#Default() abort
|
||||
let go_paths = split($GOPATH, go#util#PathListSep())
|
||||
|
||||
if len(go_paths) == 1
|
||||
@ -47,7 +47,7 @@ endfunction
|
||||
|
||||
" HasPath checks whether the given path exists in GOPATH environment variable
|
||||
" or not
|
||||
function! go#path#HasPath(path)
|
||||
function! go#path#HasPath(path) abort
|
||||
let go_paths = split($GOPATH, go#util#PathListSep())
|
||||
let last_char = strlen(a:path) - 1
|
||||
|
||||
@ -69,7 +69,7 @@ endfunction
|
||||
" Godeps, GB, it will modify the GOPATH so those directories take precedence
|
||||
" over the current GOPATH. It also detects diretories whose are outside
|
||||
" GOPATH.
|
||||
function! go#path#Detect()
|
||||
function! go#path#Detect() abort
|
||||
let gopath = $GOPATH
|
||||
|
||||
" don't lookup for godeps if autodetect is disabled.
|
||||
@ -115,7 +115,7 @@ endfunction
|
||||
|
||||
|
||||
" BinPath returns the binary path of installed go tools.
|
||||
function! go#path#BinPath()
|
||||
function! go#path#BinPath() abort
|
||||
let bin_path = ""
|
||||
|
||||
" check if our global custom path is set, if not check if $GOBIN is set so
|
||||
@ -135,7 +135,7 @@ endfunction
|
||||
|
||||
" CheckBinPath checks whether the given binary exists or not and returns the
|
||||
" path of the binary. It returns an empty string doesn't exists.
|
||||
function! go#path#CheckBinPath(binpath)
|
||||
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
|
||||
@ -161,7 +161,7 @@ function! go#path#CheckBinPath(binpath)
|
||||
" just get the basename
|
||||
let basename = fnamemodify(binpath, ":t")
|
||||
if !executable(basename)
|
||||
echo "vim-go: could not find '" . basename . "'. Run :GoInstallBinaries to fix it."
|
||||
echom "vim-go: could not find '" . basename . "'. Run :GoInstallBinaries to fix it."
|
||||
" restore back!
|
||||
let $PATH = old_path
|
||||
return ""
|
||||
|
@ -3,7 +3,7 @@ if !exists("g:go_play_open_browser")
|
||||
endif
|
||||
|
||||
|
||||
function! go#play#Share(count, line1, line2)
|
||||
function! go#play#Share(count, line1, line2) abort
|
||||
if !executable('curl')
|
||||
echohl ErrorMsg | echomsg "vim-go: require 'curl' command" | echohl None
|
||||
return
|
||||
@ -42,7 +42,7 @@ function! go#play#Share(count, line1, line2)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:get_visual_content()
|
||||
function! s:get_visual_content() abort
|
||||
let save_regcont = @"
|
||||
let save_regtype = getregtype('"')
|
||||
silent! normal! gvy
|
||||
@ -55,7 +55,7 @@ endfunction
|
||||
" http://stackoverflow.com/questions/1533565/how-to-get-visually-selected-text-in-vimscript
|
||||
" another function that returns the content of visual selection, it's not used
|
||||
" but might be useful in the future
|
||||
function! s:get_visual_selection()
|
||||
function! s:get_visual_selection() abort
|
||||
let [lnum1, col1] = getpos("'<")[1:2]
|
||||
let [lnum2, col2] = getpos("'>")[1:2]
|
||||
|
||||
@ -72,7 +72,7 @@ endfunction
|
||||
|
||||
" following two functions are from: https://github.com/mattn/gist-vim
|
||||
" thanks @mattn
|
||||
function! s:get_browser_command()
|
||||
function! s:get_browser_command() abort
|
||||
let go_play_browser_command = get(g:, 'go_play_browser_command', '')
|
||||
if go_play_browser_command == ''
|
||||
if has('win32') || has('win64')
|
||||
|
@ -6,22 +6,22 @@ if !exists("g:go_gorename_prefill")
|
||||
let g:go_gorename_prefill = 1
|
||||
endif
|
||||
|
||||
function! go#rename#Rename(bang, ...)
|
||||
let to = ""
|
||||
function! go#rename#Rename(bang, ...) abort
|
||||
let to_identifier = ""
|
||||
if a:0 == 0
|
||||
let from = expand("<cword>")
|
||||
let ask = printf("vim-go: rename '%s' to: ", from)
|
||||
if g:go_gorename_prefill
|
||||
let to = input(ask, from)
|
||||
let to_identifier = input(ask, from)
|
||||
else
|
||||
let to = input(ask)
|
||||
let to_identifier = input(ask)
|
||||
endif
|
||||
redraw!
|
||||
if empty(to)
|
||||
if empty(to_identifier)
|
||||
return
|
||||
endif
|
||||
else
|
||||
let to = a:1
|
||||
let to_identifier = a:1
|
||||
endif
|
||||
|
||||
"return with a warning if the bin doesn't exist
|
||||
@ -32,10 +32,79 @@ function! go#rename#Rename(bang, ...)
|
||||
|
||||
let fname = expand('%:p')
|
||||
let pos = go#util#OffsetCursor()
|
||||
let cmd = printf('%s -offset %s -to %s', shellescape(bin_path), shellescape(printf('%s:#%d', fname, pos)), shellescape(to))
|
||||
let offset = printf('%s:#%d', fname, pos)
|
||||
|
||||
let out = go#tool#ExecuteInDir(cmd)
|
||||
" 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]
|
||||
|
||||
if go#util#has_job()
|
||||
call go#util#EchoProgress(printf("renaming to '%s' ...", to_identifier))
|
||||
call s:rename_job({
|
||||
\ 'cmd': cmd,
|
||||
\ 'bang': a:bang,
|
||||
\})
|
||||
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)
|
||||
endfunction
|
||||
|
||||
function s:rename_job(args)
|
||||
let messages = []
|
||||
function! s:callback(chan, msg) closure
|
||||
call add(messages, a:msg)
|
||||
endfunction
|
||||
|
||||
let status_dir = expand('%:p:h')
|
||||
|
||||
function! s:close_cb(chan) closure
|
||||
let l:job = ch_getjob(a:chan)
|
||||
let l:info = job_info(l:job)
|
||||
|
||||
let status = {
|
||||
\ 'desc': 'last status',
|
||||
\ 'type': "gorename",
|
||||
\ 'state': "finished",
|
||||
\ }
|
||||
|
||||
if l:info.exitval
|
||||
let status.state = "failed"
|
||||
endif
|
||||
|
||||
call go#statusline#Update(status_dir, status)
|
||||
|
||||
call s:parse_errors(l:info.exitval, a:args.bang, messages)
|
||||
endfunction
|
||||
|
||||
let start_options = {
|
||||
\ 'callback': function("s:callback"),
|
||||
\ 'close_cb': function("s:close_cb"),
|
||||
\ }
|
||||
|
||||
" modify GOPATH if needed
|
||||
let old_gopath = $GOPATH
|
||||
let $GOPATH = go#path#Detect()
|
||||
|
||||
call go#statusline#Update(status_dir, {
|
||||
\ 'desc': "current status",
|
||||
\ 'type': "gorename",
|
||||
\ 'state': "started",
|
||||
\})
|
||||
|
||||
call job_start(a:args.cmd, start_options)
|
||||
|
||||
let $GOPATH = old_gopath
|
||||
endfunction
|
||||
|
||||
function s:parse_errors(exit_val, bang, out)
|
||||
" reload all files to reflect the new changes. We explicitly call
|
||||
" checktime to trigger a reload of all files. See
|
||||
" http://www.mail-archive.com/vim@vim.org/msg05900.html for more info
|
||||
@ -45,28 +114,28 @@ function! go#rename#Rename(bang, ...)
|
||||
silent! checktime
|
||||
let &autoread = current_autoread
|
||||
|
||||
" strip out newline on the end that gorename puts. If we don't remove, it
|
||||
" will trigger the 'Hit ENTER to continue' prompt
|
||||
let clean = split(out, '\n')
|
||||
|
||||
let l:listtype = "quickfix"
|
||||
if go#util#ShellError() != 0
|
||||
let errors = go#tool#ParseErrors(split(out, '\n'))
|
||||
call go#list#Populate(l:listtype, errors)
|
||||
if a:exit_val != 0
|
||||
call go#util#EchoError("FAILED")
|
||||
let errors = go#tool#ParseErrors(a:out)
|
||||
call go#list#Populate(l:listtype, errors, 'Rename')
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
if !empty(errors) && !a:bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
elseif empty(errors)
|
||||
" failed to parse errors, output the original content
|
||||
call go#util#EchoError(out)
|
||||
call go#util#EchoError(join(a:out, ""))
|
||||
endif
|
||||
|
||||
return
|
||||
else
|
||||
call go#list#Clean(l:listtype)
|
||||
call go#list#Window(l:listtype)
|
||||
redraw | echon "vim-go: " | echohl Function | echon clean[0] | echohl None
|
||||
endif
|
||||
|
||||
" strip out newline on the end that gorename puts. If we don't remove, it
|
||||
" will trigger the 'Hit ENTER to continue' prompt
|
||||
call go#list#Clean(l:listtype)
|
||||
call go#list#Window(l:listtype)
|
||||
call go#util#EchoSuccess(a:out[0])
|
||||
|
||||
" refresh the buffer so we can see the new content
|
||||
" TODO(arslan): also find all other buffers and refresh them too. For this
|
||||
" we need a way to get the list of changes from gorename upon an success
|
||||
|
112
sources_non_forked/vim-go/autoload/go/statusline.vim
Normal file
112
sources_non_forked/vim-go/autoload/go/statusline.vim
Normal file
@ -0,0 +1,112 @@
|
||||
" Statusline
|
||||
""""""""""""""""""""""""""""""""
|
||||
|
||||
" s:statuses is a global reference to all statuses. It stores the statuses per
|
||||
" import paths (map[string]status), where each status is unique per its
|
||||
" type. Current status dict is in form:
|
||||
" {
|
||||
" 'desc' : 'Job description',
|
||||
" 'state' : 'Job state, such as success, failure, etc..',
|
||||
" 'type' : 'Job type, such as build, test, etc..'
|
||||
" 'created_at' : 'Time it was created as seconds since 1st Jan 1970'
|
||||
" }
|
||||
let s:statuses = {}
|
||||
|
||||
" timer_id for cleaner
|
||||
let s:timer_id = 0
|
||||
|
||||
" last_status stores the last generated text per status
|
||||
let s:last_status = ""
|
||||
|
||||
" Show returns the current status of the job for 20 seconds (configurable). It
|
||||
" displays it in form of 'desc: [type|state]' if there is any state available,
|
||||
" if not it returns an empty string. This function should be plugged directly
|
||||
" into the statusline.
|
||||
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 s:timer_id = timer_start(interval, function('go#statusline#Clear'), {'repeat': -1})
|
||||
endif
|
||||
|
||||
" nothing to show
|
||||
if empty(s:statuses)
|
||||
return ''
|
||||
endif
|
||||
|
||||
let status_dir = expand('%:p:h')
|
||||
|
||||
if !has_key(s:statuses, status_dir)
|
||||
return ''
|
||||
endif
|
||||
|
||||
let status = s:statuses[status_dir]
|
||||
if !has_key(status, 'desc') || !has_key(status, 'state') || !has_key(status, 'type')
|
||||
return ''
|
||||
endif
|
||||
|
||||
let status_text = printf("[%s|%s]", status.type, status.state)
|
||||
if empty(status_text)
|
||||
return ''
|
||||
endif
|
||||
|
||||
" only update highlight if status has changed.
|
||||
if status_text != s:last_status
|
||||
if status.state =~ "success" || status.state =~ "finished"
|
||||
hi goStatusLineColor cterm=bold ctermbg=76 ctermfg=22
|
||||
elseif status.state =~ "started" || status.state =~ "analysing"
|
||||
hi goStatusLineColor cterm=bold ctermbg=208 ctermfg=88
|
||||
elseif status.state =~ "failed"
|
||||
hi goStatusLineColor cterm=bold ctermbg=196 ctermfg=52
|
||||
endif
|
||||
endif
|
||||
|
||||
let s:last_status = status_text
|
||||
return status_text
|
||||
endfunction
|
||||
|
||||
" Update updates (adds) the statusline for the given status_dir with the
|
||||
" given status dict. It overrides any previously set status.
|
||||
function! go#statusline#Update(status_dir, status) abort
|
||||
let a:status.created_at = reltime()
|
||||
let s:statuses[a:status_dir] = a:status
|
||||
|
||||
" force to update the statusline, otherwise the user needs to move the
|
||||
" cursor
|
||||
exe 'let &ro = &ro'
|
||||
|
||||
" before we stop the timer, check if we have any previous jobs to be cleaned
|
||||
" up. Otherwise every job will reset the timer when this function is called
|
||||
" and thus old jobs will never be cleaned
|
||||
call go#statusline#Clear(0)
|
||||
|
||||
" also reset the timer, so the user has time to see it in the statusline.
|
||||
" Setting the timer_id to 0 will trigger a new cleaner routine.
|
||||
call timer_stop(s:timer_id)
|
||||
let s:timer_id = 0
|
||||
endfunction
|
||||
|
||||
" Clear clears all currently stored statusline data. The timer_id argument is
|
||||
" just a placeholder so we can pass it to a timer_start() function if needed.
|
||||
function! go#statusline#Clear(timer_id) abort
|
||||
for [status_dir, status] in items(s:statuses)
|
||||
let elapsed_time = reltimestr(reltime(status.created_at))
|
||||
" strip whitespace
|
||||
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
|
||||
|
||||
if str2nr(elapsed_time) > 10
|
||||
call remove(s:statuses, status_dir)
|
||||
endif
|
||||
endfor
|
||||
|
||||
if len(s:statuses) == 0
|
||||
let s:statuses = {}
|
||||
endif
|
||||
|
||||
" force to update the statusline, otherwise the user needs to move the
|
||||
" cursor
|
||||
exe 'let &ro = &ro'
|
||||
endfunction
|
||||
|
||||
" vim: sw=2 ts=2 et
|
@ -1,6 +1,7 @@
|
||||
let s:current_file = expand("<sfile>")
|
||||
|
||||
function! go#template#create()
|
||||
function! go#template#create() abort
|
||||
let l:go_template_use_pkg = get(g:, 'go_template_use_pkg', 0)
|
||||
let l:root_dir = fnamemodify(s:current_file, ':h:h:h')
|
||||
|
||||
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
||||
@ -10,12 +11,19 @@ function! go#template#create()
|
||||
let l:package_name = go#tool#PackageName()
|
||||
|
||||
" if we can't figure out any package name(no Go files or non Go package
|
||||
" files) from the directory create the template
|
||||
if l:package_name == -1
|
||||
" files) from the directory create the template or use the cwd
|
||||
" as the name
|
||||
if l:package_name == -1 && l:go_template_use_pkg != 1
|
||||
let l:template_file = get(g:, 'go_template_file', "hello_world.go")
|
||||
let l:template_path = go#util#Join(l:root_dir, "templates", l:template_file)
|
||||
exe '0r ' . fnameescape(l:template_path)
|
||||
$delete _
|
||||
elseif l:package_name == -1 && l:go_template_use_pkg == 1
|
||||
" cwd is now the dir of the package
|
||||
let l:path = fnamemodify(getcwd(), ':t')
|
||||
let l:content = printf("package %s", l:path)
|
||||
call append(0, l:content)
|
||||
$delete _
|
||||
else
|
||||
let l:content = printf("package %s", l:package_name)
|
||||
call append(0, l:content)
|
||||
@ -28,7 +36,7 @@ function! go#template#create()
|
||||
execute cd . fnameescape(dir)
|
||||
endfunction
|
||||
|
||||
function! go#template#ToggleAutoCreate()
|
||||
function! go#template#ToggleAutoCreate() abort
|
||||
if get(g:, "go_template_autocreate", 1)
|
||||
let g:go_template_autocreate = 0
|
||||
call go#util#EchoProgress("auto template create disabled")
|
||||
|
@ -7,12 +7,12 @@ let s:jobs = {}
|
||||
|
||||
" 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)
|
||||
function! go#term#new(bang, cmd) abort
|
||||
return go#term#newmode(a:bang, a:cmd, g:go_term_mode)
|
||||
endfunction
|
||||
|
||||
" new creates a new terminal with the given command and window mode.
|
||||
function! go#term#newmode(bang, cmd, mode)
|
||||
function! go#term#newmode(bang, cmd, mode) abort
|
||||
let mode = a:mode
|
||||
if empty(mode)
|
||||
let mode = g:go_term_mode
|
||||
@ -36,7 +36,7 @@ function! go#term#newmode(bang, cmd, mode)
|
||||
setlocal noswapfile
|
||||
setlocal nobuflisted
|
||||
|
||||
let job = {
|
||||
let job = {
|
||||
\ 'stderr' : [],
|
||||
\ 'stdout' : [],
|
||||
\ 'bang' : a:bang,
|
||||
@ -53,6 +53,7 @@ function! go#term#newmode(bang, cmd, mode)
|
||||
let $GOPATH = old_gopath
|
||||
|
||||
let job.id = id
|
||||
let job.cmd = a:cmd
|
||||
startinsert
|
||||
|
||||
" resize new term if needed.
|
||||
@ -74,7 +75,7 @@ function! go#term#newmode(bang, cmd, mode)
|
||||
return id
|
||||
endfunction
|
||||
|
||||
function! s:on_stdout(job_id, data)
|
||||
function! s:on_stdout(job_id, data, event) dict abort
|
||||
if !has_key(s:jobs, a:job_id)
|
||||
return
|
||||
endif
|
||||
@ -83,7 +84,7 @@ function! s:on_stdout(job_id, data)
|
||||
call extend(job.stdout, a:data)
|
||||
endfunction
|
||||
|
||||
function! s:on_stderr(job_id, data)
|
||||
function! s:on_stderr(job_id, data, event) dict abort
|
||||
if !has_key(s:jobs, a:job_id)
|
||||
return
|
||||
endif
|
||||
@ -92,7 +93,7 @@ function! s:on_stderr(job_id, data)
|
||||
call extend(job.stderr, a:data)
|
||||
endfunction
|
||||
|
||||
function! s:on_exit(job_id, exit_status)
|
||||
function! s:on_exit(job_id, exit_status, event) dict abort
|
||||
if !has_key(s:jobs, a:job_id)
|
||||
return
|
||||
endif
|
||||
@ -113,9 +114,9 @@ function! s:on_exit(job_id, exit_status)
|
||||
|
||||
if !empty(errors)
|
||||
" close terminal we don't need it anymore
|
||||
close
|
||||
close
|
||||
|
||||
call go#list#Populate(l:listtype, errors)
|
||||
call go#list#Populate(l:listtype, errors, job.cmd)
|
||||
call go#list#Window(l:listtype, len(errors))
|
||||
if !self.bang
|
||||
call go#list#JumpToFirst(l:listtype)
|
||||
|
@ -13,7 +13,7 @@ endif
|
||||
" < >
|
||||
" t for tag
|
||||
|
||||
function! go#textobj#Function(mode)
|
||||
function! go#textobj#Function(mode) abort
|
||||
let offset = go#util#OffsetCursor()
|
||||
|
||||
let fname = shellescape(expand("%:p"))
|
||||
@ -84,7 +84,7 @@ function! go#textobj#Function(mode)
|
||||
call cursor(info.rbrace.line-1, 1)
|
||||
endfunction
|
||||
|
||||
function! go#textobj#FunctionJump(mode, direction)
|
||||
function! go#textobj#FunctionJump(mode, direction) abort
|
||||
" get count of the motion. This should be done before all the normal
|
||||
" expressions below as those reset this value(because they have zero
|
||||
" count!). We abstract -1 because the index starts from 0 in motion.
|
||||
|
@ -1,4 +1,4 @@
|
||||
function! go#tool#Files()
|
||||
function! go#tool#Files() abort
|
||||
if go#util#IsWin()
|
||||
let format = '{{range $f := .GoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}{{range $f := .CgoFiles}}{{$.Dir}}\{{$f}}{{printf \"\n\"}}{{end}}'
|
||||
else
|
||||
@ -9,7 +9,7 @@ function! go#tool#Files()
|
||||
return split(out, '\n')
|
||||
endfunction
|
||||
|
||||
function! go#tool#Deps()
|
||||
function! go#tool#Deps() abort
|
||||
if go#util#IsWin()
|
||||
let format = '{{range $f := .Deps}}{{$f}}{{printf \"\n\"}}{{end}}'
|
||||
else
|
||||
@ -20,7 +20,7 @@ function! go#tool#Deps()
|
||||
return split(out, '\n')
|
||||
endfunction
|
||||
|
||||
function! go#tool#Imports()
|
||||
function! go#tool#Imports() abort
|
||||
let imports = {}
|
||||
if go#util#IsWin()
|
||||
let format = '{{range $f := .Imports}}{{$f}}{{printf \"\n\"}}{{end}}'
|
||||
@ -43,7 +43,18 @@ function! go#tool#Imports()
|
||||
return imports
|
||||
endfunction
|
||||
|
||||
function! go#tool#PackageName()
|
||||
function! go#tool#Info(auto) abort
|
||||
let l:mode = get(g:, 'go_info_mode', 'gocode')
|
||||
if l:mode == 'gocode'
|
||||
call go#complete#Info(a:auto)
|
||||
elseif l:mode == 'guru'
|
||||
call go#guru#DescribeInfo()
|
||||
else
|
||||
call go#util#EchoError('go_info_mode value: '. l:mode .' is not valid. Valid values are: [gocode, guru]')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#tool#PackageName() abort
|
||||
let command = "go list -f \"{{.Name}}\""
|
||||
let out = go#tool#ExecuteInDir(command)
|
||||
if go#util#ShellError() != 0
|
||||
@ -53,7 +64,7 @@ function! go#tool#PackageName()
|
||||
return split(out, '\n')[0]
|
||||
endfunction
|
||||
|
||||
function! go#tool#ParseErrors(lines)
|
||||
function! go#tool#ParseErrors(lines) abort
|
||||
let errors = []
|
||||
|
||||
for line in a:lines
|
||||
@ -85,7 +96,7 @@ endfunction
|
||||
|
||||
"FilterValids filters the given items with only items that have a valid
|
||||
"filename. Any non valid filename is filtered out.
|
||||
function! go#tool#FilterValids(items)
|
||||
function! go#tool#FilterValids(items) abort
|
||||
" Remove any nonvalid filename from the location list to avoid opening an
|
||||
" empty buffer. See https://github.com/fatih/vim-go/issues/287 for
|
||||
" details.
|
||||
@ -141,7 +152,7 @@ endfunction
|
||||
|
||||
" Exists checks whether the given importpath exists or not. It returns 0 if
|
||||
" the importpath exists under GOPATH.
|
||||
function! go#tool#Exists(importpath)
|
||||
function! go#tool#Exists(importpath) abort
|
||||
let command = "go list ". a:importpath
|
||||
let out = go#tool#ExecuteInDir(command)
|
||||
|
||||
@ -155,7 +166,7 @@ endfunction
|
||||
|
||||
" following two functions are from: https://github.com/mattn/gist-vim
|
||||
" thanks @mattn
|
||||
function! s:get_browser_command()
|
||||
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()
|
||||
@ -173,7 +184,7 @@ function! s:get_browser_command()
|
||||
return go_play_browser_command
|
||||
endfunction
|
||||
|
||||
function! go#tool#OpenBrowser(url)
|
||||
function! go#tool#OpenBrowser(url) abort
|
||||
let cmd = s:get_browser_command()
|
||||
if len(cmd) == 0
|
||||
redraw
|
||||
|
@ -1,7 +1,7 @@
|
||||
let s:buf_nr = -1
|
||||
|
||||
"OpenWindow opens a new scratch window and put's the content into the window
|
||||
function! go#ui#OpenWindow(title, content, filetype)
|
||||
function! go#ui#OpenWindow(title, content, filetype) abort
|
||||
" Ensure there's only one return window in this session/tabpage
|
||||
call go#util#Windo("unlet! w:vim_go_return_window")
|
||||
" Mark the window we're leaving as such
|
||||
@ -54,7 +54,7 @@ function! go#ui#OpenWindow(title, content, filetype)
|
||||
echon
|
||||
endfunction
|
||||
|
||||
function! go#ui#GetReturnWindow()
|
||||
function! go#ui#GetReturnWindow() abort
|
||||
for l:wn in range(1, winnr("$"))
|
||||
if !empty(getwinvar(l:wn, "vim_go_return_window"))
|
||||
return l:wn
|
||||
@ -63,7 +63,7 @@ function! go#ui#GetReturnWindow()
|
||||
endfunction
|
||||
|
||||
" CloseWindow closes the current window
|
||||
function! go#ui#CloseWindow()
|
||||
function! go#ui#CloseWindow() abort
|
||||
" Close any window associated with the ui buffer, if it's there
|
||||
if bufexists(s:buf_nr)
|
||||
let ui_window_number = bufwinnr(s:buf_nr)
|
||||
@ -82,7 +82,7 @@ endfunction
|
||||
|
||||
" OpenDefinition parses the current line and jumps to it by openening a new
|
||||
" tab
|
||||
function! go#ui#OpenDefinition(filter)
|
||||
function! go#ui#OpenDefinition(filter) abort
|
||||
let curline = getline('.')
|
||||
|
||||
" don't touch our first line or any blank line
|
||||
|
@ -1,5 +1,5 @@
|
||||
" PathSep returns the appropriate OS specific path separator.
|
||||
function! go#util#PathSep()
|
||||
function! go#util#PathSep() abort
|
||||
if go#util#IsWin()
|
||||
return '\'
|
||||
endif
|
||||
@ -7,7 +7,7 @@ function! go#util#PathSep()
|
||||
endfunction
|
||||
|
||||
" PathListSep returns the appropriate OS specific path list separator.
|
||||
function! go#util#PathListSep()
|
||||
function! go#util#PathListSep() abort
|
||||
if go#util#IsWin()
|
||||
return ";"
|
||||
endif
|
||||
@ -15,7 +15,7 @@ function! go#util#PathListSep()
|
||||
endfunction
|
||||
|
||||
" LineEnding returns the correct line ending, based on the current fileformat
|
||||
function! go#util#LineEnding()
|
||||
function! go#util#LineEnding() abort
|
||||
if &fileformat == 'dos'
|
||||
return "\r\n"
|
||||
elseif &fileformat == 'mac'
|
||||
@ -27,12 +27,12 @@ endfunction
|
||||
|
||||
" Join joins any number of path elements into a single path, adding a
|
||||
" Separator if necessary and returns the result
|
||||
function! go#util#Join(...)
|
||||
function! go#util#Join(...) abort
|
||||
return join(a:000, go#util#PathSep())
|
||||
endfunction
|
||||
|
||||
" IsWin returns 1 if current OS is Windows or 0 otherwise
|
||||
function! go#util#IsWin()
|
||||
function! go#util#IsWin() abort
|
||||
let win = ['win16', 'win32', 'win64', 'win95']
|
||||
for w in win
|
||||
if (has(w))
|
||||
@ -43,12 +43,18 @@ function! go#util#IsWin()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! go#util#has_job() abort
|
||||
" 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")
|
||||
endfunction
|
||||
|
||||
let s:env_cache = {}
|
||||
|
||||
" env returns the go environment variable for the given key. Where key can be
|
||||
" GOARCH, GOOS, GOROOT, etc... It caches the result and returns the cached
|
||||
" version.
|
||||
function! go#util#env(key)
|
||||
function! go#util#env(key) abort
|
||||
let l:key = tolower(a:key)
|
||||
if has_key(s:env_cache, l:key)
|
||||
return s:env_cache[l:key]
|
||||
@ -68,81 +74,49 @@ function! go#util#env(key)
|
||||
return l:var
|
||||
endfunction
|
||||
|
||||
function! go#util#goarch()
|
||||
function! go#util#goarch() abort
|
||||
return substitute(go#util#System('go env GOARCH'), '\n', '', 'g')
|
||||
endfunction
|
||||
|
||||
function! go#util#goos()
|
||||
function! go#util#goos() abort
|
||||
return substitute(go#util#System('go env GOOS'), '\n', '', 'g')
|
||||
endfunction
|
||||
|
||||
function! go#util#goroot()
|
||||
function! go#util#goroot() abort
|
||||
return substitute(go#util#System('go env GOROOT'), '\n', '', 'g')
|
||||
endfunction
|
||||
|
||||
function! go#util#gopath()
|
||||
function! go#util#gopath() abort
|
||||
return substitute(go#util#System('go env GOPATH'), '\n', '', 'g')
|
||||
endfunction
|
||||
|
||||
function! go#util#osarch()
|
||||
function! go#util#osarch() abort
|
||||
return go#util#goos() . '_' . go#util#goarch()
|
||||
endfunction
|
||||
|
||||
"Check if has vimproc
|
||||
function! s:has_vimproc()
|
||||
if !exists('g:go#use_vimproc')
|
||||
if go#util#IsWin()
|
||||
try
|
||||
call vimproc#version()
|
||||
let exists_vimproc = 1
|
||||
catch
|
||||
let exists_vimproc = 0
|
||||
endtry
|
||||
else
|
||||
let exists_vimproc = 0
|
||||
endif
|
||||
|
||||
let g:go#use_vimproc = exists_vimproc
|
||||
endif
|
||||
|
||||
return g:go#use_vimproc
|
||||
endfunction
|
||||
|
||||
if s:has_vimproc()
|
||||
let s:vim_system = get(g:, 'gocomplete#system_function', 'vimproc#system2')
|
||||
let s:vim_shell_error = get(g:, 'gocomplete#shell_error_function', 'vimproc#get_last_status')
|
||||
else
|
||||
let s:vim_system = get(g:, 'gocomplete#system_function', 'system')
|
||||
let s:vim_shell_error = ''
|
||||
endif
|
||||
|
||||
" System runs a shell command. It will reset the shell to /bin/sh for Unix-like
|
||||
" systems if it is executable.
|
||||
function! go#util#System(str, ...)
|
||||
function! go#util#System(str, ...) abort
|
||||
let l:shell = &shell
|
||||
if !go#util#IsWin() && executable('/bin/sh')
|
||||
let &shell = '/bin/sh'
|
||||
endif
|
||||
|
||||
try
|
||||
let l:output = call(s:vim_system, [a:str] + a:000)
|
||||
let l:output = call('system', [a:str] + a:000)
|
||||
return l:output
|
||||
finally
|
||||
let &shell = l:shell
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! go#util#ShellError()
|
||||
if empty(s:vim_shell_error)
|
||||
return v:shell_error
|
||||
endif
|
||||
return call(s:vim_shell_error, [])
|
||||
function! go#util#ShellError() abort
|
||||
return v:shell_error
|
||||
endfunction
|
||||
|
||||
|
||||
" StripPath strips the path's last character if it's a path separator.
|
||||
" example: '/foo/bar/' -> '/foo/bar'
|
||||
function! go#util#StripPathSep(path)
|
||||
function! go#util#StripPathSep(path) abort
|
||||
let last_char = strlen(a:path) - 1
|
||||
if a:path[last_char] == go#util#PathSep()
|
||||
return strpart(a:path, 0, last_char)
|
||||
@ -153,13 +127,13 @@ endfunction
|
||||
|
||||
" StripTrailingSlash strips the trailing slash from the given path list.
|
||||
" example: ['/foo/bar/'] -> ['/foo/bar']
|
||||
function! go#util#StripTrailingSlash(paths)
|
||||
function! go#util#StripTrailingSlash(paths) abort
|
||||
return map(copy(a:paths), 'go#util#StripPathSep(v:val)')
|
||||
endfunction
|
||||
|
||||
" Shelljoin returns a shell-safe string representation of arglist. The
|
||||
" {special} argument of shellescape() may optionally be passed.
|
||||
function! go#util#Shelljoin(arglist, ...)
|
||||
function! go#util#Shelljoin(arglist, ...) abort
|
||||
try
|
||||
let ssl_save = &shellslash
|
||||
set noshellslash
|
||||
@ -174,9 +148,6 @@ function! go#util#Shelljoin(arglist, ...)
|
||||
endfunction
|
||||
|
||||
fu! go#util#Shellescape(arg)
|
||||
if s:has_vimproc()
|
||||
return vimproc#shellescape(a:arg)
|
||||
endif
|
||||
try
|
||||
let ssl_save = &shellslash
|
||||
set noshellslash
|
||||
@ -188,7 +159,7 @@ endf
|
||||
|
||||
" Shelllist returns a shell-safe representation of the items in the given
|
||||
" arglist. The {special} argument of shellescape() may optionally be passed.
|
||||
function! go#util#Shelllist(arglist, ...)
|
||||
function! go#util#Shelllist(arglist, ...) abort
|
||||
try
|
||||
let ssl_save = &shellslash
|
||||
set noshellslash
|
||||
@ -202,7 +173,7 @@ function! go#util#Shelllist(arglist, ...)
|
||||
endfunction
|
||||
|
||||
" Returns the byte offset for line and column
|
||||
function! go#util#Offset(line, col)
|
||||
function! go#util#Offset(line, col) abort
|
||||
if &encoding != 'utf-8'
|
||||
let sep = go#util#LineEnding()
|
||||
let buf = a:line == 1 ? '' : (join(getline(1, a:line-1), sep) . sep)
|
||||
@ -213,13 +184,13 @@ function! go#util#Offset(line, col)
|
||||
endfunction
|
||||
"
|
||||
" Returns the byte offset for the cursor
|
||||
function! go#util#OffsetCursor()
|
||||
function! go#util#OffsetCursor() abort
|
||||
return go#util#Offset(line('.'), col('.'))
|
||||
endfunction
|
||||
|
||||
" Windo is like the built-in :windo, only it returns to the window the command
|
||||
" was issued from
|
||||
function! go#util#Windo(command)
|
||||
function! go#util#Windo(command) abort
|
||||
let s:currentWindow = winnr()
|
||||
try
|
||||
execute "windo " . a:command
|
||||
@ -231,7 +202,7 @@ endfunction
|
||||
|
||||
" snippetcase converts the given word to given preferred snippet setting type
|
||||
" case.
|
||||
function! go#util#snippetcase(word)
|
||||
function! go#util#snippetcase(word) abort
|
||||
let l:snippet_case = get(g:, 'go_snippet_case_type', "snakecase")
|
||||
if l:snippet_case == "snakecase"
|
||||
return go#util#snakecase(a:word)
|
||||
@ -244,7 +215,7 @@ endfunction
|
||||
|
||||
" snakecase converts a string to snake case. i.e: FooBar -> foo_bar
|
||||
" Copied from tpope/vim-abolish
|
||||
function! go#util#snakecase(word)
|
||||
function! go#util#snakecase(word) abort
|
||||
let word = substitute(a:word,'::','/','g')
|
||||
let word = substitute(word,'\(\u\+\)\(\u\l\)','\1_\2','g')
|
||||
let word = substitute(word,'\(\l\|\d\)\(\u\)','\1_\2','g')
|
||||
@ -255,7 +226,7 @@ endfunction
|
||||
|
||||
" camelcase converts a string to camel case. i.e: FooBar -> fooBar
|
||||
" Copied from tpope/vim-abolish
|
||||
function! go#util#camelcase(word)
|
||||
function! go#util#camelcase(word) abort
|
||||
let word = substitute(a:word, '-', '_', 'g')
|
||||
if word !~# '_' && word =~# '\l'
|
||||
return substitute(word,'^.','\l&','')
|
||||
@ -264,7 +235,7 @@ function! go#util#camelcase(word)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! go#util#AddTags(line1, line2, ...)
|
||||
function! go#util#AddTags(line1, line2, ...) abort
|
||||
" default is json
|
||||
let l:keys = ["json"]
|
||||
if a:0
|
||||
@ -311,21 +282,27 @@ endfunction
|
||||
|
||||
" TODO(arslan): I couldn't parameterize the highlight types. Check if we can
|
||||
" simplify the following functions
|
||||
|
||||
"
|
||||
" NOTE(arslan): echon doesn't work well with redraw, thus echo doesn't print
|
||||
" even though we order it. However echom seems to be work fine.
|
||||
function! go#util#EchoSuccess(msg)
|
||||
redraw | echon "vim-go: " | echohl Function | echon a:msg | echohl None
|
||||
redraw | echohl Function | echom "vim-go: " . a:msg | echohl None
|
||||
endfunction
|
||||
|
||||
function! go#util#EchoError(msg)
|
||||
redraw | echon "vim-go: " | echohl ErrorMsg | echon a:msg | echohl None
|
||||
redraw | echohl ErrorMsg | echom "vim-go: " . a:msg | echohl None
|
||||
endfunction
|
||||
|
||||
function! go#util#EchoWarning(msg)
|
||||
redraw | echon "vim-go: " | echohl WarningMsg | echon a:msg | echohl None
|
||||
redraw | echohl WarningMsg | echom "vim-go: " . a:msg | echohl None
|
||||
endfunction
|
||||
|
||||
function! go#util#EchoProgress(msg)
|
||||
redraw | echon "vim-go: " | echohl Identifier | echon a:msg | echohl None
|
||||
redraw | echohl Identifier | echom "vim-go: " . a:msg | echohl None
|
||||
endfunction
|
||||
|
||||
function! go#util#EchoInfo(msg)
|
||||
redraw | echohl Debug | echom "vim-go: " . a:msg | echohl None
|
||||
endfunction
|
||||
|
||||
" vim: sw=2 ts=2 et
|
||||
|
Reference in New Issue
Block a user