Tôi có thể thấy các thay đổi trước khi tôi lưu tệp của mình trong Vim không?


134

Tôi sử dụng Vim. Tôi mở một tập tin. Tôi chỉnh sửa nó và tôi muốn xem những gì tôi đã chỉnh sửa trước khi tôi lưu nó.

Làm thế nào tôi có thể làm điều này trong Vim?

Câu trả lời:


57

http://vim.wikia.com/wiki/Diff_cản_buffer_and_the_origen_file

Dưới đây là một chức năng và lệnh để xem sự khác biệt giữa tệp hiện đang được chỉnh sửa và phiên bản chưa sửa đổi của nó trong hệ thống tệp. Chỉ cần đặt cái này trong vimrc của bạn hoặc trong thư mục plugin, mở tệp, thực hiện một số sửa đổi mà không lưu chúng và thực hiện :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()

Để thoát khỏi chế độ xem khác nhau, bạn có thể sử dụng :diffofflệnh.

Dưới đây là một chức năng tương tự, được điều chỉnh để bắt chước 'cvs diff'lệnh ...


7
@ luc-hermitte Không phải là :w !diff % -cấp trên thay thế khi bạn đang sử dụng vim trên một số lượng lớn các hộp mà bạn không thể dễ dàng thay đổi .vimrc? (Miễn là họ đã cài đặt diff.)
thomanski

1
Vim không phải là công cụ của hy vọng cuối cùng. Một trong đó sẽ làm việc khi không có gì khác có sẵn. Nó là công cụ làm việc chính của tôi.
Luc Hermitte

12
Chỉ cung cấp một liên kết không thực sự là một câu trả lời
Skurpi

3
Câu trả lời của Chaos là vượt trội và trong câu trả lời của Tobias, lời giải thích đã hoàn tất.
Avi Cohen

1
Bạn có thể vui lòng thêm một số nội dung thay vì chỉ là một liên kết? Hướng dẫn SO ...
Błażej Michalik

160
:w !diff % -

4
Có cách nào để làm điều này với vimdiff không? Tôi đã thử: w! Vimdiff% - nhưng không thành công.
Joe J

14
Ai đó có thể giải thích điều đó? Tôi không hiểu chuyện gì đang xảy ra. Tôi hiểu bạn đang pháo kích ra diff. %đề cập đến filepath hiện đang mở. Tại sao tất cả điều này là một đối số cho :wlệnh? Ngoài ra, làm thế nào để -được gán cho nội dung của bộ đệm làm việc? Là tự động trong vim, rằng nội dung của bộ đệm (hoặc có thể là một phạm vi cụ thể trong bộ đệm) được gán cho stdin cho các lệnh shell?
Nathan Wallace

9
@NathanWallace: Đó là một đối số :wbởi vì chúng tôi đang viết tệp vào lệnh (bật stdin). Trong lệnh, -bảo nó đọc từ stdin.
hỗn loạn

14
Hoặc sử dụng :w !git diff % -cho phiên bản màu, nếu bạn đã cài đặt git!
Dergachev

5
@Dergachev Tôi gặp lỗi fatal: bad flag '-' used after filenamekhi chạy :w !git diff % -.
Grayscale

100

Bởi vì một số người hỏi về một lời giải thích cho lệnh

:w !diff % -

Đây là nỗ lực của tôi để viết một câu trả lời chi tiết hơn:

Tôi giả sử rằng bạn đang làm việc trên một hệ thống với catecho cài đặt và cài đặt (ví dụ như hầu hết mọi GNU / Linux, Mac OS, BSD và các hệ thống tương tự UNIX khác).

Lệnh trên hoạt động như sau:

  1. Cú pháp lưu tệp trong vim là:

    :w <filename>
    
  2. Cú pháp để thực thi lệnh shell trong vim là:

    :!<command>
    
  3. Bên trong môi trường shell do vim phát hành %sẽ trỏ đến tên tệp hiện tại. Bạn có thể xác minh điều này bằng cách thực hiện như sau:

    :!echo %
    

    Điều này sẽ xuất tên tệp (hoặc một lỗi, nếu vim đã chạy mà không có tên tệp).

    Sử dụng cat chúng ta cũng có thể xuất nội dung của tệp:

    :!cat %
    

    Điều này sẽ trả về nội dung tệp ở trạng thái lưu cuối cùng của nó hoặc lỗi nếu nó chưa bao giờ được lưu.

  4. Chương trình diff có thể đọc từ đầu vào tiêu chuẩn (stdin). Trang người đàn ông của nó nêu như sau:

    [...] Nếu TẬP TIN là '-', hãy đọc đầu vào tiêu chuẩn. [...]

  5. Thực thi lệnh save mà không có tên tệp mà thay vào đó là lệnh shell đằng sau nó khiến vim ghi nội dung tệp vào stdin của shell thay vì lưu nó trong tệp vật lý. Bạn có thể xác minh điều này bằng cách thực hiện

    :w !cat
    

    Điều này sẽ luôn luôn in các tập tin nội dung hiện tại (mà sẽ được ghi vào một tập tin thay thế).

