Vim: Création de répertoires parents lors de la sauvegarde

Si vim foo/bar/somefile mais que foo/bar n’existe pas déjà, Vim refuse d’enregistrer.

Je sais que je pourrais passer à un shell ou faire :!mkdir foo/bar de Vim mais je suis paresseux 🙂 Y a-t-il un moyen de faire cela automatiquement par Vim quand il enregistre le tampon?

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

Notez les conditions: expand("")!~#'^\w\+:/' empêchera vim de créer des répertoires pour des fichiers tels que ftp://* et !isdirectory empêchera les appels coûteux à mkdir.

Mise à jour : une solution légèrement meilleure qui vérifie également la présence de buftype 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(''), +expand('')) augroup END 

Sur la base des suggestions à 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 la commande :W Idéalement, j’aimerais avoir tout :w! , :wq :wq! , :wall etc fonctionne de la même manière, mais je ne suis pas sûr que ce soit possible sans les réimplémenter avec des fonctions personnalisées.

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

cnoremap mk. !mkdir -p =expand("%:h")/

Si je dois créer le répertoire dans lequel je suis, tapez :mk. et il remplace cela par “! mkdir -p / chemin / vers / mon / fichier /” et me permet de revoir la commande avant de l’invoquer.

J’ai fait :saveas! créer le répertoire s’il est manquant: https://github.com/henrik/dotfiles/commit/54cc9474b345332cf54cf25b51ddb8a9bd00a0bb

Ce code vous invitera à créer le répertoire avec :w , ou simplement le faire avec :w! :

 augroup vimrc-auto-mkdir autocmd! autocmd BufWritePre * call s:auto_mkdir(expand(':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 

Je pense que j’ai réussi à le faire en trois lignes, en combinant ce que d’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 arrive (c.-à-d. Des problèmes de permission), il ne fera que se fermer et laisser le fichier écrire échouer.

Si quelqu’un voit des défauts évidents, merci de poster un commentaire. Je ne suis pas très versé dans le vimscript.

EDIT: Notes grâce à ZyX

  • Cela ne fonctionnera pas si vos dossiers ont des espaces (apparemment, ils ne sont pas correctement échappés ou quelque chose)
  • Ou si vous faites des pseudo-fichiers.
  • Ou si vous recherchez votre vimrc.
  • Mais mon fils, c’est court.