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

Updated plugins

This commit is contained in:
amix
2015-12-16 10:53:53 -03:00
parent 26861f69b1
commit 6b48dc598f
19 changed files with 576 additions and 95 deletions

View File

@ -14,24 +14,30 @@ endfunction
" 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, ...)
let default_makeprg = &makeprg
" 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)
" create our command arguments. go build discards any results when it
" compiles multiple packages. So we pass the `errors` package just as an
" 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')
call go#jobcontrol#Spawn("build", args)
return
endif
let old_gopath = $GOPATH
let $GOPATH = go#path#Detect()
let default_makeprg = &makeprg
let &makeprg = "go " . join(args, ' ')
let l:tmpname = tempname()
if v:shell_error
let &makeprg = "go build . errors"
else
" :make expands '%' and '#' wildcards, so they must also be escaped
let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
let gofiles = go#util#Shelljoin(go#tool#Files(), 1)
let &makeprg = "go build -o " . l:tmpname . ' ' . goargs . ' ' . gofiles
endif
echon "vim-go: " | echohl Identifier | echon "building ..."| echohl None
if g:go_dispatch_enabled && exists(':Make') == 2
call go#util#EchoProgress("building dispatched ...")
silent! exe 'Make'
else
silent! exe 'lmake!'
@ -42,25 +48,35 @@ function! go#cmd#Build(bang, ...)
let errors = go#list#Get()
call go#list#Window(len(errors))
if !empty(errors)
if !empty(errors)
if !a:bang
call go#list#JumpToFirst()
endif
else
redraws! | echon "vim-go: " | echohl Function | echon "[build] SUCCESS"| echohl None
call go#util#EchoSuccess("[build] SUCCESS")
endif
call delete(l:tmpname)
let &makeprg = default_makeprg
let $GOPATH = old_gopath
endfunction
" Run runs the current file (and their dependencies if any) in a new terminal.
function! go#cmd#RunTerm(mode)
let cmd = "go run ". go#util#Shelljoin(go#tool#Files())
call go#term#newmode(cmd, a:mode)
endfunction
" Run runs the current file (and their dependencies if any) and outputs it.
" 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, ...)
if has('nvim')
call go#cmd#RunTerm('')
return
endif
let old_gopath = $GOPATH
let $GOPATH = go#path#Detect()
@ -90,27 +106,8 @@ function! go#cmd#Run(bang, ...)
exe 'lmake!'
endif
" Remove any nonvalid filename from the location list to avoid opening an
" empty buffer. See https://github.com/fatih/vim-go/issues/287 for
" details.
let items = go#list#Get()
let errors = []
let is_readable = {}
for item in items
let filename = bufname(item.bufnr)
if !has_key(is_readable, filename)
let is_readable[filename] = filereadable(filename)
endif
if is_readable[filename]
call add(errors, item)
endif
endfor
for k in keys(filter(is_readable, '!v:val'))
echo "vim-go: " | echohl Identifier | echon "[run] Dropped " | echohl Constant | echon '"' . k . '"'
echohl Identifier | echon " from location list (nonvalid filename)" | echohl None
endfor
let errors = go#tool#FilterValids(items)
call go#list#Populate(errors)
call go#list#Window(len(errors))
@ -149,33 +146,51 @@ endfunction
" 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, ...)
let command = "go test "
let args = ["test"]
" don't run the test, only compile it. Useful to capture and fix errors or
" to create a test binary.
if a:compile
let command .= "-c "
call add(args, "-c")
endif
if a:0
let command .= go#util#Shelljoin(map(copy(a:000), "expand(v:val)"))
" 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))
else
" only add this if no custom flags are passed
let timeout = get(g:, 'go_test_timeout', '10s')
let command .= "-timeout=" . timeout . " "
call add(args, printf("-timeout=%s", timeout))
endif
if has('nvim')
if get(g:, 'go_term_enabled', 0)
call go#term#new(["go"] + args)
else
call go#jobcontrol#Spawn("test", args)
endif
return
endif
call go#cmd#autowrite()
if a:compile
echon "vim-go: " | echohl Identifier | echon "compiling tests ..." | echohl None
else
echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None
endif
call go#cmd#autowrite()
redraw
let command = "go " . join(args, ' ')
let out = go#tool#ExecuteInDir(command)
if v:shell_error
let errors = go#tool#ParseErrors(split(out, '\n'))
let errors = go#tool#FilterValids(errors)
call go#list#Populate(errors)
call go#list#Window(len(errors))
if !empty(errors) && !a:bang

View File