Đặt nó cùng nhau (hoặc tl; dr): Tệp được "lưu" vào stdin, diff được chạy với tên tệp và stdin làm đầu vào.

Biết điều này cũng có thể so sánh các tệp với vimdiff đang làm một cái gì đó như thế này - đây chỉ là một ý tưởng bạn không muốn làm điều này:

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

(Sau đó mở chỉ đọc và đóng vimdiff bằng cách sử dụng :qall)


Một cách tiếp cận lành mạnh hơn để sử dụng vimdiff sẽ tạo ra một tập lệnh shell chứa các phần sau vim - -c ":vnew $1 |windo diffthis", làm cho nó có thể thực thi được, ví dụ như lưu nó trong PATH vimdiffWithStdinvà sau đó so sánh với lệnh sau trong vim::w !vimdiffWithStdin %
Tobias Heinicke

Thậm chí đơn giản hơn : :w !vimdiff % /dev/stdin. Tôi không biết nếu một thủ thuật tương tự tồn tại cho các cửa sổ.
deft_code 30/03/2015

11

Tôi luôn thích sự khác biệt - công việc tốt, đơn giản.


Điều này hoạt động rất nhiều so với các tùy chọn nâng cao hơn. Điều này cho khả năng chuyển đổi nó.
Steven Lu

1
@StevenLu - Meh ... bạn có thể làm gì? Trong mọi trường hợp, vui mừng bạn thích nó. Tôi thấy nó thực tế hơn các phương pháp khác.
Rook

Tôi, tôi làm thứ hai @Steven, sự thay đổi được đề xuất của bạn là tuyệt vời. Cảm ơn!
NHƯ

Điều này cũng có thể được cài đặt như một plugin từ cùng một nhà phát triển: github.com/jmcantrell/vim-diffchanges
Sumanth Lingappa

10

từ 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

