I am trying to implement toggling of the Vim terminal like VS Code by doing <C-~>. But am not sure how to go about it. I find executing :term to open and to close tedious. I figured having a conditional mapping that checks if the terminal is already open, then deciding to open or close the terminal based on that information.
3 Answers
Since Vim doesn't actually recognize the <C-~>
key sequence, you will have to choose another sequence. For example, if you wanted it to be <M-~>
you could do:
nnoremap <M-~> :terminal<CR>
vnoremap <M-~> <ESC>:terminal<CR>
inoremap <M-~> <ESC>:terminal<CR>
This, unfortunately, will only open a terminal, not "toggle" the terminal. To do that it gets more complicated:
nnoremap <M-~> :call TermToggle()<CR>
vnoremap <M-~> <ESC>:call TermToggle()<CR>
inoremap <M-~> <ESC>:call TermToggle()<CR>
tnoremap <M-~> exit<CR>
function! TermToggle()
if term_list() == []
terminal
else
for term in term_list()
call term_sendkeys(term, "exit\<cr>")
endfor
endif
endfunction
Even that isn't perfect, because if you have an application running in the terminal or you have typed any characters on the command line and left them, it will not properly exit since it just "feeds" the command exit
to the terminal.
This is highly dependent on the specific terminal emulator you're using to run vim.
If your terminal supports modifyOtherKeys
mode (xterm, gnome-terminal), then this will work.
Otherwise, it is difficult. Some terminals allow overriding arbitrary key codes, for instance you could map to some unused key, e.g., setting it to <esc>OM
in the terminal and then,
nnoremap <f26> :<c-u>terminal<cr>
-
I've tried to get Vim to recognize the
<C-~>
key sequence in multiple terminals (that do support modifyOtherKeys) and in gVim, and was unsuccessful in all of them. Maybe I'm missing something?– HeptiteJan 24, 2022 at 5:29
Assuming you don't want to exit
but instead just close the terminal window, you could try something like
function ToggleTerm() abort
const terms = term_list()
if empty(terms)
" no terminals, make one
botright terminal
else
const term = terms[0]
if bufwinnr(term) < 0
" terminal hidden, open it
execute 'botright sbuffer' term
else
" terminal open, close all windows showing it in the tab
for win_id in win_findbuf(term)
let win_nr = win_id2win(win_id)
if win_nr > 0
execute win_nr 'close'
endif
endfor
endif
endif
endfunction
Map a key to this as described elsewhere. It will open a terminal on the bottom if none exists; otherwise, if a terminal is open, it will close all windows in the current tab page that are showing the first open terminal. If a terminal exists but is hidden by close
, it will open that.