From bb5c2ceab185bcf4e37b72c0052ace77d5bc1cc9 Mon Sep 17 00:00:00 2001 From: Yukinari Toyota Date: Sun, 17 Jan 2016 00:42:46 +0900 Subject: [PATCH] cmd: fix GoTestFunc is not working cmd: show testing and test pass message in GoTest on neovim jobcontrol: add AddHandler and RemoveHandler API to catch on_exit callback for callers of caller cmd: add neovim integration for GoCoverage --- autoload/go/cmd.vim | 88 +++++++++++++++++++++++++++----------- autoload/go/jobcontrol.vim | 35 +++++++++++++++ autoload/go/term.vim | 2 +- autoload/go/util.vim | 2 +- 4 files changed, 99 insertions(+), 28 deletions(-) diff --git a/autoload/go/cmd.vim b/autoload/go/cmd.vim index f227093f42..68f753d830 100644 --- a/autoload/go/cmd.vim +++ b/autoload/go/cmd.vim @@ -150,6 +150,26 @@ function! go#cmd#Install(bang, ...) echon "vim-go: " | echohl Function | echon "installed to ". $GOPATH | echohl None endfunction +let s:test_handler_id = '' +let s:test_handler_jobs = {} + +function! s:test_handler(job, exit_status, data) + if !has_key(s:test_handler_jobs, a:job.id) + return + endif + let l:compile = s:test_handler_jobs[a:job.id] + if a:exit_status == 0 + if l:compile + echon "vim-go: " | echohl Function | echon "[test] SUCCESS" | echohl None + else + echon "vim-go: " | echohl Function | echon "[test] PASS" | echohl None + endif + else + echon "vim-go: " | echohl ErrorMsg | echon "[test] FAIL" | echohl None + endif + unlet s:test_handler_jobs[a:job.id] +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 @@ -166,29 +186,32 @@ function! go#cmd#Test(bang, compile, ...) " 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 test - call extend(args, go#util#Shelllist(goargs, 1)) + call extend(args, goargs) else " only add this if no custom flags are passed let timeout = get(g:, 'go_test_timeout', '10s') call add(args, printf("-timeout=%s", timeout)) endif - if has('nvim') - if get(g:, 'go_term_enabled', 0) - call go#term#new(a:bang, ["go"] + args) - else - call go#jobcontrol#Spawn(a:bang, "test", args) - endif - return - endif - if a:compile echon "vim-go: " | echohl Identifier | echon "compiling tests ..." | echohl None else echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None endif + if has('nvim') + if get(g:, 'go_term_enabled', 0) + let id = go#term#new(a:bang, ["go"] + args) + else + let id = go#jobcontrol#Spawn(a:bang, "test", args) + endif + if s:test_handler_id == '' + let s:test_handler_id = go#jobcontrol#AddHandler(function('s:test_handler')) + endif + let s:test_handler_jobs[id] = a:compile + return id + endif + call go#cmd#autowrite() redraw @@ -257,27 +280,40 @@ function! go#cmd#TestFunc(bang, ...) call call('go#cmd#Test', args) endfunction +let s:coverage_handler_id = '' +let s:coverage_handler_jobs = {} + +function! s:coverage_handler(job, exit_status, data) + if !has_key(s:coverage_handler_jobs, a:job.id) + return + endif + let l:tmpname = s:coverage_handler_jobs[a:job.id] + if a:exit_status == 0 + let openHTML = 'go tool cover -html='.l:tmpname + call go#tool#ExecuteInDir(openHTML) + endif + call delete(l:tmpname) + unlet s:coverage_handler_jobs[a:job.id] +endfunction + " Coverage creates a new cover profile with 'go test -coverprofile' and opens " a new HTML coverage page from that profile. function! go#cmd#Coverage(bang, ...) let l:tmpname=tempname() + let args = [a:bang, 0, "-coverprofile", l:tmpname] - let command = "go test -coverprofile=" . l:tmpname . ' ' . go#util#Shelljoin(a:000) - - call go#cmd#autowrite() - let out = go#tool#ExecuteInDir(command) - if v:shell_error - let errors = go#tool#ParseErrors(split(out, '\n')) - call go#list#Populate(errors) - call go#list#Window(len(errors)) - if !empty(errors) && !a:bang - call go#list#JumpToFirst() + if a:0 + call extend(args, a:000) + endif + let id = call('go#cmd#Test', args) + if has('nvim') + if s:coverage_handler_id == '' + let s:coverage_handler_id = go#jobcontrol#AddHandler(function('s:coverage_handler')) endif - else - " clear previous location list - call go#list#Clean() - call go#list#Window() - + let s:coverage_handler_jobs[id] = l:tmpname + return + endif + if !v:shell_error let openHTML = 'go tool cover -html='.l:tmpname call go#tool#ExecuteInDir(openHTML) endif diff --git a/autoload/go/jobcontrol.vim b/autoload/go/jobcontrol.vim index 3dedd5c8f5..d040674ed5 100644 --- a/autoload/go/jobcontrol.vim +++ b/autoload/go/jobcontrol.vim @@ -2,6 +2,10 @@ " internal function s:spawn let s:jobs = {} +" s:handlers is a global event handlers for all jobs started with Spawn() or +" with the internal function s:spawn +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). @@ -36,6 +40,22 @@ function! go#jobcontrol#Statusline() abort return '' endfunction +" AddHandler adds a on_exit callback handler and returns the id. +function! go#jobcontrol#AddHandler(handler) + let i = len(s:handlers) + while has_key(s:handlers, string(i)) + let i += 1 + break + endwhile + let s:handlers[string(i)] = a:handler + return string(i) +endfunction + +" RemoveHandler removes a callback handler by id. +function! go#jobcontrol#RemoveHandler(id) + unlet s:handlers[a:id] +endfunction + " spawn spawns a go subcommand with the name and arguments with jobstart. Once " 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 @@ -100,6 +120,8 @@ function! s:on_exit(job_id, exit_status) call go#list#Window() let self.state = "SUCCESS" + + call s:callback_handlers_on_exit(s:jobs[a:job_id], a:exit_status, std_combined) return endif @@ -118,6 +140,7 @@ function! s:on_exit(job_id, exit_status) if !len(errors) " failed to parse errors, output the original content call go#util#EchoError(std_combined[0]) + call s:callback_handlers_on_exit(s:jobs[a:job_id], a:exit_status, std_combined) return endif @@ -129,6 +152,18 @@ function! s:on_exit(job_id, exit_status) call go#list#JumpToFirst() endif endif + call s:callback_handlers_on_exit(s:jobs[a:job_id], a:exit_status, std_combined) +endfunction + +" callback_handlers_on_exit runs all handlers for job on exit event. +function! s:callback_handlers_on_exit(job, exit_status, data) + if empty(s:handlers) + return + endif + + for s:handler in values(s:handlers) + call s:handler(a:job, a:exit_status, a:data) + endfor endfunction " on_stdout is the stdout handler for jobstart(). It collects the output of diff --git a/autoload/go/term.vim b/autoload/go/term.vim index eaca0f5cb0..2b0d70999b 100644 --- a/autoload/go/term.vim +++ b/autoload/go/term.vim @@ -8,7 +8,7 @@ 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) - call go#term#newmode(a:bang, a:cmd, g:go_term_mode) + 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. diff --git a/autoload/go/util.vim b/autoload/go/util.vim index 85ab9331a7..29b27330b5 100644 --- a/autoload/go/util.vim +++ b/autoload/go/util.vim @@ -58,7 +58,7 @@ function! go#util#Shelljoin(arglist, ...) return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ') endfunction -" Shelljoin returns a shell-safe representation of the items in the given +" 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, ...) if a:0