Vim: Creating parent directories on save

前端 未结 6 1757
一生所求
一生所求 2020-12-07 08:32

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

相关标签:
6条回答
  • 2020-12-07 09:11

    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.

    0 讨论(0)
  • 2020-12-07 09:20

    I made :saveas! create the directory if missing: https://github.com/henrik/dotfiles/commit/54cc9474b345332cf54cf25b51ddb8a9bd00a0bb

    0 讨论(0)
  • 2020-12-07 09:22
    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
    
    0 讨论(0)
  • 2020-12-07 09:26

    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
    
    0 讨论(0)
  • 2020-12-07 09:29

    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

    • This will not work if your folders have spaces on them (apparently they are not properly escaped or something)
    • Or if you are doing pseudo files.
    • Or if you are sourcing your vimrc.
    • But son, it is short.
    0 讨论(0)
  • 2020-12-07 09:30

    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.

    0 讨论(0)
提交回复
热议问题