If I invoke vim foo/bar/somefile
but foo/bar
don\'t already exist, Vim refuses to save.
I know I could switch to a shell or do :!mkdi
Based on the suggestions to my question, here's what I ended up with:
function WriteCreatingDirs()
execute ':silent !mkdir -p %:h'
write
endfunction
command W call WriteCreatingDirs()
This defines the :W
command. Ideally, I'd like to have all of :w!
, :wq
, :wq!
, :wall
etc work the same, but I'm not sure if it's possible without basically reimplementing them all with custom functions.
I made :saveas!
create the directory if missing: https://github.com/henrik/dotfiles/commit/54cc9474b345332cf54cf25b51ddb8a9bd00a0bb
augroup BWCCreateDir
autocmd!
autocmd BufWritePre * if expand("<afile>")!~#'^\w\+:/' && !isdirectory(expand("%:h")) | execute "silent! !mkdir -p ".shellescape(expand('%:h'), 1) | redraw! | endif
augroup END
Note the conditions: expand("<afile>")!~#'^\w\+:/'
will prevent vim from creating directories for files like ftp://*
and !isdirectory
will prevent expensive mkdir call.
Update: sligtly better solution that also checks for non-empty buftype and uses mkdir()
:
function s:MkNonExDir(file, buf)
if empty(getbufvar(a:buf, '&buftype')) && a:file!~#'\v^\w+\:\/'
let dir=fnamemodify(a:file, ':h')
if !isdirectory(dir)
call mkdir(dir, 'p')
endif
endif
endfunction
augroup BWCCreateDir
autocmd!
autocmd BufWritePre * :call s:MkNonExDir(expand('<afile>'), +expand('<abuf>'))
augroup END
This code will prompt you to create the directory with :w
, or just do it with :w!
:
augroup vimrc-auto-mkdir
autocmd!
autocmd BufWritePre * call s:auto_mkdir(expand('<afile>:p:h'), v:cmdbang)
function! s:auto_mkdir(dir, force)
if !isdirectory(a:dir)
\ && (a:force
\ || input("'" . a:dir . "' does not exist. Create? [y/N]") =~? '^y\%[es]$')
call mkdir(iconv(a:dir, &encoding, &termencoding), 'p')
endif
endfunction
augroup END
I think I managed to do this in three lines, combining what others are saying on this answer.
This seems to do the trick:
if has("autocmd")
autocmd BufWritePre * :silent !mkdir -p %:p:h
end
It attempts to create the folder automatically when saving a buffer. If anything bad happens (i.e. permission issues) it will just shut up and let the file write fail.
If anyone sees any obvious flaws, please post a comment. I'm not very versed in vimscript.
EDIT: Notes thanks to ZyX
I added this to my ~/.vimrc
cnoremap mk. !mkdir -p <c-r>=expand("%:h")<cr>/
If I need to create the directory I'm in I type :mk.
and it replaces that with "!mkdir -p /path/to/my/file/" and allows me to review the command before I invoke it.