I would like to execute a certain function every time I leave a buffer associated with C++, and another function every time I enter a C++ buffer. I came up with this so far:

" Buffer Leave
augroup myBufferLeave
    autocmd BufLeave *.cpp,*.c,*.h call s:ExecuteLeave()
augroup END

" Buffer Enter
augroup myBufferEnter
    autocmd BufEnter *.cpp,*.c,*.h call s:ExecuteEnter()
augroup END

Another alternative is to hook into the global BufEnter event and set a buffer variable or check the current &ft and execute the appropriate function:

autocmd BufEnter * if &ft = 'cpp' |
    \ call s:ExecuteEnter() |
    \ endif

autocmd BufLeave * if &ft = 'cpp' |
    \ call s:ExecuteLeave() |
    \ endif

Is there a cleaner way to do this? Ideally, without tapping into the * global buffer events. Ideally, I would like to use something like this:

 autocmd BufLeave cpp call s:ExecuteLeave()
 autocmd BufEnter cpp call s:ExecuteEnter()

Is there a way to pack the *.cpp,*.c,*.h condition into one single definition such as cpp? The cpp definition is a FileType, but file-types are not triggered on BufEnter and BufLeave. If one needs to add another file extension, such as *.CXX for example, the list will become bloated eventually *.cpp,*.c,*.h, *.CXX, *.C, and a bit hard to maintain.

  • 1
    Possible X/Y problem. What exactly are you trying to do? Have buffer specific mappings (See :h :map-local), buffer commands (See :h :command-buffer), or buffer local settings (See :h setlocal)? – Peter Rincker Apr 7 '16 at 20:53
  • 1
    I would like to be able to come up with a buffer enter/leave event that is not depending on long file extension lists. Ideally, dealing with the file extensions problem in a 'ftdetect' script, and put ambiguous file extensions such as '*.h, *.C, *.CXX' into a 'cpp' file type, so we keep adding to these in order to include new extensions into the defined file type and on the 'BufEnter' and 'BufLeave' side we just use the FileType tag, such as 'cpp' instead of a long list of constantly growing extensions. – mbilyanov Apr 7 '16 at 21:37
  • 1
    I understand what the kind of autocmd pattern you are trying to craft (Spoiler: your autocmd * if &ft method is the correct way to do this). My question to you is what are your ExecuteEnter()/ExecuteLeave() supposed to be doing? More than likely you are trying to add buffer specific mappings/commands/settings, of which there are better ways methods. – Peter Rincker Apr 7 '16 at 21:46
  • 1
    I would like to set an option, set completeopt-=preview when entering C++ or C buffers and set completeopt+=preview when leaving C++ or C buffers. But nowadays, the C/C++ files may have a very rich variety of extensions, writing down all of these seems too laborious and not very smart. – mbilyanov Apr 7 '16 at 21:55

As the completeopt is a global option, you are correct in that you need a way to toggle the preview setting. I suggest you do this via the BufEnter autocmd with a * as the pattern.

augroup TogglePreview
  autocmd Filetype,BufEnter * execute 'set completeopt'.(&ft == 'cpp' ? '+' : '-').'=preview'
augroup END

The idea is that the autocmd uses 'filetype' upon entering a new buffer or settings the buffer's 'filetype' to decide to turn on/off the preview option.

You may want to consider using :pclose to close the preview window as well.

For more help see:

:h :au
:h BufEnter
:h 'completeopt'
:h :exe
:h :pclose
| improve this answer | |
  • 1
    Cool. It seems like this has to be an '*' event. Why would you prefer WinEnter over BufEnter? Also, why do we need the 'FileType' in there? Is not WinEnter (or BuffEnter) enough? Thanks. – mbilyanov Apr 7 '16 at 22:29
  • 1
    Using BufEnter is probably better (I have changed the post). The reason I use FileType event is in case you a buffer's 'filetype' changes. – Peter Rincker Apr 7 '16 at 22:40

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.