Bagaimana saya bisa menghentikan Vim dari menulis file tanpa membuat kesalahan?

10

Saya mencoba memperbaiki kode dari jawaban ini untuk meminta konfirmasi sebelum membuat direktori yang hilang, inilah yang saya tulis:

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

Satu hal yang saya lewatkan: ketika saya tidak menekan ypada prompt saya ingin Vim untuk membatalkan penulisan jadi saya tidak mendapatkan kesalahan E212: Can't open file for writingdan saya tidak perlu menekan tombol lain untuk membuat pesan kesalahan hilang. Ada cara untuk mencapainya?

toro2k
sumber

Jawaban:

9

Alih-alih menggunakan BufWritePreautocmd, Anda dapat menggunakan BufWriteCmd autocmd, dari :help BufWriteCmd:

Sebaiknya lakukan penulisan file dan reset 'dimodifikasi' jika berhasil, kecuali '+' di 'cpo' dan menulis ke file lain cpo- +.

Kami hanya dapat menelepon :writedari autocmd. Ini akan menangani pengaturan modified.

Jadi logika kemudian akan dimodifikasi untuk memanggil :writeketika direktori sudah ada, dan memanggil :writesetelah membuat direktori jika belum ada. Jika Anda menekan n, kami tidak melakukan apa pun. Ini akan membiarkan buffer apa adanya, dan tidak akan mengatur ulang modified, sehingga :qmasih akan memberi Anda E37: No write since last changekesalahan.

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
sumber
2
Dalam file VimScript, :perintah tidak pernah diperlukan untuk perintah.
tommcdo
@tomcdo Terima kasih. Entah mengapa otak saya kadang-kadang lupa hal ini> _ <
Martin Tournoij
2
@ toro2k Terima kasih. Saya tidak tahu tentang itu. Saya mengedit jawaban saya, saya juga menambahkan silentsehingga Anda tidak akan menerima pesan jika Anda tidak menggunakan ini autogroup. Saya juga memperbaiki masalah lain yang saya perhatikan: :w another_nametidak berhasil (tidak berfungsi).
Martin Tournoij
2
@ toro2k Karena jika tidak, writehanya akan menulis ke nama file saat ini (sama seperti saat Anda mengetik :write), dan :write another_filenametidak akan berfungsi (masih akan menggunakan nama file asli).
Martin Tournoij
1
@ whitesiroi Anda dapat menggunakan bufypepengaturan untuk mendapatkan tipe buffer. Jangan ragu untuk mengedit posting dengan perbaikan (atau jika tidak, saya akan minggu depan).
Martin Tournoij