Vim: Создание родительских каталогов при сохранении - PullRequest
105 голосов
/ 27 ноября 2010

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

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

Ответы [ 6 ]

82 голосов
/ 28 ноября 2010
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.

Обновление : чуть лучшее решение, которое также проверяет непустой тип buf и использует 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
17 голосов
/ 27 ноября 2010

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

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

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

6 голосов
/ 31 июля 2011

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

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

Если мне нужно создать каталог, в котором я нахожусь, я набираю :mk., и он заменяет его на «! Mkdir -p / path / to / my / file /» и позволяет мне просмотреть команду перед ее вызовом .

3 голосов
/ 18 марта 2017

Этот код предложит вам создать каталог с :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
3 голосов
/ 24 февраля 2012

Я сделал :saveas! создать каталог, если отсутствует: https://github.com/henrik/dotfiles/commit/54cc9474b345332cf54cf25b51ddb8a9bd00a0bb

1 голос
/ 26 сентября 2012

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

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

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

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

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

РЕДАКТИРОВАТЬ: Примечания благодаря ZyX

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