¿Cómo puedo evitar que Vim escriba un archivo sin generar un error?


10

Estoy tratando de mejorar el código de esta respuesta para pedir confirmación antes de crear el directorio que falta, esto es lo que escribo:

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"))

Una cosa que me falta: cuando no presiono yel mensaje, me gustaría que Vim cancele la escritura para no obtener el error E212: Can't open file for writingy no necesito presionar otra tecla para que desaparezca el mensaje de error. Hay una manera de lograr esto?

Respuestas:


9

En lugar de usar el BufWritePreautocmd, puede usar el BufWriteCmd autocmd, desde :help BufWriteCmd:

Debe escribir el archivo y restablecer 'modificado' si tiene éxito, a menos que '+' esté en 'cpo' y escriba en otro archivo cpo- +.

Solo podemos llamar :writedesde el autocmd. Esto se encargará de la configuración modified.

Entonces, la lógica se modificaría para llamar :writecuando el directorio ya existe, y llamar :writedespués de crear el directorio si aún no existe. Si presiona n, no hacemos nada. Esto dejará el búfer como está y no se volverá a configurar modified, por :qlo que aún le dará un E37: No write since last changeerror.

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"))

2
En los archivos VimScript, el inicio :nunca es necesario para los comandos.
tommcdo

@tommcdo Gracias. Por alguna razón, mi cerebro olvida esto a veces> _ <
Martin Tournoij

2
@ toro2k Gracias. No sabía sobre eso. Edité mi respuesta, también agregué silentpara que no recibas un mensaje si no estás usando esto autogroup. También solucioné otro problema que noté: :w another_nameno funcionó (no funciona).
Martin Tournoij

2
@ toro2k Porque de lo contrario writesimplemente escribirá en el nombre de archivo actual (al igual que cuando escribe :write), y :write another_filenameno funcionará (seguirá utilizando el nombre de archivo original).
Martin Tournoij

1
@whitesiroi Puede usar la bufypeconfiguración para obtener el tipo de búfer. Siéntase libre de editar la publicación con una solución (o si no lo hace, lo haré la próxima semana).
Martin Tournoij
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.