2010-11-27 2 views
80

Если я вызываю vim foo/bar/somefile, но foo/bar еще не существует, Vim отказывается сэкономить.Vim: Создание родительских каталогов при сохранении

Я знаю, что могу переключиться на оболочку или сделать :!mkdir foo/bar от Vim, но я ленивый :) Есть ли способ заставить Vim делать это автоматически, когда он сохраняет буфер?

+7

`MkDir -p%: h` лучше, потому что он работает для вложенных несуществующих путей, не вызывает ошибку, когда путь уже существует, а `%: h` - полный путь к текущему файлу. Однако я не знаю, как это сделать автоматически. Обычно это делается с помощью automcommands, но событие `BufWritePre`, похоже, не работает здесь. – 2010-11-27 17:11:29

+0

Определите функцию, которая проверяет, существует ли файл и вызывает встроенную `write`, и вызывает систему в` mkdir -p` на `dirname` в противном случае, сопоставьте ее с` W` ... Я слишком ленив, чтобы искать синтаксис и отправить его в качестве ответа ... Извините – khachik 2010-11-27 17:16:48

+1

Я думаю, что я мог бы комбинировать ваши предложения и псевдоним `: w` с` mkdir -p%: h`, за которым следует builting `: write` – 2010-11-27 17:47:25

ответ

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 

Примечание условия: expand("<afile>")!~#'^\w\+:/' помешают Vim создавать каталоги для файлов, таких как ftp://* и !isdirectory помешают дорогой вызов MKDIR.

Update: sligtly лучшее решение, которое также проверяет непустого buftype и использует 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 
13

на основе предложений на мой вопрос, вот что я закончил с:

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

Это определяет команду :W. В идеале, я бы хотел, чтобы все :w!, :wq, :wq!, :wall и т. Д. Работали одинаково, но я не уверен, что это возможно, не переосмысливая их все с помощью специальных функций.

+1

Я пробовал эта же команда, и каждый раз, когда я использую `: W`, мой экран становится почти пустым. Я попытаюсь удалить мои предыдущие варианты и дать обратную связь. – 2016-09-03 14:28:32

5

Я добавил это мой ~/.vimrc

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

Если я вам нужно создать каталог I'm in I type :mk., и он заменяет это с помощью «! mkdir -p/path/to/my/file /» и позволяет мне просмотреть команду до того, как я ее вызову.

0

Я думаю, что мне удалось сделать это в три строки, комбинируя то, что другие говорят об этом ответе.

Это, кажется, сделать трюк:

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

Он пытается автоматически создать папку при сохранении буфера. Если что-то плохое происходит (например, проблемы с разрешениями), он просто заткнется и позволит файлу сбой записи.

Если кто-либо видит какие-либо очевидные недостатки, отправьте комментарий. Я не очень разбираюсь в vimscript.

EDIT: Заметки благодаря ZYX

  • Это не будет работать, если ваши папки имеют пробелы на них (по-видимому, они не правильно убежали или что-то)
  • Или, если вы делаете псевдо-файлы.
  • Или, если вы ищете свой vimrc.
  • Но сын, он короткий.
0

This code предложит вам создать каталог с :w, или просто сделать это с :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 
Смежные вопросы