Vim에 파일을 저장하기 전에 변경 사항을 볼 수 있습니까?


135

Vim을 사용합니다. 파일을 엽니 다. 편집 한 후 저장하기 전에 편집 한 내용을보고 싶습니다.

Vim에서 어떻게해야합니까?

답변:


57

http://vim.wikia.com/wiki/Diff_current_buffer_and_the_original_file

다음은 현재 편집 된 파일과 파일 시스템에서 수정되지 않은 버전 사이의 차이점을 보는 기능 및 명령입니다. 이것을 vimrc 또는 플러그인 디렉토리에 넣고 파일을 열고 저장하지 않고 수정하고 수행하십시오 :DiffSaved.

function! s:DiffWithSaved()
  let filetype=&ft
  diffthis
  vnew | r # | normal! 1Gdd
  diffthis
  exe "setlocal bt=nofile bh=wipe nobl noswf ro ft=" . filetype
endfunction
com! DiffSaved call s:DiffWithSaved()

diff보기에서 벗어나려면 :diffoff명령을 사용할 수 있습니다 .

아래는 'cvs diff'명령 을 모방하기 위해 유사한 기능입니다 ...


7
@ luc-hermitte :w !diff % -.vimrc를 쉽게 변경할 수없는 끊임없이 변화하는 수많은 상자에서 vim을 사용할 때 대안이 우수하지 않습니까? (diff가 설치되어있는 경우)
thomanski

1
Vim은 마지막 희망의 도구가 아닙니다. 아무것도 사용할 수 없을 때 작동합니다. 내 주요 작업 도구입니다.
Luc Hermitte

12
링크를 제공하는 것은 실제로 답이 아닙니다
Skurpi

3
카오스의 대답은 우수하고 토비아스의 대답에서는 설명이 완료되었습니다.
Avi Cohen

1
링크 대신 컨텐츠를 추가 할 수 있습니까? SO 지침 ...
Błażej Michalik

160
:w !diff % -

4
vimdiff로 이것을 수행하는 방법이 있습니까? 나는 : w! vimdiff %를 시도했지만 성공하지 못했습니다.
Joe J

14
누군가 설명 할 수 있습니까? 무슨 일이 일어나고 있는지 이해할 수 없습니다. 에 문의하는 것으로 알고 있습니다 diff. %현재 열린 파일 경로를 나타냅니다. 이 모든 것이 왜 :w명령에 대한 논쟁 입니까? 또한 -작업 버퍼의 내용에 어떻게 할당됩니까? vim에서 자동입니까, 버퍼의 내용 (또는 버퍼의 특정 범위)이 쉘 명령의 stdin에 할당됩니까?
Nathan Wallace

9
@NathanWallace : :w(on stdin) 명령에 파일을 작성 하기 때문에 논쟁의 여지가 있습니다. 명령에서 -에서 읽도록 지시합니다 stdin.
혼돈

14
또는 :w !git diff % -git이 설치되어 있으면 색상 버전을 사용하십시오 !
Dergachev

5
@Dergachev 내가 fatal: bad flag '-' used after filename실행할 때 오류가 발생합니다 :w !git diff % -.
회색조

100

어떤 사람들은 명령에 대한 설명을 요구했기 때문에

:w !diff % -

더 자세한 답변을 작성하려는 시도는 다음과 같습니다.

나는 당신이 설치되어 cat있고 echo설치된 시스템 (예를 들어, 거의 모든 GNU / Linux, Mac OS, BSD 및 다른 유닉스 계열 시스템)에서 작업하고 있다고 가정합니다 .

위의 명령은 다음과 같이 작동합니다.

  1. vim에 파일을 저장하는 구문은 다음과 같습니다.

    :w <filename>
    
  2. vim에서 쉘 명령을 실행하는 구문은 다음과 같습니다.

    :!<command>
    
  3. vim이 발행 한 셸 환경 %에서 현재 파일 이름을 가리 킵니다. 다음을 실행하여이를 확인할 수 있습니다.

    :!echo %
    

    이것은 파일 이름을 출력해야합니다 (또는 vim이 파일 이름없이 실행 된 경우 오류).

    cat을 사용하여 파일의 내용을 출력 할 수도 있습니다.

    :!cat %
    

    파일 내용을 마지막 저장 상태로 저장하거나 저장하지 않은 경우 오류를 반환해야합니다.

  4. 프로그램 diff는 표준 입력 (stdin)에서 읽을 수 있습니다. 해당 매뉴얼 페이지에는 다음이 나와 있습니다.

    [...] 파일이 '-'인 경우 표준 입력을 읽습니다. [...]

  5. 파일 이름없이 쉘 명령 대신 save 명령을 실행하면 vim은 파일 내용을 실제 파일에 저장하는 대신 쉘의 stdin에 기록합니다. 당신은 이것을 실행하여 이것을 확인할 수 있습니다

    :w !cat
    

    항상 파일에 현재 내용을 인쇄해야합니다 (대신 파일에 기록되었을 것임).