@ -43,6 +43,8 @@ if !exists("g:go_fmt_experimental")
let g:go_fmt_experimental = 0
endif
let s:got_fmt_error = 0
" we have those problems :
" http://stackoverflow.com/questions/12741977/prevent-vim-from-updating-its-undo-tree
" http://stackoverflow.com/questions/18532692/golang-formatter-and-vim-how-to-destroy-history-record?rq=1
@ -117,9 +119,12 @@ function! go#fmt#Format(withGoimport)
let &fileformat = old_fileformat
let &syntax = &syntax
" clean up previous location list
call go#list#Clean()
call go#list#Window()
" clean up previous location list, but only if it's due fmt
if s:got_fmt_error
let s:got_fmt_error = 0
call go#list#Clean()
call go#list#Window()
endif
elseif g:go_fmt_fail_silently == 0
let splitted = split(out, '\n')
"otherwise get the errors and put them to location list
@ -141,6 +146,7 @@ function! go#fmt#Format(withGoimport)
echohl Error | echomsg "Gofmt returned error" | echohl None
endif
let s:got_fmt_error = 1
call go#list#Window(len(errors))
" We didn't use the temp file, so clean up

View File

@ -0,0 +1,168 @@
" s:jobs is a global reference to all jobs started with Spawn() or with the
" internal function s:spawn
let s:jobs = {}
" 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(desc, args)
" autowrite is not enabled for jobs
call go#cmd#autowrite()
let job = s:spawn(a:desc, a: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
" 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
" current files folder.
function! s:spawn(desc, args)
let job = {
\ 'desc': a:desc,
\ 'winnr': winnr(),
\ 'importpath': go#package#ImportPath(expand('%:p:h')),
\ 'state': "RUNNING",
\ 'stderr' : [],
\ 'stdout' : [],
\ 'on_stdout': function('s:on_stdout'),
\ 'on_stderr': function('s:on_stderr'),
\ 'on_exit' : function('s:on_exit'),
\ }
" modify GOPATH if needed
let old_gopath = $GOPATH
let $GOPATH = go#path#Detect()
" execute go build in the files directory
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
" cleanup previous jobs for this file
for jb in values(s:jobs)
if jb.importpath == job.importpath
unlet s:jobs[jb.id]
endif
endfor
let dir = getcwd()
execute cd . fnameescape(expand("%:p:h"))
" append the subcommand, such as 'build'
let argv = ['go'] + a:args
" run, forrest, run!
let id = jobstart(argv, job)
let job.id = id
let s:jobs[id] = job
execute cd . fnameescape(dir)
" restore back GOPATH
let $GOPATH = old_gopath
return job
endfunction
" on_exit is the exit handler for jobstart(). It handles cleaning up the job
" 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, data)
let std_combined = self.stderr + self.stdout
if empty(std_combined)
call go#list#Clean()
call go#list#Window()
let self.state = "SUCCESS"
return
endif
let errors = go#tool#ParseErrors(std_combined)
let errors = go#tool#FilterValids(errors)
if !len(errors)
" no errors could be past, just return
call go#list#Clean()
call go#list#Window()
let self.state = "SUCCESS"
return
endif
let self.state = "FAILED"
" if we are still in the same windows show the list
if self.winnr == winnr()
call go#list#Populate(errors)
call go#list#Window(len(errors))
call go#list#JumpToFirst()
endif
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)
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)
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:ts=2:sw=2:et

View File

@ -36,6 +36,10 @@ function! go#list#Populate(items)
call setloclist(0, a:items, 'r')
endfunction
function! go#list#PopulateWin(winnr, items)
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(errformat, items)

View File

