if has('nvim') && !exists("g:go_term_mode") let g:go_term_mode = 'vsplit' endif " new creates a new terminal with the given command. Mode is set based on the " global variable g:go_term_mode, which is by default set to :vsplit function! go#term#new(bang, cmd) abort return go#term#newmode(a:bang, a:cmd, g:go_term_mode) endfunction " new creates a new terminal with the given command and window mode. function! go#term#newmode(bang, cmd, mode) abort let mode = a:mode if empty(mode) let mode = g:go_term_mode endif let state = { \ 'cmd': a:cmd, \ 'bang' : a:bang, \ 'winnr': winnr(), \ 'stdout': [], \ 'stderr': [] \ } " 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 " explicitly bind callbacks to state so that within them, self will always " refer to state. See :help Partial for more information. let job = { \ 'on_stdout': function('s:on_stdout', [], state), \ 'on_stderr': function('s:on_stderr', [], state), \ 'on_exit' : function('s:on_exit', [], state), \ } let state.id = termopen(a:cmd, job) let state.termwinnr = winnr() execute cd . fnameescape(dir) startinsert " resize new term if needed. let height = get(g:, 'go_term_height', winheight(0)) let width = get(g:, 'go_term_width', winwidth(0)) " Adjust the window width or height depending on whether it's a vertical or " horizontal split. if mode =~ "vertical" || mode =~ "vsplit" || mode =~ "vnew" exe 'vertical resize ' . width elseif mode =~ "split" || mode =~ "new" exe 'resize ' . height endif " we also need to resize the pty, so there you go... call jobresize(state.id, width, height) stopinsert if state.winnr !=# winnr() exe state.winnr . "wincmd w" endif return state.id endfunction function! s:on_stdout(job_id, data, event) dict abort call extend(self.stdout, a:data) endfunction function! s:on_stderr(job_id, data, event) dict abort call extend(self.stderr, a:data) endfunction function! s:on_exit(job_id, exit_status, event) dict abort let l:listtype = go#list#Type("_term") " usually there is always output so never branch into this clause if empty(self.stdout) call s:cleanlist(self.winnr, l:listtype) return endif let errors = go#tool#ParseErrors(self.stdout) let errors = go#tool#FilterValids(errors) if !empty(errors) " close terminal; we don't need it anymore execute self.termwinnr . "close" if self.winnr !=# winnr() execute self.winnr . "wincmd w" endif call go#list#Populate(l:listtype, errors, self.cmd) call go#list#Window(l:listtype, len(errors)) if !self.bang call go#list#JumpToFirst(l:listtype) endif return endif call s:cleanlist(self.winnr, l:listtype) endfunction function s:cleanlist(winnr, listtype) abort " There are no errors. Clean and close the list. Jump to the window to which " the location list is attached, close the list, and then jump back to the " current window. let l:winnr = winnr() execute a:winnr . "wincmd w" call go#list#Clean(a:listtype) execute l:winnr . "wincmd w" endfunction " vim: sw=2 ts=2 et