10

I'm trying to improve the code from this answer to ask for confirmation before creating the missing directory, this is what I write:

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

One thing I'm missing: when I don't press y at the prompt I'd like Vim to abort the write so I don't get the error E212: Can't open file for writing and I don't need to hit another key to make the error message disappear. There is a way to achieve this?

9

Instead of using the BufWritePre autocmd, you can use the BufWriteCmd autocmd, from :help BufWriteCmd:

Should do the writing of the file and reset 'modified' if successful, unless '+' is in 'cpo' and writing to another file cpo-+.

We can just call :write from the autocmd. This will take care of setting modified.

So the logic would then be modified to call :write when the directory already exist, and call :write after creating the directory if it doesn't exist yet. If you press n, we do nothing. This will leave the buffer as-is, and won't re-set modified, so :q will still give you a E37: No write since last change error.

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
    In VimScript files, the leading : is never necessary for commands. – tommcdo Feb 11 '15 at 13:54
  • @tommcdo Thanks. For some reason my brain forgets this sometimes >_< – Martin Tournoij Feb 11 '15 at 13:58
  • 2
    @toro2k Thanks. I didn't know about that. I edited my answer, I also added silent so you won't get a message if you're not using this autogroup. I also fixed another problem I noticed: :w another_name didn't work (not it works). – Martin Tournoij Feb 13 '15 at 14:16
  • 2
    @toro2k Because otherwise write will just write to current filename (just like when you type :write), and :write another_filename won't work (it will still use the original filename). – Martin Tournoij Feb 13 '15 at 14:43
  • 1
    @whitesiroi You can use the bufype setting to get the buffer type. Feel free to edit the post with a fix (or if you don't, I will next week). – Martin Tournoij Aug 18 '16 at 11:11

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.