Como posso impedir que o Vim grave um arquivo sem gerar um erro?

10

Estou tentando melhorar o código desta resposta para pedir confirmação antes de criar o diretório ausente, é isso que escrevo:

function! CreateDirectoryAskConfirmation(path)
    if !isdirectory(a:path)
        echohl Question
        echo "Create directory " . a:path . "?"
        echohl None

        let response = nr2char(getchar())
        if response ==? "y"
            call mkdir(a:path, "p")
        endif
    endif
endfunction

autocmd BufWritePre * call CreateDirectoryAskConfirmation(expand("<afile>:p:h"))

Uma coisa está faltando: quando não pressiono yno prompt, gostaria que o Vim abortasse a gravação, para não receber o erro E212: Can't open file for writinge não precisar pressionar outra tecla para que a mensagem de erro desapareça. Existe uma maneira de conseguir isso?

toro2k
fonte

Respostas:

9

Em vez de usar o BufWritePreautocmd, você pode usar o BufWriteCmd autocmd, em :help BufWriteCmd:

Deve fazer a gravação do arquivo e redefinir 'modificado' se for bem-sucedido, a menos que '+' esteja em 'cpo' e gravando em outro arquivo cpo- +.

Podemos apenas ligar a :writepartir do autocmd. Isso cuidará da configuração modified.

Portanto, a lógica seria modificada para chamar :writequando o diretório já existir e chamar :writeapós criar o diretório, se ele ainda não existir. Se você pressionar n, não fazemos nada. Isso deixará o buffer como está e não será redefinido modified; portanto :q, ainda ocorrerá um E37: No write since last changeerro.

function! CreateDirectoryAskConfirmation(path, dir)
    silent doautocmd BufWritePre

    " Directory exists, :write and return
    if isdirectory(a:dir)
        execute 'write ' . a:path
        silent doautocmd BufWritePost
        return
    endif

    " Ask for confirmation to create this directory
    echohl Question
    echo "Create directory `" . a:dir . "' [y/N]?"
    echohl None

    let response = nr2char(getchar())
    " mkdir() and :write if we want to make a directory
    if response ==? "y"
        call mkdir(a:dir, "p")
        execute 'write ' . a:path
        silent doautocmd BufWritePost
    endif
endfunction

autocmd BufWriteCmd * call CreateDirectoryAskConfirmation(expand("<amatch>:p"), expand("<amatch>:p:h"))
Martin Tournoij
fonte
2
Nos arquivos VimScript, a liderança :nunca é necessária para comandos.
21415 TommyCdo:
@tommcdo Obrigado. Por alguma razão, meu cérebro esquece isso às vezes> _ <
Martin Tournoij 11/02/15
2
@ toro2k Obrigado. Eu não sabia disso. Editei minha resposta e também adicionei silentpara que você não receba uma mensagem se não estiver usando isso autogroup. Também consertei outro problema que notei: :w another_namenão funcionou (não funciona).
Martin Tournoij 13/02/2015
2
@ toro2k Porque, caso contrário write, apenas escreverá no nome do arquivo atual (como quando você digita :write) e :write another_filenamenão funcionará (ainda usará o nome do arquivo original).
Martin Tournoij 13/02/2015
11
@whitesiroi Você pode usar a bufypeconfiguração para obter o tipo de buffer. Sinta-se à vontade para editar a postagem com uma correção (ou, caso contrário, eu vou semana que vem).
Martin Tournoij 18/08/19