Vim : 저장시 상위 디렉토리 생성


122

호출 vim foo/bar/somefile했지만 foo/bar아직 존재하지 않으면 Vim은 저장을 거부합니다.

셸로 전환하거나 :!mkdir foo/barVim에서 할 수 있다는 것을 알고 있지만 게으르다 :) 버퍼를 저장할 때 Vim이 자동으로 수행하도록하는 방법이 있습니까?


13
mkdir -p %:h중첩 된 존재하지 않는 경로에 대해 작동하고 경로가 이미있을 때 오류를 발생시키지 않으며 %:h현재 파일의 전체 경로 이기 때문에 더 좋습니다 . 그러나 이것을 자동으로 호출하는 방법을 모릅니다. 일반적으로 이것은 automcommands로 수행되지만 BufWritePre이벤트는 여기서 작동하지 않는 것 같습니다.
Konrad Rudolph

파일이 존재하는지 확인하고 내장 write을 호출하고 시스템을 호출 하는 함수를 정의합니다 mkdir -p. dirname그렇지 않으면 매핑합니다 W. 구문을 검색하고 답변으로 게시하기에는 너무 게으르다 ... 죄송합니다
khachik

1
나는 당신의 제안과 별칭 :w을 결합 mkdir -p %:h하여 건물 을 만들 수 있다고 생각합니다:write
Damien Pollet

답변:


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

조건을 참고 : expand("<afile>")!~#'^\w\+:/'같은 파일에 대한 디렉토리를 만들 수 정력을 방지 ftp://*하고 !isdirectory비싼 MKDIR 호출을 방지 할 수 있습니다.

업데이트 : 비어 있지 않은 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

1
감사합니다 :) 내가-해킹 추측하는 것보다 훨씬 청소기 보인다
데미안 Pollet

11
call mkdir(expand('%:h'), 'p')휴대 성이 더 좋을 수 있습니다.
Marius Gedminas 2012-08-21

1
@MariusGedminas 그 변경 사항이 적용된 전체 코드를보고 싶습니다. 답변으로 게시하거나 어딘가에 업로드 해 주시겠습니까?
kikito 2012

@kikito 내 대답을 참조하십시오. 그 댓글 몇 시간 후에 수정되었습니다.
ZyX 2012 년

@Zyx 감사합니다! 나는 조금 더 짧은 것을 끝내었지만 (현재 내 대답은 현재 마지막 것입니다) 트릭을 잘하는 것 같습니다.
kikito

20

내 질문에 대한 제안에 따라 다음과 같은 결과를 얻었습니다.

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

이것은 :W 명령을 . 이상적으로, 나는 모두가하고 싶은 :w!, :wq, :wq!, :wall동일하게 작동 등을하지만, 기본적으로 사용자 정의 기능을 모두 재 구현없이 가능 있는지 확실하지 않습니다.


2
이 명령을 시도했는데를 사용할 때마다 :W화면이 거의 비어 있습니다. 이전 옵션을 제거하고 피드백을 제공하겠습니다.
moebius_eye

6

나는 이것을 ~ / .vimrc에 추가했습니다.

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

내가있는 디렉토리를 생성해야하는 경우 입력 :mk.하고 "! mkdir -p / path / to / my / file /"로 바꾸고 명령을 호출하기 전에 검토 할 수 있습니다.



3

이 코드 와 디렉토리를 생성하라는 메시지를 표시합니다 :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

1

나는 다른 사람들 이이 대답에 대해 말하는 것을 결합하여 세 줄로 이것을 할 수 있다고 생각합니다.

이것은 트릭을 수행하는 것 같습니다.

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

버퍼 저장시 자동으로 폴더 생성을 시도합니다. 잘못된 일이 발생하면 (예 : 권한 문제) 종료되고 파일 쓰기가 실패합니다.

누구든지 명백한 결함을 발견하면 의견을 게시하십시오. 나는 vimscript에 정통하지 않습니다.

편집 : ZyX 덕분에 메모

  • 폴더에 공백이 있으면 작동하지 않습니다 (분명히 제대로 이스케이프되지 않은 것 같습니다)
  • 또는 의사 파일을 수행하는 경우.
  • 또는 vimrc를 소싱하는 경우.
  • 하지만 아들, 짧습니다.

1
%그러한 스크립트에는 절대 사용하지 마십시오 . 예를 들어,라는 이름의 파일을 편집하는 경우 : 빔은 특수 기호를 탈출하지 않을 /mnt/windows/Documents and Settings/User/_vimrc: 네 개의 새로운 디렉토리를 가지고 끝날 것을 /mnt/windows/Documents, ./and, ./Settings./Settings/User. 그리고 :execute여기 에는 필요하지 않습니다 .
ZyX 2012 년

1
system()완전히 침묵 쉘 통화 기능,하지만 당신은 둘 다 필요하지 않습니다 :execute%:p:h: :silent !mkdir -p %:p:h(당신이 필요로하는 수 있지만 당신이 쓴 것을 정확히 작동 :redraw!이 경우에, 마지막에 :execute편리 제공)하지만 사용하는 것이 좋습니다 call system('mkdir -p '.shellescape(expand('%:p:h'))). 사용하십니까 :execute '!command' shellescape(arg, 1)대신의 앞머리를 사용하는 경우 (shellescape 두 번째 인수를) system(). 이스케이프 된 인수에 개행이 포함되어 있으면 앞머리를 사용하십시오.
ZyX 2012 년

그리고 당신은 내가 처음으로 코드에 방지하고 다른 문제를 방지하지 않습니다 시작 쉘마다의 vimrc 소싱 한 후 하나의 추가 시간을 (당신의 vimrc 업데이트 수행하여 끌어 오기 랬 :source ~/.vimrc) (이것은 무엇 augroupautocmd!폐기보기 쉘을 실행 한 후,위한 것입니다) 명령 (즉 redraw!), 의사 파일을 사용하는 경우 가비지 디렉토리 생성 (첫 번째 코드에서는 패턴과 일치하는 파일 이름으로 만 확인되지만 두 번째 코드에서는 확인 &buftype) 케이스 디렉토리에서 쓸모없는 쉘 호출 존재합니다 ( isdirectory()조건).
ZyX

1
@ZyX 피드백에 감사드립니다. 내가 가지고 있지 않은 문제를 해결하고 싶지 않습니다. 내 폴더에 특수 문자 (즉, 공백)를 사용하지 않으므로 % : p : h는 나에게 적합합니다. 나는 결코 vimrc를 소스하지 않으며 (대신 vim을 죽이고 다시 엽니 다) 의사 파일이 무엇인지조차 모릅니다. 다시 그리기! 나에게 아무것도하지 않는 것 같습니다. 그러나 나는 모든 것을 더 짧게 만들기 위해 실행을 제거하는 당신의 제안을 좋아합니다. 건배!
kikito

1
특수 문자가 있든 없든 상관 없어요. 신경 써야 할 것입니다. %누구에게나 그것을 사용하도록 제안 하기에는 확장에 너무 많은 문제가 있습니다 . 의사 파일은 많은 플러그인 (예 : 도망자 또는 내 aurum)에서 사용되므로 관심을 가질 가치가 있습니다. vimrc를 자원하는 것도 일반적인 관행입니다. vimrc에서 원하는 것은 무엇이든 가질 수 있지만 답으로 제안하지 마십시오. :silent! call mkdir(expand('%:p:h'), 'p')Variant를 사용하면 내가 언급 한 두 가지 사항과 언급하지 않은 세 번째 사항 !mkdir이 해결됩니다. Windows에서는 작동하지 않습니다.
ZyX
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.