@ -0,0 +1,124 @@
if has('nvim') && !exists("g:go_term_mode")
let g:go_term_mode = 'vsplit'
endif
" s:jobs is a global reference to all jobs started with new()
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(cmd)
call go#term#newmode(a:cmd, g:go_term_mode)
endfunction
" new creates a new terminal with the given command and window mode.
function! go#term#newmode(cmd, mode)
let mode = a:mode
if empty(mode)
let mode = g:go_term_mode
endif
" modify GOPATH if needed
let old_gopath = $GOPATH
let $GOPATH = go#path#Detect()
" execute go build in the files directory
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let dir = getcwd()
execute cd . fnameescape(expand("%:p:h"))
execute mode.' __go_term__'
setlocal filetype=goterm
setlocal bufhidden=delete
setlocal winfixheight
setlocal noswapfile
setlocal nobuflisted
let job = {
\ 'stderr' : [],
\ 'stdout' : [],
\ 'on_stdout': function('s:on_stdout'),
\ 'on_stderr': function('s:on_stderr'),
\ 'on_exit' : function('s:on_exit'),
\ }
let id = termopen(a:cmd, job)
execute cd . fnameescape(dir)
" restore back GOPATH
let $GOPATH = old_gopath
let job.id = id
startinsert
" resize new term if needed.
let height = get(g:, 'go_term_height', winheight(0))
let width = get(g:, 'go_term_width', winwidth(0))
" we are careful how to resize. for example it's vertical we don't change
" the height. The below command resizes the buffer
if a:mode == "split"
exe 'resize ' . height
elseif a:mode == "vertical"
exe 'vertical resize ' . width
endif
" we also need to resize the pty, so there you go...
call jobresize(id, width, height)
let s:jobs[id] = job
return id
endfunction
function! s:on_stdout(job_id, data)
if !has_key(s:jobs, a:job_id)
return
endif
let job = s:jobs[a:job_id]
call extend(job.stdout, a:data)
endfunction
function! s:on_stderr(job_id, data)
if !has_key(s:jobs, a:job_id)
return
endif
let job = s:jobs[a:job_id]
call extend(job.stderr, a:data)
endfunction
function! s:on_exit(job_id, data)
if !has_key(s:jobs, a:job_id)
return
endif
let job = s:jobs[a:job_id]
" usually there is always output so never branch into this clause
if empty(job.stdout)
call go#list#Clean()
call go#list#Window()
else
let errors = go#tool#ParseErrors(job.stdout)
let errors = go#tool#FilterValids(errors)
if !empty(errors)
" close terminal we don't need it
close
call go#list#Populate(errors)
call go#list#Window(len(errors))
call go#list#JumpToFirst()
else
call go#list#Clean()
call go#list#Window()
endif
endif
unlet s:jobs[a:job_id]
endfunction
" vim:ts=4:sw=4:et

View File

@ -50,9 +50,14 @@ function! go#tool#ParseErrors(lines)
if !empty(fatalerrors)
call add(errors, {"text": fatalerrors[1]})
elseif !empty(tokens)
call add(errors, {"filename" : fnamemodify(tokens[1], ':p'),
\"lnum": tokens[2],
\"text": tokens[3]})
" strip endlines of form ^M
let out=substitute(tokens[3], '\r$', '', '')
call add(errors, {
\ "filename" : fnamemodify(tokens[1], ':p'),
\ "lnum" : tokens[2],
\ "text" : out,
\ })
elseif !empty(errors)
" Preserve indented lines.
" This comes up especially with multi-line test output.
@ -65,6 +70,42 @@ function! go#tool#ParseErrors(lines)
return errors
endfunction
"FilterValids filters the given items with only items that have a valid
"filename. Any non valid filename is filtered out.
function! go#tool#FilterValids(items)
" Remove any nonvalid filename from the location list to avoid opening an
" empty buffer. See https://github.com/fatih/vim-go/issues/287 for
" details.
let filtered = []
let is_readable = {}
for item in a:items
if has_key(item, 'bufnr')
let filename = bufname(item.bufnr)
elseif has_key(item, 'filename')
let filename = item.filename
else
" nothing to do, add item back to the list
call add(filtered, item)
continue
endif
if !has_key(is_readable, filename)
let is_readable[filename] = filereadable(filename)
endif
if is_readable[filename]
call add(filtered, item)
endif
endfor
for k in keys(filter(is_readable, '!v:val'))
echo "vim-go: " | echohl Identifier | echon "[run] Dropped " | echohl Constant | echon '"' . k . '"'
echohl Identifier | echon " from location list (nonvalid filename)" | echohl None
endfor
return filtered
endfunction
function! go#tool#ExecuteInDir(cmd) abort
let old_gopath = $GOPATH
let $GOPATH = go#path#Detect()

View File

@ -53,7 +53,37 @@ endfunction
function! go#util#Shelljoin(arglist, ...)
if a:0
return join(map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')'), ' ')
else
return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ')
endif
return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ')
endfunction
" Shelljoin 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
return map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')')
endif
return map(copy(a:arglist), 'shellescape(v:val)')
endfunction
" TODO(arslan): I couldn't parameterize the highlight types. Check if we can
" simplify the following functions
function! go#util#EchoSuccess(msg)
redraws! | echon "vim-go: " | echohl Function | echon a:msg | echohl None
endfunction
function! go#util#EchoError(msg)
redraws! | echon "vim-go: " | echohl ErrorMsg | echon a:msg | echohl None
endfunction
function! go#util#EchoWarning(msg)
redraws! | echon "vim-go: " | echohl WarningMsg | echon a:msg | echohl None
endfunction
function! go#util#EchoProgress(msg)
redraws! | echon "vim-go: " | echohl Identifier | echon a:msg | echohl None
endfunction
" vim:ts=4:sw=4:et