... Như tài liệu tại vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig . Ưu điểm của việc này w !diff % -là nó cũng hoạt động trên các nguồn từ xa (ví dụ vim sftp://example.com/foo.txt:)
Lekensteyn

1
Tôi thích điều này hơn vì chúng tôi thấy sự khác biệt ngay bên trong bộ đệm vim thay vì trong một thiết bị đầu cuối
Niko Bellic

Làm thế nào để bạn trở lại bình thường một khi bạn đã hoàn thành việc kiểm tra sự khác biệt?
Niko Bellic

Bạn có thể thoát khỏi mệnh đề if bằng cách thay thế lệnh bằng lệnh! (xem: h E174)
elig

@NikoBellic Trước tiên hãy đóng cửa sổ "cũ" (được đánh dấu là bộ đệm đầu) với ': q'. Bạn có thể thay đổi giữa các cửa sổ bằng cách nhấn ctrl-W hai lần trong khi ở chế độ bình thường. Sau đó, bạn có thể tắt diff bằng cách viết: diffoff
brunch875

2

Nguồn sau đây và sử dụng: lệnh 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

Không chính xác những gì bạn đang tìm kiếm nhưng SCMDiff.vim thực sự tuyệt vời. Một phím bấm và nó làm nổi bật tệp hiện tại của bạn với sửa đổi đầu trong một repo kiểm soát nguồn. Nó có nghĩa là để làm việc với nhiều SCMS. Tôi sử dụng nó với lực lượng.


2

Có một plugin, dựa trên các câu trả lời khác nhau ở đây: https://github.com/gangleri/vim-diffsatted

Nó cung cấp :w !diff % -phương thức và liên quan nhiều hơn diffthismột.

Ngoài ra, undotree cũng cho phép điều này, nhưng cũng nhiều hơn nữa (khác nhau giữa các điểm kiểm tra hoàn tác khác nhau). Tương tự như Gundo .


1

Tôi có thể giới thiệu histwin plugin .

Mặc dù nó không khác với phiên bản đã lưu hiện tại của tệp (giống như các câu trả lời khác), nhưng nó có thể thay đổi vimdiff kể từ khi bạn bắt đầu chỉnh sửa và thậm chí phát lại các thay đổi của bạn theo thứ tự. Sự khác biệt cho thấy nếu bạn tiết kiệm trung gian.

Ngoài ra, nó sẽ hiển thị một danh sách tất cả các nhánh lịch sử hoàn tác và cho phép bạn chuyển đổi hoặc khác biệt giữa chúng.

PS: Mặc dù plugin không tự động theo dõi các khoảnh khắc trong lịch sử chỉnh sửa vì mỗi lần thay đổi tệp, bạn có thể "gắn thẻ" rõ ràng thời điểm khi bạn lưu tệp để sau này bạn có thể vimdiff với nó, nếu bạn muốn điều đó. Có lẽ điều này có thể được tự động?


1

Nếu bạn muốn sử dụng vim để so sánh như trong vimdiff, bạn có thể làm một cái gì đó như thế này:

Chỉnh sửa .vimrc của bạn và thêm:

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

Từ đó, bạn sẽ thấy các thay đổi của mình và có thể thoát khỏi chế độ xem khác bằng cách sử dụng qalllike trong vimdiff bằng cách nhấn F8 trong chế độ lệnh. Thay thế F8 bằng bất kỳ phím nào bạn thích.

Chỉnh sửa: Đã thêm -M để không cho phép bất kỳ sửa đổi nào, vì nó không được lưu.


Lệnh này bắt đầu làm việc cho tôi, nó cho tôi thấy sự khác biệt bên cạnh nhau. Tuy nhiên, ngay khi tôi cố gắng chỉnh sửa bất cứ thứ gì, cửa sổ vim sẽ phát điên. Tôi bắt đầu gõ và tôi nhận được một dấu nhắc bash đằng sau các từ trong vim ở hai bên màn hình. Vì vậy, nó dường như hiển thị diff, nhưng sau đó vim gặp sự cố. Ngoài ra, tôi nhận được lỗi này Vim: Error reading input, exiting...bất kỳ ý tưởng những gì đang xảy ra ở đây?
Trevor

@Trevor: Tôi chỉ có thể đoán vấn đề là gì. Nó thực sự không lưu để thực hiện bất kỳ sửa đổi trong khi khác nhau như thế này. Do đó tôi đã thêm tham số "-M" để không cho phép hoàn toàn. Lấy làm tiếc.
Tobias Heinicke

1

git hỗ trợ lệnh sau

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

ánh xạ nó tới một lệnh bằng cách thêm đoạn mã sau vào ~ / .vimrc của bạn

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

Bây giờ thực thi :GitDifftrở thành một lệnh nhỏ tiện dụng để nhanh chóng hiển thị khác biệt trước mỗi lần lưu.


0

Bạn có thể tạo vim tạo bản sao lưu cuối cùng và bản sao lưu gốc bằng:

:set backup
:set patchmode=.orig 

Sau đó, bạn có thể mở chúng trong một tách:

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

Và từ đó làm:

:vimdiff in each buffer

Nếu bạn chết không có thức ăn thừa nhưng muốn vimdiff, bạn cũng có thể làm:

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

và sau đó làm: diffthis trên mỗi phân chia


0

Những thay đổi bạn vừa chỉnh sửa [ bộ đệm ], tức là những thay đổi khác với phiên bản đã lưu trước đó (trong thư mục dir hoạt động), những thay đổi này có thể khác với phiên bản chỉ mục cuối cùng ( Git ). Tôi đã ánh xạ cả hai:

" 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()

Ví dụ về vimdiff vs Gdiff.

  • vimdiff: : vimdiff
  • Gdiff: Cảnh sát Cam kết thay đổi, bạn chỉ thấy Gdiff, những gì có thể hoặc có thể có những thay đổi tương tự như vimdiff: cam kết thay đổi, bạn chỉ thấy Gdiff, những gì có thể hoặc có thể KHÔNG có những thay đổi tương tự như vimdiff

Hơn nữa, để vimdifftập tin đồng âm dễ dàng trong đường dẫn khác:

    " 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
Người ta chỉ có thể tạo 1 bản đồ thực thi: a Gdiffnếu có thể và nếu không (ví dụ không phải là dự án Git) thì thực hiện a :vimdiff. Với try-catch-endtry. Nhưng cách này :DiffWithSavedtrong một dự án Git là thiếu.
Xopi García

-2

Thực hiện theo các gợi ý trên tôi sử dụng git diff mà tôi thích nhiều:

:w !git diff  % -
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.