Como ativar / desativar um augroup em tempo real?

13

Eu criei um augroupno meu .vimrccontendo vários autocmde eu preciso ativar / desativar estes autocommandem tempo real.

A idéia é criar um mapeamento (digamos, F4por exemplo) que habilite esses comandos automáticos quando pressionados uma vez e os desabilite quando pressionados novamente sem precisar gerar um arquivo ou recarregar o arquivo .vimrc.

Como eu posso fazer isso?

statox
fonte

Respostas:

17

Com base na sua resposta: você não precisa de uma variável para manter o estado de augroup, você pode usar exists()para isso, desde que conheça pelo menos um dos autocmds que fazem parte do grupo:

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>
Sato Katsura
fonte
Hey maneira legal de melhorá-lo! Eu não sabia que você pode fazer isso.
Statox
1
Você pode até dividir o grupo em duas partes e remover a elseramificação, executando o autocmd!incondicionalmente no início.
31415 VanLaser
@VanLaser Você poderia? Você já tentou fazer dessa maneira? Dica: o que exists('#TestAutoGroup#BufEnter')retornaria após um autocmd!?
Sato Katsura
1
Algo assim, talvez: pastebin.com/HEEYjseR
VanLaser
1
@ VanLaser E então você pode tornar essa operação sem estado, livrando-se dessa variável global. Talvez haja uma função que possa cuidar disso. Essa função pode precisar ... Ow. Direita. :)
Sato Katsura
9

(Na verdade, eu descobri isso sozinho, mas como não encontrei uma resposta neste site, pensei que seria útil criar uma pergunta auto-respondida )

Para isso, é possível criar a seguinte função e colocá-la no .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

A função cria uma variável usada para determinar se o grupo foi ativado anteriormente ou não.

Quando não foi ativado, o grupo é preenchido com os comandos automáticos desejados. Se o grupo foi ativado anteriormente, usamos autocmd!para "redefinir", ou seja, excluir o comando anteriormente inserido nele.

Uma documentação relevante está aqui

Por fim, é possível criar o seguinte mapeamento:

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

para usar F4para chamar a função.

EDIT : Karl Yngve Lervåg sugeriu uma versão aprimorada dessa função que reduziu o número de linhas de código; achei que seria bom manter as duas versões, a primeira ainda funcionando, talvez mais fácil de entender por um estreante do vimscript como eu.

Aqui está a função aprimorada de Karl, muito obrigado a ele:

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

Nesta versão, o grupo é sempre redefinido e, se não foi ativado, é preenchido com os comandos automáticos desejados

statox
fonte
7

Acho que a maneira mais fácil é usar uma variável global. Exemplo:

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>

Para obter mais ajuda, consulte:

:h g:
:h get()
:h :if
:h :bar
:h line-continuation
Peter Rincker
fonte
Não sei ao certo por que você acha que é uma maneira fácil: eu não sou um mestre em vimscript, então sua sintaxe parece um pouco complicada demais para mim. Quais são os profissionais do seu método?
Statox
Prós: 1) Sem função. 2) Pode ser facilmente adaptado para usar variáveis ​​locais de buffer / janela em vez de uma variável global. 3) Mapeamento simples
Peter Rincker 31/07/2015
Está bem. Obrigado por compartilhar sua solução. Eu não pensaria em fazê-lo dessa maneira!
Statox