123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- 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
|