Vim: creazione di directory padre al salvataggio


122

Se invoco vim foo/bar/somefilema foo/barnon esisto già, Vim si rifiuta di salvare.

So che potrei passare a una shell o farlo :!mkdir foo/barda Vim ma sono pigro :) C'è un modo per far sì che Vim lo faccia automaticamente quando salva il buffer?


13
mkdir -p %:hè migliore perché funziona per percorsi nidificati non esistenti, non genera un errore quando il percorso esiste già ed %:hè il percorso completo del file corrente. Tuttavia, non so come invocarlo automaticamente. Normalmente, questo viene fatto con i comandi automatici, ma l' BufWritePreevento non sembra funzionare qui.
Konrad Rudolph,

Definisci una funzione che controlla se il file esiste e chiama il builtin writee richiama il sistema su mkdir -pon dirnamealtrimenti, W
mappalo

1
Immagino di poter combinare sia i tuoi suggerimenti che l'alias :wper mkdir -p %:hseguire la costruzione:write
Damien Pollet

Risposte:


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

Notare le condizioni: expand("<afile>")!~#'^\w\+:/'impedirà a vim di creare directory per file come ftp://*e !isdirectoryimpedirà costose chiamate a mkdir.

Aggiornamento : soluzione leggermente migliore che controlla anche il buftype non vuoto e utilizza 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
Grazie, sembra molto più pulito di quello che immagino hackerato :)
Damien Pollet

11
call mkdir(expand('%:h'), 'p')potrebbe essere più portabile.
Marius Gedminas

1
@MariusGedminas vorrei vedere il codice completo con quella modifica. Potresti postarlo come risposta / caricarlo da qualche parte?
kikito

@kikito Vedi la mia risposta. È stato modificato poche ore dopo quel commento.
ZyX

@Zyx grazie! Ho finito per fare qualcosa di un po 'più breve (la mia risposta è attualmente l'ultima) ma sembra che funzioni bene.
kikito

20

Sulla base dei suggerimenti alla mia domanda, ecco cosa ho ottenuto:

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

Questo definisce il :Wcomando. Idealmente, mi piacerebbe avere tutti :w!, :wq, :wq!, :wallecc lavorare lo stesso, ma non sono sicuro se è possibile, senza praticamente tutti reimplementare con funzioni personalizzate.


2
Ho provato lo stesso comando e ogni volta che lo uso :W, lo schermo diventa quasi vuoto. Cercherò di rimuovere le mie opzioni precedenti e fornirò un feedback.
moebius_eye

6

L'ho aggiunto al mio ~ / .vimrc

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

Se ho bisogno di creare la directory in cui mi trovo, la digito :mk.e la sostituisce con "! Mkdir -p / path / to / my / file /" e mi permette di rivedere il comando prima di invocarlo.



3

Questo codice ti chiederà di creare la directory con :wo semplicemente di farlo 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

1

Penso di essere riuscito a farlo in tre righe, combinando ciò che gli altri dicono su questa risposta.

Questo sembra fare il trucco:

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

Tenta di creare la cartella automaticamente durante il salvataggio di un buffer. Se succede qualcosa di brutto (ad esempio problemi di autorizzazione) si spegnerà e lascerà che la scrittura del file fallisca.

Se qualcuno vede dei difetti evidenti, per favore pubblica un commento. Non sono molto esperto in vimscript.

EDIT: Note grazie a ZyX

  • Questo non funzionerà se le tue cartelle contengono spazi (apparentemente non sono stati correttamente salvati o qualcosa del genere)
  • O se stai creando pseudo file.
  • O se stai cercando il tuo file vimrc.
  • Ma figlio, è breve.

1
Non usare mai %in tali script. Vim non ha intenzione di fuggire eventuali simboli speciali: per esempio, se si sta modificando un file di nome /mnt/windows/Documents and Settings/User/_vimrcsi finirà per avere quattro nuovi indici: /mnt/windows/Documents, ./and, ./Settingse ./Settings/User. E, a proposito, non hai bisogno di :executequi.
ZyX

1
C'è una system()funzione per chiamate shell completamente silenziose, ma non hai bisogno di entrambe :executee %:p:h: :silent !mkdir -p %:p:hfunziona esattamente come quello che hai scritto (anche se potresti aver bisogno :redraw!alla fine, in questo caso :executetorna utile), ma è meglio usare call system('mkdir -p '.shellescape(expand('%:p:h'))). Usa :execute '!command' shellescape(arg, 1)(con il secondo argomento di shellescape) se devi usare bang invece di system(). Usa frangia se l'argomento con escape contiene una nuova riga.
ZyX

E non eviti altri problemi che sto evitando nel mio primo frammento di codice: avviare la shell una volta in più dopo ogni sourcing di vimrc (supponendo che tu abbia inserito gli aggiornamenti di vimrc facendo :source ~/.vimrc) (questo è ciò che augroupe autocmd!sono per), vista scartata dopo aver lanciato la shell comandi (questo è ciò che redraw!serve), creazione di directory spazzatura in caso di utilizzo di pseudo-file (nel primo codice snippato viene controllato abbinando solo il nome del file a un modello, ma nel secondo controllo anche &buftype) e chiamata shell inutile nella directory case esiste ( isdirectory()condizione).
ZyX

1
@ZyX Grazie per il tuo feedback. Non voglio risolvere problemi che non ho. Non uso mai caratteri speciali (cioè spazi) nelle mie cartelle, quindi%: p: h va bene per me. Non provo mai vimrc (invece uccido e riapro vim) e non so nemmeno cosa siano gli pseudofili. ridisegnare! non sembra farmi niente. Ma mi piace il tuo suggerimento di rimuovere execute per rendere tutto più breve. Saluti!
kikito

1
Non importa se hai caratteri speciali o meno, è la cosa di cui dovresti preoccuparti. Ci sono troppi problemi con l' %espansione per suggerire di usarla a qualcuno. Gli pseudo file sono usati in una grande quantità di plugin (es. Fuggitivo o mio aurum), quindi vale la pena prendersi cura di loro. Anche la fornitura di risorse a vimrc è una pratica comune. Puoi avere quello che vuoi nel vimrc, ma non suggerirlo come risposta. Usare la :silent! call mkdir(expand('%:p:h'), 'p')variante risolve due dei punti che ho menzionato e il terzo che non ho menzionato: !mkdirnon funzionerà su Windows.
ZyX
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.