파일 정리 (또는 tl; dr) : 파일이 stdin에 "저장"되고, diff는 파일 이름과 stdin을 입력으로 실행됩니다.

이것을 아는 것은 vimdiff와 파일을 다음과 같이 비교할 수도 있습니다-이것은 당신이 이것을하고 싶지 않은 아이디어 일뿐입니다.

:w !cat > /tmp/tempFile && vimdiff /tmp/tempFile % && rm /tmp/tempFile

(판독 전용이어서 개폐 vimdiff 사용하여 :qall)


vimdiff를 사용하는보다 깔끔한 방법은 다음을 포함하는 쉘 스크립트를 작성하여 vim - -c ":vnew $1 |windo diffthis"실행 가능하게 만들고 예를 들어 PATH에 저장 vimdiffWithStdin한 다음 vim의 다음 명령과 비교하는 것입니다.:w !vimdiffWithStdin %
Tobias Heinicke

더 간단합니다 : :w !vimdiff % /dev/stdin. 창문에 비슷한 속임수가 있는지 모르겠습니다.
deft_code

12

나는 항상 diffchanges를 좋아했습니다. 훌륭하고 간단합니다.


이것은 고도로 공감 된 옵션보다 훨씬 효과적입니다. 이를 통해 전환 할 수 있습니다.
Steven Lu

1
@StevenLu-Meh ... 당신은 무엇을 할 수 있습니까? 어쨌든, 당신이 그것을 좋아해서 기쁘다. 다른 접근법보다 더 실용적입니다.
루크

나, 나는 @Steven을 두 번째로한다. 감사!
AS

동일한 개발자로부터 플러그인으로 설치할 수도 있습니다 : github.com/jmcantrell/vim-diffchanges
Sumanth Lingappa

멋진 플러그인이지만 나중에 만든 패치를 삭제하지 않습니까? 편집 : 내 나쁜! 그렇습니다. 나는 그것을 잘못 사용하고 있었다. 나는을 사용해야했다 :DiffChangesDiffToggle.
aderchox

10

vimrc_example.vim에서 :

" Convenient command to see the difference between the current buffer and the
" file it was loaded from, thus the changes you made.
if !exists(":DiffOrig")
  command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis
          \ | wincmd p | diffthis
endif

... vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig에 설명되어 있습니다 . 이 이상의 장점 w !diff % -이 너무 통한 원격 소스를 작동 (예 : vim sftp://example.com/foo.txt)
Lekensteyn

1
더 나은이 같은 우리는 정력 내부의 차이를 잘 터미널에서 대신 자체 버퍼보기 때문에
니코 벨릭

차이점을 검토 한 후에 어떻게 정상으로 돌아 갑니까?
Niko Bellic

command를 command로 대체하여 if 절을 제거 할 수 있습니다! (: h E174 참조)
elig

@NikoBellic 먼저 ': q'로 "오래된"창 (스크래치 버퍼로 표시)을 닫으십시오. 일반 모드에서 ctrl-W를 두 번 눌러 창 사이를 변경할 수 있습니다. diffoff : 그럼 당신은 작성하여 DIFF을 전환 할 수 있습니다
brunch875

2

다음을 소싱하고 : DIFF 명령을 사용하십시오.

function! s:diff()
    let tmpa = tempname()
    let tmpb = tempname()
    earlier 100h
    exec 'w '.tmpa
    later 100h
    exec 'w '.tmpb
    update
    exec 'tabnew '.tmpa
    diffthis
    vert split
    exec 'edit '.tmpb
    diffthis
endfunction
command! -nargs=0 DIFF call <SID>diff()

2

정확히 당신이 찾고있는 것이 아니라 SCMDiff.vim 이 정말 멋집니다. 한 번의 키 누르기와 소스 컨트롤 리포지토리의 헤드 개정판으로 현재 파일을 강조 표시합니다. 많은 SCMS와 함께 작동합니다. 나는 perforce와 함께 사용합니다.



1

histwin 플러그인을 추천 할 수 있습니다 .

파일 이 현재 저장된 버전의 파일 (다른 답변 과 같음 )과 다르지 않지만 edting을 시작한 이후 변경 사항vimdiff 할 수 있으며 변경 사항을 순서대로 재생할 수도 있습니다. 중간에 저장하면 차이가 표시됩니다.

또한 모든 실행 취소 히스토리 브랜치 의 목록을 표시하고 이들 사이를 전환하거나 비교할 수 있습니다.

추신 : 플러그인은 모든 파일 변경 이후 편집 히스토리에서 모멘트를 자동으로 추적하지는 않지만, 파일을 저장할 때 모멘트를 명시 적으로 "태그"하여 나중에 원할 경우 나중에 파일을 읽을 수 있습니다. 아마도 이것이 자동화 될 수 있습니까?


1

vimdiff에서와 같이 vim을 비교에 사용하려면 다음과 같이 할 수 있습니다.

.vimrc를 편집하고 다음을 추가하십시오.

nmap <F8> :w !vim -M -R - -c ":vnew % \| windo diffthis"<CR><CR>

거기에서 변경 사항을 볼 수 qall있으며 명령 모드에서 F8을 눌러 vimdiff에서와 같이 diff보기를 종료 할 수 있습니다 . F8을 원하는 키로 교체하십시오.

편집 : 저장되지 않았으므로 수정을 허용하지 않기 위해 -M을 추가했습니다.


이 명령은 나를 위해 작동하기 시작합니다. 그러나 아무것도 시도하고 편집하자마자 vim 창이 열광합니다. 입력을 시작하면 화면 양쪽의 vim 단어 뒤에 bash 프롬프트가 나타납니다. 따라서 diff를 표시하는 것처럼 보이지만 vim이 충돌합니다. 또한이 오류가 발생 Vim: Error reading input, exiting...하면 여기에 어떤 문제가 있습니까?
Trevor

@ 트레버 : 문제가 무엇인지 추측 할 수 있습니다. 이처럼 차이점을 수정하면서 실제로 수정하지 않아도됩니다. 따라서 "-M"매개 변수를 추가하여 전체적으로 허용하지 않습니다. 죄송합니다.
Tobias Heinicke

1

git은 다음 명령을 지원합니다

:w !git diff --no-index -- % -

~ / .vimrc에 다음을 추가하여 명령에 매핑하십시오.

command GitDiff execute "w !git diff --no-index -- % -"

이제 실행 :GitDiff은 저장하기 전에 diff를 빠르게 표시하는 편리한 작은 명령이됩니다.


0

vim에서 다음을 사용하여 마지막 백업 및 원본 백업을 만들 수 있습니다.

:set backup
:set patchmode=.orig 

그런 다음 분할하여 열 수 있습니다.

:vsp %:p~ or :vsp %:.orig

그리고 거기에서 :

:vimdiff in each buffer

남은 음식은 없지만 vimdiff를 원한다면 다음과 같이 할 수도 있습니다.

ggVGy    # copy the whole buffer
:vnew    # open a split
CTRL-W w # switch to it
shift-P  # paste at start

그런 다음 각 분할에서 diffthis


0

방금 편집 한 [ buffer ], 즉 마지막 저장된 버전 ( 작업 디렉토리 )과 다른 변경 사항, 마지막 인덱스 버전 ( Git ) 과 다를 수 있습니다 . 나는 둘 다 매핑했다.

" Find diff inbetween currrent buffer and ... A{last index version} vs B{last saved version in working directory}
"  - A{last index version}: the file as you last commited it
    " git diff to vimdiff against the index version of the file:
    nnoremap <leader>gd <Esc>:Gvdiff<CR><Esc>:echo "currentBuffer vs lastIndexVersion (last commited)"<CR>
"  - B{last saved version in working directory}: the file you last :w,
"   not neccesary commited it (not commited for sure if it is in NO git project)
    " https://vim.fandom.com/wiki/Diff_current_buffer_and_the_original_file
    nnoremap <leader>gd2 <Esc>:DiffSaved<CR><Esc>:echo "currentBuffer vs lastSaved (not neccesary equal to last commited)"<CR>
    function! s:DiffWithSaved()
        let filetype=&ft
        diffthis
        vnew | r # | normal! 1Gdd
        diffthis
        exe "setlocal bt=nofile bh=wipe nobl noswf ro ft=" . filetype
    endfunction
    com! DiffSaved call s:DiffWithSaved()

vimdiff와 Gdiff의 예.

  • vimdiff : : vimdiff
  • Gdiff : 그 디프 변경 사항을 커밋하면 Gdiff 만 볼 수 있으며 vimdiff와 동일한 변경 사항이있을 수 있습니다. 변경 사항을 커밋하면 Gdiff 만 볼 수 있으며 vimdiff와 동일한 변경 사항이 있거나 없을 수 있습니다.

또한 vimdiff다른 경로에서 쉽게 homonym 파일을 만들 려면 다음을 수행하십시오.

    " vimdiff homonym file 
   nnoremap <leader>dh  <Esc>:vsplit %:p:h/../__/%:t <bar> :windo diffthis<Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left>
        "E.g."$ vim /path01/proj02_pg064/processorder.php
        ":vsplit %:p:h/../proj01_pg05/%:t | :windo diffthis

1
Gdiff가능한 경우 그리고 그렇지 않으면 (예를 들어 Git 프로젝트가 아닌) 실행하는 하나의 맵을 만든 다음을 수행 할 수 :vimdiff있습니다. 로 try-catch-endtry. 그러나 :DiffWithSavedGit 프로젝트에서 이러한 방식 은 부족합니다.
Xopi García

-2

위의 내용은 내가 좋아하는 git diff를 사용한다고 제안합니다.

:w !git diff  % -
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.