web-dev-qa-db-fra.com

Vim: Création de répertoires parents lors de l'enregistrement

Si j'invoque vim foo/bar/somefile mais foo/bar n'existe pas déjà, Vim refuse de sauvegarder.

Je sais que je pourrais passer à un Shell ou faire :!mkdir foo/bar de Vim mais je suis paresseux :) Existe-t-il un moyen pour que Vim le fasse automatiquement lorsqu'il enregistre le tampon?

109
Damien Pollet
augroup BWCCreateDir
    autocmd!
    autocmd BufWritePre * if expand("<afile>")!~#'^\w\+:/' && !isdirectory(expand("%:h")) | execute "silent! !mkdir -p ".shellescape(expand('%:h'), 1) | redraw! | endif
augroup END

Notez les conditions: expand("<afile>")!~#'^\w\+:/' empêchera vim de créer des répertoires pour des fichiers comme ftp://* Et !isdirectory Empêchera un appel mkdir coûteux.

pdate: solution nettement meilleure qui vérifie également le type de buft non vide et utilise 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
86
ZyX

Sur la base des suggestions de ma question, voici ce que j'ai fini avec:

function WriteCreatingDirs()
    execute ':silent !mkdir -p %:h'
    write
endfunction
command W call WriteCreatingDirs()

Ceci définit le :W commande. Idéalement, j'aimerais avoir tout :w!, :wq, :wq!, :wall etc fonctionnent de la même manière, mais je ne sais pas si c'est possible sans les réimplémenter tous avec des fonctions personnalisées.

18
Damien Pollet

J'ai ajouté ceci à mon ~/.vimrc

cnoremap mk. !mkdir -p <c-r>=expand("%:h")<cr>/

Si je dois créer le répertoire dans lequel je me trouve, je tape :mk. et il le remplace par "! mkdir -p/chemin/vers/mon/fichier /" et me permet de revoir la commande avant de l'invoquer.

6
Asa Ayers
3
Henrik N

Ce code vous invitera à créer le répertoire avec :w, ou faites-le simplement avec :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
3
Tom Hale

Je pense que j'ai réussi à le faire en trois lignes, en combinant ce que les autres disent sur cette réponse.

Cela semble faire l'affaire:

if has("autocmd")
  autocmd BufWritePre * :silent !mkdir -p %:p:h
end

Il tente de créer le dossier automatiquement lors de l'enregistrement d'un tampon. Si quelque chose de mauvais se produit (c'est-à-dire des problèmes d'autorisation), il se fermera simplement et laissera l'écriture du fichier échouer.

Si quelqu'un voit des défauts évidents, veuillez poster un commentaire. Je ne connais pas très bien Vimscript.

EDIT: Notes grâce à ZyX

  • Cela ne fonctionnera pas si vos dossiers contiennent des espaces (apparemment, ils ne sont pas correctement échappés ou quelque chose)
  • Ou si vous faites des pseudo-fichiers.
  • Ou si vous vous approvisionnez en vimrc.
  • Mais fils, c'est court.
1
kikito