The context

I have mapped <c-p> in terminal mode so that it deletes the terminal buffer where the cursor is. The way I've created this mapping is presented below

tnoremap <c-p> <c-w>:bd!<CR>

This mapping works when opening a terminal (by executing :term) or when executing :term {command} and when the {command} is still being executed.

If the job is finished, pressing <c-p> does not execute the mapped command.

Because of this, I had to find a way to create that same effect taking into consideration that mappings created with the :tmap command don't work when the job on a terminal buffer is finished.

I first thought in this command (see below), but I don't want <c-p> to be mapped in normal mode (this is explained by the fact that my main goal was to only create it for terminal buffers through the tmap command. Otherwise I wouldn't have post this question.)

nnoremap <c-p> <c-w>:bd!<CR>

Since I dont wan't this mapping to be created for all buffers, I tried to accomplish that with this command (whose idea was retrieved from this question).

au BufWinEnter * if &buftype == 'terminal' | nnoremap <buffer> <c-p> <c-w>:bd!<CR> | endif

However, pressing <c-p> didn't result in anything. I tried to troubleshot this and found out that the BufWinEnter is not the appropiate autocommand event, since it seems that when the :term {command} is executed, that autocmd is triggered but at that time the &buftype variable is not yet set.

The question

How can I map <c-p> so that it executes <c-w>:bd!<cr> on those buffers that were opened with the :term {command} and whose job is already finished, without making <c-p> to be always mapped?

Note that this would be accomplished if we were to find an appropiate autocommand event which is triggered when the &buftype variable is already set because thus this mapping would work and wouldn't make <c-p> to be always mapped to that command.

au BufWinEnter * if &buftype == 'terminal' | nnoremap <buffer> <c-p> <c-w>:bd!<CR> | endif

Additional information

The following minimal vimrc might help you to troubleshot this problem

set nocompatible

fun! P()
    echom '&buftype is: "' . &buftype . '"'

" Execute `:term ls` and you will see that the echoed message prints an empty
" `&buftype`.
autocmd BufWinEnter * call P()

" Try pressing this on a terminal whose job is finished (open one " with `:term
" ls`). You will notice that it doesn't execute the mapped command.
tnoremap <c-p> <c-w>:bd!<cr>

You could try

autocmd TerminalOpen * nnoremap <buffer> <c-p> :bdelete!<CR>

Note that I've used <buffer> to keep it local to the terminal; also, in normal mode, you don't need <C-w> before :.

| improve this answer | |
  • Thanks, it works! Although i scrolled through all the autocommands events, I didn't catch that one. – gfe May 27 at 19:37
  • 2
    @R.Morales I got lucky :) I did /term – D. Ben Knoble May 27 at 19:51
  • 1
    For this to work you need to have at least version 8.1 since the TerminalOpen event is not present in version 8.0. – gfe Jun 7 at 7:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.