2010-11-27 27 views
80

Si invoco vim foo/bar/somefile pero foo/bar aún no existe, Vim se niega a guardar.Vim: Crear directorios principales en guardar

Sé que podría cambiar a una concha o hacer :!mkdir foo/bar de Vim, pero soy perezoso :) ¿Hay una manera de hacer que Vim hacer eso de forma automática cuando se guarda la memoria intermedia?

+7

'mkdir -p%: H' es mejor, ya que funciona de caminos existentes no anidados, no genera un error cuando la ruta ya existe, y '%: h' es la ruta completa del archivo actual. Sin embargo, no sé cómo invocar esto automáticamente. Normalmente, esto se hace con automcommands pero el evento 'BufWritePre' no parece funcionar aquí. –

+0

Define una función que verifica si el archivo existe y llama a la escritura 'write' y llama al sistema a' mkdir -p' en 'dirname' de lo contrario, asócielo a' W' ... Soy demasiado flojo para buscar la sintaxis y que la publique como respuesta ... lo sentimos – khachik

+1

supongo que podría combinar ambos sus sugerencias y alias ': W' a' mkdir -p%: H' seguido por el Builting ': write' –

Respuesta

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

Nota: las condiciones expand("<afile>")!~#'^\w\+:/' evitará vim desde la creación de directorios de archivos como ftp://* y !isdirectory prevendrán costosos llamada mkdir.

actualización: sligtly mejor solución que también comprueba buftype no vacío y utiliza 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 
+1

Gracias, parece mucho más limpio de lo que supongo-hackeado :) –

+9

'call mkdir (expand ('%: h'), 'p')' podría ser más portátil. –

+1

@MariusGedminas Me gustaría ver el código completo con ese cambio. ¿Podrías publicarlo como respuesta/subirlo a alguna parte? – kikito

13

Sobre la base de las sugerencias a mi pregunta, esto es lo que terminó con:

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

Esto define el comando :W. Idealmente, me gustaría tener todos :w!, :wq, :wq!, :wall etc. funcionan de la misma manera, pero no estoy seguro de si es posible sin básicamente reimplementarlos todos con funciones personalizadas.

+1

que he probado este mismo comando y cada vez que uso ': W', mi pantalla se vuelve casi en blanco. Trataré de eliminar mis opciones anteriores y dar feedback. –

5

he añadido esto a mi ~/.vimrc

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

Si yo Necesito crear el directorio en el que estoy. Escribo :mk. y lo reemplaza con "! mkdir -p/ruta/a/mi/archivo /" y me permite revisar el comando antes de invocarlo.

0

Creo que logré hacer esto en tres líneas, la combinación de lo que otros dicen sobre esta respuesta.

Esto parece hacer el truco:

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

Se intenta crear la carpeta automáticamente al guardar un búfer. Si ocurre algo malo (es decir, problemas de permisos), se cerrará y dejará que el archivo escriba fallará.

Si alguien ve defectos obvios, publique un comentario. No soy muy versado en vimscript.

EDIT: Notas gracias a ZYX

  • Esto no funcionará si sus carpetas tienen espacios en ellos (al parecer no se escapan correctamente o algo así)
  • o si está haciendo archivos seudo.
  • O si está obteniendo su vimrc.
  • Pero hijo, es corto.
+1

Nunca use '%' en tales scripts. Vim no escapará ningún símbolo especial: por ejemplo, si está editando un archivo llamado '/ mnt/windows/Documents and Settings/User/_vimrc', terminará teniendo cuatro directorios nuevos:'/mnt/windows/Documents ','./y ','./Settings' y './Settings/User'.Y, por cierto, no necesitas ': ejecutar' aquí. – ZyX

+1

Existe la función 'system()' para llamadas de shell completamente silenciosas, pero no necesita tanto ': execute' como'%: p: h': ': silent! Mkdir -p%: p: h' funciona exactamente como lo que has escrito (aunque es posible que necesites ': redraw!' al final, en este caso ': execute' es útil), pero es mejor usar' call system ('mkdir -p' .shellescape (expandir '%: p: h'))) '. Utilice ': execute '! Command' shellescape (arg, 1)' (con el segundo argumento para shellescape) si tiene que usar bangs en lugar de 'system()'. Use bangs si el argumento escape contiene líneas nuevas. – ZyX

+0

Y no evita otros problemas que estoy evitando en mi primer fragmento de código: lanzar shell una vez más después de cada vimrc sourcing (suponiendo que obtenga actualizaciones de vimrc haciendo ': source ~/.vimrc') (esto es lo que' augroup' y 'autocmd!' son para), vista desechada después de ejecutar comandos de shell (para eso sirve 'redraw!'), crear directorios basura en caso de usar pseudo-archivos (en el primer código cortado se comprueba solo haciendo coincidir nombre de archivo contra un patrón, pero en el segundo también verifico '& buftype') y inútil llamada de shell en caso de que exista directorio (condición' isdirectory() '). – ZyX

0

This code le pedirá que cree el directorio con :w, o simplemente hacerlo con :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 
Cuestiones relacionadas