let s:is_vim = !has('nvim') let s:channel_map = {} let s:is_win = has('win32') || has('win64') " start terminal, return [bufnr, pid] function! coc#terminal#start(cmd, cwd, env) abort if s:is_vim && !has('terminal') throw 'terminal feature not supported by current vim.' endif let cwd = empty(a:cwd) ? getcwd() : a:cwd execute 'belowright 8new +setl\ buftype=nofile' setl winfixheight setl norelativenumber setl nonumber setl bufhidden=hide if exists('#User#CocTerminalOpen') exe 'doautocmd User CocTerminalOpen' endif let bufnr = bufnr('%') let env = {} let original = {} if !empty(a:env) " use env option when possible if s:is_vim let env = copy(a:env) elseif exists('*setenv') for key in keys(a:env) let original[key] = getenv(key) call setenv(key, a:env[key]) endfor endif endif function! s:OnExit(status) closure if a:status == 0 execute 'silent! bd! '.bufnr endif endfunction if has('nvim') let job_id = termopen(a:cmd, { \ 'cwd': cwd, \ 'pty': 1, \ 'on_exit': {job, status -> s:OnExit(status)}, \ 'env': env, \ }) if !empty(original) && exists('*setenv') for key in keys(original) call setenv(key, original[key]) endfor endif if job_id == 0 throw 'create terminal job failed' endif wincmd p let s:channel_map[bufnr] = job_id return [bufnr, jobpid(job_id)] else let cmd = s:is_win ? join(a:cmd, ' ') : a:cmd let res = term_start(cmd, { \ 'cwd': cwd, \ 'term_kill': s:is_win ? 'kill' : 'term', \ 'term_finish': 'close', \ 'exit_cb': {job, status -> s:OnExit(status)}, \ 'curwin': 1, \ 'env': env, \}) if res == 0 throw 'create terminal job failed' endif let job = term_getjob(bufnr) let s:channel_map[bufnr] = job_getchannel(job) wincmd p return [bufnr, job_info(job).process] endif endfunction function! coc#terminal#send(bufnr, text, add_new_line) abort let chan = get(s:channel_map, a:bufnr, v:null) if empty(chan) | return| endif if has('nvim') let lines = split(a:text, '\v\r?\n') if a:add_new_line && !empty(lines[len(lines) - 1]) if s:is_win call add(lines, "\r\n") else call add(lines, '') endif endif call chansend(chan, lines) let winnr = bufwinnr(a:bufnr) if winnr != -1 exe 'noa '.winnr.'wincmd w' exe 'noa normal! G' exe 'noa '.wincmd p endif else if !a:add_new_line call ch_sendraw(chan, a:text) else call ch_sendraw(chan, a:text.(s:is_win ? "\r\n" : "\n")) endif endif endfunction function! coc#terminal#close(bufnr) abort if has('nvim') let job_id = get(s:channel_map, a:bufnr, 0) if !empty(job_id) silent! call chanclose(job_id) endif endif exe 'silent! bd! '.a:bufnr endfunction