-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from GoldsteinE/master
Multiple terminals
- Loading branch information
Showing
4 changed files
with
254 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,190 @@ | ||
" Vimteractive implementation | ||
" | ||
" Variables | ||
" s:vimteractive_buffers | ||
" script-local variable that keeps track of vimteractive terminal buffers | ||
" | ||
" b:vimteractive_connected_term | ||
" buffer-local variable held by buffer that indicates the name of the | ||
" connected terminal buffer | ||
" | ||
" b:vimteractive_term_type | ||
" buffer-local variable held by terminal buffer that indicates the terminal type | ||
|
||
|
||
" Initialise the list of terminal buffer numbers on startup | ||
if !exists('s:vimteractive_buffers') | ||
let s:vimteractive_buffers = [] | ||
end | ||
|
||
" Remove a terminal from the list on deletion. | ||
function! s:del_term() | ||
let l:term_bufname = expand('<afile>') | ||
let l:term_bufnr = bufnr(term_bufname) | ||
let l:term_index = index(s:vimteractive_buffers, l:term_bufnr) | ||
if l:term_index >= 0 | ||
call remove(s:vimteractive_buffers, l:term_index) | ||
endif | ||
endfunction | ||
|
||
|
||
" Reopen a terminal buffer in a split window if necessary | ||
function! s:show_term() | ||
let l:open_bufnrs = map(range(1, winnr('$')), 'winbufnr(v:val)') | ||
if index(l:open_bufnrs, bufnr(b:vimteractive_connected_term)) == -1 | ||
split | ||
execute ":b " . b:vimteractive_connected_term | ||
wincmd p | ||
endif | ||
endfunction | ||
|
||
|
||
" Generate a new terminal name | ||
function! s:new_name(term_type) | ||
" Create a new terminal name | ||
let l:term_bufname = "term_" . a:term_type | ||
let i = 1 | ||
while bufnr(l:term_bufname) != -1 | ||
let l:term_bufname = "term_" . a:term_type . '_' . i | ||
let i += 1 | ||
endwhile | ||
return l:term_bufname | ||
endfunction | ||
|
||
|
||
" Listen for Buffer close events if they're in the terminal list | ||
autocmd BufDelete * call <SID>del_term() | ||
|
||
|
||
" List all running terminal names | ||
function! vimteractive#buffer_list(...) | ||
let l:vimteractive_buffers = copy(s:vimteractive_buffers) | ||
return map(l:vimteractive_buffers, 'bufname(v:val)') | ||
endfunction | ||
|
||
|
||
" Send list of lines to the terminal buffer, surrounded with a bracketed paste | ||
function! vimteractive#sendlines(lines) | ||
if get(g:vimteractive_bracketed_paste, g:current_term_type, 1) | ||
call term_sendkeys(g:vimteractive_buffer_name,"[200~" . join(a:lines, "\n") . "[201~\n") | ||
" Autostart a terminal if desired | ||
if !exists("b:vimteractive_connected_term") | ||
if g:vimteractive_autostart | ||
call vimteractive#term_start('-auto-') | ||
else | ||
echoerr "No terminal connected." | ||
echoerr "call :Iterm to start a new one, or :Iconn to connect to an existing one" | ||
return | ||
endif | ||
endif | ||
|
||
" Check if connected terminal is still alive | ||
if index(s:vimteractive_buffers, b:vimteractive_connected_term) == -1 | ||
echoerr "Vimteractive terminal " . b:vimteractive_connected_term . " has been deleted" | ||
echoerr "call :Iterm to start a new one, or :Iconn to connect to an existing one" | ||
return | ||
endif | ||
|
||
call s:show_term() | ||
|
||
let l:term_type = getbufvar(b:vimteractive_connected_term, "term_type") | ||
|
||
mark` | ||
if get(g:vimteractive_bracketed_paste, l:term_type, 1) | ||
call term_sendkeys(b:vimteractive_connected_term,"[200~" . join(a:lines, "\n") . "[201~\n") | ||
else | ||
call term_sendkeys(g:vimteractive_buffer_name, join(a:lines, "\n") . "\n") | ||
call term_sendkeys(b:vimteractive_connected_term, join(a:lines, "\n") . "\n") | ||
endif | ||
endfunction | ||
|
||
" Send a line to the terminal buffer | ||
function! vimteractive#sendline(line) | ||
call vimteractive#sendlines([a:line]) | ||
endfunction | ||
|
||
" Start a vimteractive session | ||
function! vimteractive#session(terminal_type) | ||
|
||
" Start a vimteractive terminal | ||
function! vimteractive#term_start(term_type) | ||
if has('terminal') == 0 | ||
echoerr "Your version of vim is not compiled with +terminal. Cannot use vimteractive" | ||
return | ||
endif | ||
|
||
if a:terminal_type ==# '-auto-' | ||
let term_type = get(g:vimteractive_default_shells, &filetype, &filetype) | ||
if has_key(g:vimteractive_commands, term_type) | ||
let l:terminal = get(g:vimteractive_commands, term_type) | ||
let g:current_term_type = term_type | ||
else | ||
echoerr "Cannot determine terminal commmand for filetype " . &filetype | ||
return | ||
endif | ||
" Determine the terminal type | ||
if a:term_type ==# '-auto-' | ||
let l:term_type = get(g:vimteractive_default_shells, &filetype, &filetype) | ||
else | ||
let l:terminal = get(g:vimteractive_commands, a:terminal_type) | ||
let g:current_term_type = a:terminal_type | ||
let l:term_type = a:term_type | ||
endif | ||
|
||
if g:vimteractive_terminal != '' && g:vimteractive_terminal != l:terminal | ||
echoerr "Cannot run: " . l:terminal " Alreading running: " . g:vimteractive_terminal | ||
" Retrieve starting command | ||
if has_key(g:vimteractive_commands, l:term_type) | ||
let l:term_command = get(g:vimteractive_commands, l:term_type) | ||
else | ||
echoerr "Cannot determine terminal commmand for type " . l:term_type | ||
return | ||
endif | ||
|
||
if bufnr(g:vimteractive_buffer_name) == -1 | ||
" If no vimteractive buffer exists: | ||
" Start the terminal | ||
let job = term_start(l:terminal, {"term_name":g:vimteractive_buffer_name}) | ||
set nobuflisted " Unlist the buffer | ||
set norelativenumber " Turn off line numbering if off | ||
set nonumber " Turn off line numbering if off | ||
wincmd p " Return to the previous window | ||
let g:vimteractive_terminal = l:terminal " Name the current terminal | ||
|
||
elseif bufwinnr(g:vimteractive_buffer_name) == -1 | ||
" Else if vimteractive buffer not open: | ||
" Split the window | ||
split | ||
" switch the top window to the vimteractive buffer | ||
execute ":b " . g:vimteractive_buffer_name | ||
" Return to the previous window | ||
wincmd p | ||
" Create a new term | ||
echom "Starting " . l:term_command | ||
let l:term_bufname = s:new_name(l:term_type) | ||
call term_start(l:term_command, { | ||
\ "term_name": l:term_bufname, | ||
\ "term_finish": "close", | ||
\ "term_kill": "term" | ||
\ }) | ||
|
||
else | ||
" Else if throw error | ||
echoerr "vimteractive already open. Quit before opening a new buffer" | ||
" Add this terminal to the buffer list, and store type | ||
call add(s:vimteractive_buffers, bufnr(l:term_bufname)) | ||
let b:vimteractive_term_type = l:term_type | ||
|
||
" Turn line numbering off | ||
set nonumber norelativenumber | ||
" Switch to terminal-normal mode when entering buffer | ||
autocmd BufEnter <buffer> call feedkeys("\<C-W>N") | ||
" Switch to insert mode when leaving buffer | ||
autocmd BufLeave <buffer> execute "silent! normal! i" | ||
" Make :quit really do the right thing | ||
cabbrev <buffer> q bdelete! " | ||
cabbrev <buffer> qu bdelete! " | ||
cabbrev <buffer> qui bdelete! " | ||
cabbrev <buffer> quit bdelete! " | ||
" Return to previous window | ||
wincmd p | ||
|
||
" Store name and type of current buffer | ||
let b:vimteractive_connected_term = bufnr(l:term_bufname) | ||
|
||
" Pause as necessary | ||
while term_getline(b:vimteractive_connected_term, 1) == '' | ||
sleep 10m " Waiting for prompt | ||
endwhile | ||
if get(g:vimteractive_slow_prompt, l:term_type) | ||
execute "sleep " . l:slow . "m" | ||
endif | ||
redraw | ||
|
||
endfunction | ||
|
||
|
||
" Connect to vimteractive terminal | ||
function! vimteractive#connect(bufname = '') | ||
if len(s:vimteractive_buffers) == 0 | ||
echoerr "No vimteractive terminal buffers present" | ||
echoerr "call :Iterm to start a new one" | ||
return | ||
endif | ||
|
||
let l:bufname = a:bufname | ||
if strlen(a:bufname) ==# 0 | ||
if len(s:vimteractive_buffers) ==# 1 | ||
let l:bufname = vimteractive#buffer_list()[0] | ||
else | ||
echom "Please specify terminal from " | ||
echom vimteractive#buffer_list() | ||
return | ||
endif | ||
endif | ||
|
||
if !bufexists(l:bufname) | ||
echoerr "Buffer " . l:bufname . " is not found or already disconnected" | ||
return | ||
endif | ||
|
||
let b:vimteractive_connected_term = bufnr(l:bufname) | ||
echom "Connected " . bufname("%") . " to " . l:bufname | ||
|
||
endfunction |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,7 +37,16 @@ The activating commands are | |
- clojure |:Iclojure| | ||
- zsh |:Izsh| | ||
|
||
You can also let Vimteractive detect interpreter using |:Iterm| | ||
You can also let Vimteractive detect interpreter using |:Iterm| or just send | ||
some lines: Vimteractive will create terminal if needed. Note: it's highly | ||
recommended to use IPython as your default Python interpreter. You can set it | ||
like this: | ||
|
||
let g:vimteractive_default_shells = { 'python': 'ipython' } | ||
|
||
Default Python REPL support for pasting is really bad and you should use | ||
IPython whenever possible. If you need to use default Python REPL, you must | ||
put newline after every top-level block. | ||
|
||
Commands may be sent from a text file to the chosen terminal using CTRL-S. | ||
See |v_CTRL_S| for more details. | ||
|
@@ -87,6 +96,9 @@ enter the terminal, and be able to enter commands interactively into the | |
prompt as if you had run it in the command line. You can save this buffer if | ||
you wish to a new file if it contains valuable output | ||
|
||
By default every buffer is connected to separate terminal. If you want to | ||
connect two buffers to one terminal, use |:Iconn| command. | ||
|
||
|
||
Supported terminals *vimteractive-terminals* | ||
|
||
|
@@ -113,8 +125,17 @@ In |Visual-mode|, CTRL-S sends all currently selected lines to the terminal. | |
|
||
ALT-S sends all lines from the start to the current line. | ||
|
||
If there is no active terminal for current buffer, CTRL-S will automatically | ||
create one for you using |:Iterm|. | ||
|
||
============================================================================== | ||
3. Extending functionality *vimteractive-extending* | ||
3. Connecting to existing REPLs *:Iconn* *vimteractive-connecting* | ||
:Iconn [{buffer}] Connect current buffer to REPL in {buffer}. You can | ||
connect any number of buffers to one REPL. {buffer} | ||
can be omited if there is only one terminal. | ||
|
||
============================================================================== | ||
4. Extending functionality *vimteractive-extending* | ||
|
||
To add a new interpreter to Vimteractive, you should define | ||
g:vimteractive_commands variable. For example: | ||
|
@@ -131,13 +152,19 @@ you may try to disable bracketed paste mode for it: | |
|
||
let g:vimteractive_bracketed_paste = { 'pythonasync': 0 } | ||
|
||
If your interpreter has slow-starting REPL (like Clojure), you may want to | ||
wait before sending data to it at the first time. Specify time to wait in | ||
milliseconds like this: | ||
|
||
let g:vimteractive_slow_prompt = { 'pythonasync': 200 } | ||
|
||
This project is very much in an alpha phase, so if you have any issues that | ||
arise on your system, feel free to contact me: | ||
|
||
[email protected]. | ||
|
||
============================================================================== | ||
4. About *vimteractive-functionality* | ||
5. About *vimteractive-functionality* | ||
|
||
The core maintainer of vimteractive is: | ||
|
||
|
@@ -148,6 +175,6 @@ Find the latest version of vimteractive at: | |
http://github.com/williamjameshandley/vimteractive | ||
|
||
============================================================================== | ||
5. License *vimteractive-license* | ||
6. License *vimteractive-license* | ||
|
||
Vimteractive is licensed under GPL 3.0 |
Oops, something went wrong.