11

I created an augroup in my .vimrc containing several autocmd and I need to enable/disable these autocommand on the fly.

The idea is to create a mapping (let's say F4 for example) which would enable these autocommands when pressed once and disable them when pressed again without having to source a file or reload the .vimrc.

How can I do that?

15

Building on your answer: you don't need a variable to keep state of the augroup, you can use exists() for that, provided that you know at least one of the autocmds that are part of the group:

function! ToggleTestAutoGroup()
    if !exists('#TestAutoGroup#BufEnter')
        augroup TestAutoGroup
            autocmd!
            autocmd BufEnter   * echom "BufEnter " . bufnr("%")
            autocmd BufLeave   * echom "BufLeave " . bufnr("%")
            autocmd TabEnter   * echom "TabEnter " . tabpagenr()
            autocmd TabLeave   * echom "TabLeave " . tabpagenr()
        augroup END
    else
        augroup TestAutoGroup
            autocmd!
        augroup END
    endif
endfunction

nnoremap <F4> :call ToggleTestAutoGroup()<CR>
  • Hey cool way to improve it! I didn't know you can do that. – statox Jul 31 '15 at 18:20
  • 1
    You could even split the group in 2 parts and remove the else branch, by running the autocmd! unconditionally at the beginning. – VanLaser Jul 31 '15 at 18:58
  • @VanLaser Could you? Have you tried doing it that way? Hint: what would exists('#TestAutoGroup#BufEnter') return after an autocmd!? – Sato Katsura Jul 31 '15 at 19:08
  • 1
    Something like this, maybe: pastebin.com/HEEYjseR – VanLaser Jul 31 '15 at 19:20
  • 1
    @VanLaser And then you could make that operation stateless, by getting rid of that global variable. Perhaps there's a function that could take care of that. That function might need to... Ow. Right. :) – Sato Katsura Aug 1 '15 at 13:17
8

(I actually figured it out by myself but as I didn't find an answer on this site I thought that could be usefull to create a self-answered question)

To do so it is possible to create the following function and put it in the .vimrc:

function! ToggleTestAutoGroup()
    if !exists('g:TestAutoGroupMarker')
        let g:TestAutoGroupMarker = 1
    endif

    " Enable if the group was previously disabled
    if (g:TestAutoGroupMarker == 1)
        let g:TestAutoGroupMarker = 0

        " actual augroup
        augroup TestAutoGroup
            autocmd! BufEnter   * echom "BufEnter " . bufnr("%")
            autocmd! BufLeave   * echom "BufLeave " . bufnr("%")
            autocmd! TabEnter   * echom "TabEnter " . tabpagenr()
            autocmd! TabLeave   * echom "TabLeave " . tabpagenr()
        augroup END
    else    " Clear the group if it was previously enabled
        let g:TestAutoGroupMarker = 1

        " resetting the augroup
        augroup TestAutoGroup
            autocmd!
        augroup END
    endif
endfunction

The function creates a variable used to determine if the group was previously enabled or not.

When it wasn't enabled, the group is populated with the wanted autocommands. If the group was previously enabled we use autocmd! to "reset" it i.e. deleting the command previously entered in it.

A relevant documentation is here

Finally it is possible to create the folowing mapping:

nnoremap <F4> :call ToggleTestAutoGroup()<CR>

to use F4 to call the function.

EDIT: Karl Yngve Lervåg suggested an improved version of this function which reduced the number of lines of code, I felt it would be good to keep both versions the first one being still working maybe easier to understand by a vimscript debutant like me.

Here is Karl's improved function, many thanks to him:

function! ToggleTestAutoGroup()
    " Switch the toggle variable
    let g:TestAutoGroupToggle = !get(g:, 'TestAutoGroupToggle', 1)

    " Reset group
    augroup TestAutoGroup
        autocmd!
    augroup END

    " Enable if toggled on
    if g:TestAutoGroupToggle
        augroup TestAutoGroup
            autocmd! BufEnter   * echom "BufEnter " . bufnr("%")
            autocmd! BufLeave   * echom "BufLeave " . bufnr("%")
            autocmd! TabEnter   * echom "TabEnter " . tabpagenr()
            autocmd! TabLeave   * echom "TabLeave " . tabpagenr()
        augroup END
    endif
endfunction

In this version the group is always reset, and if it wasn't enabled, it is populated with the wanted autocommands

7

I find the easy way is to use a global variable. Example:

augroup TestAutoGroup
  autocmd!
  autocmd BufEnter * |
        \ if get(g:, 'toggle_autocmd', 1) |
        \   echom "BufEnter " . bufnr("%") |
        \ endif
augroup END

nnoremap <f4> :<c-u>let g:toggle_autocmd = !get(g:, 'toggle_autocmd', 1)<cr>

For more help see:

:h g:
:h get()
:h :if
:h :bar
:h line-continuation
  • I'm not sure to understand why you think it is an easy way: I'm not a vimscript master so your syntax seems a little bit overcomplicated to me. What are the pros of you method? – statox Jul 31 '15 at 19:28
  • Pros: 1) No function. 2) Can easily be adapted to use a buffer/window local variables instead of a global variable. 3) Simple mapping – Peter Rincker Jul 31 '15 at 20:32
  • Ok. Thank you for sharing your solution I wouldn't have thought of doing it this way! – statox Aug 1 '15 at 9:01

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.