Kann ich Änderungen sehen, bevor ich meine Datei in Vim speichere?

134

Ich benutze Vim. Ich öffne eine Datei. Ich bearbeite es und möchte sehen, was ich bearbeitet habe, bevor ich es speichere.

Wie kann ich das in Vim machen?

teerapap
quelle

Antworten:

57

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

Hier ist eine Funktion und ein Befehl, um einen Unterschied zwischen der aktuell bearbeiteten Datei und ihrer unveränderten Version im Dateisystem festzustellen. Legen Sie dies einfach in Ihrem vimrc oder im Plugin-Verzeichnis ab, öffnen Sie eine Datei, nehmen Sie einige Änderungen vor, ohne sie zu speichern, und tun Sie dies :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()

Um die Diff-Ansicht zu verlassen, können Sie den :diffoffBefehl verwenden.

Unten finden Sie eine ähnliche Funktion, die den 'cvs diff'Befehl nachahmt ...

Bill Lynch
quelle
7
@ luc-hermitte Ist die Alternative nicht :w !diff % -überlegen, wenn Sie vim für eine sich ständig ändernde und große Anzahl von Boxen verwenden, für die Sie die .vimrc nicht einfach ändern können? (Vorausgesetzt, sie haben Diff installiert.)
Thomanski
1
Vim ist nicht das Werkzeug der letzten Hoffnung. Die, die funktioniert, wenn nichts anderes verfügbar ist. Es ist mein Hauptarbeitswerkzeug.
Luc Hermitte
12
Nur einen Link
anzugeben
3
Chaos 'Antwort ist überlegen und in Tobias' Antwort ist die Erklärung vollständig.
Avi Cohen
1
Können Sie bitte statt nur eines Links Inhalte hinzufügen? SO Richtlinien ...
Błażej Michalik
160
:w !diff % -
Chaos
quelle
4
Gibt es eine Möglichkeit, dies mit vimdiff zu tun? Ich habe versucht: w! Vimdiff% - aber ohne Erfolg.
Joe J
14
Kann das jemand erklären? Ich verstehe nicht, was passiert. Ich verstehe, dass Sie beschießen diff. %verweist auf den aktuell geöffneten Dateipfad. Warum ist das alles ein Argument für den :wBefehl? Wie wird -der Inhalt des Arbeitspuffers zugewiesen? Ist das in vim automatisch, dass der Inhalt des Puffers (oder vielleicht ein bestimmter Bereich im Puffer) stdin für Shell-Befehle zugewiesen wird?
Nathan Wallace
9
@ NathanWallace: Es ist ein Argument dafür, :wweil wir die Datei in den Befehl (on stdin) schreiben . -Weist es im Befehl an, aus zu lesen stdin.
Chaos
14
Oder verwenden Sie :w !git diff % -für eine kolorierte Version, wenn Sie Git installiert haben!
Dergachev
5
@Derachev Ich erhalte den Fehler, fatal: bad flag '-' used after filenamewenn ich laufe :w !git diff % -.
Graustufen
100

Weil einige Leute nach einer Erklärung für den Befehl fragten

:w !diff % -

Hier ist mein Versuch, eine detailliertere Antwort zu schreiben:

Ich gehe davon aus, dass Sie an einem System arbeiten, auf dem installiert catund echoinstalliert ist (z. B. fast alle GNU / Linux-, Mac OS-, BSD- und andere UNIX-ähnliche Systeme).

Der obige Befehl funktioniert wie folgt:

  1. Die Syntax zum Speichern einer Datei in vim lautet:

    :w <filename>
    
  2. Die Syntax zum Ausführen eines Shell-Befehls in vim lautet:

    :!<command>
    
  3. In der von vim ausgegebenen Shell-Umgebung wird %zufällig auf den aktuellen Dateinamen verwiesen. Sie können dies überprüfen, indem Sie Folgendes ausführen:

    :!echo %
    

    Dies sollte den Dateinamen ausgeben (oder einen Fehler, wenn vim ohne Dateinamen ausgeführt wurde).

    Mit cat können wir auch den Inhalt der Datei ausgeben:

    :!cat %
    

    Dies sollte den Dateiinhalt in seinem zuletzt gespeicherten Zustand oder einen Fehler zurückgeben, wenn er noch nie gespeichert wurde.

  4. Das Programmdiff kann von der Standardeingabe (stdin) lesen. Die Manpage enthält Folgendes:

    [...] Wenn eine DATEI '-' ist, lesen Sie die Standardeingabe. [...]

  5. Wenn Sie den Befehl save ohne Dateinamen, sondern mit einem dahinter stehenden Shell-Befehl ausführen, schreibt vim den Dateiinhalt in stdin der Shell, anstatt ihn in einer physischen Datei zu speichern. Sie können dies überprüfen, indem Sie ausführen

    :w !cat
    

    Dies sollte immer den aktuellen Inhalt der Dateien drucken (der stattdessen in eine Datei geschrieben worden wäre).

Zusammenfügen (oder tl; dr): Die Datei wird in stdin "gespeichert", diff wird mit dem Dateinamen und stdin als Eingabe ausgeführt.

Wenn Sie dies wissen, können Sie auch Dateien mit vimdiff vergleichen, die so etwas tun - dies ist nur eine Idee, die Sie nicht tun möchten:

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

(Dann schreibgeschützt öffnen und vimdiff mit schließen :qall)

Tobias Heinicke
quelle
Ein vernünftigerer Ansatz zur Verwendung von vimdiff wäre, ein Shell-Skript zu erstellen, das Folgendes enthält vim - -c ":vnew $1 |windo diffthis", es ausführbar zu machen, es beispielsweise im PATH zu speichern vimdiffWithStdinund dann mit dem folgenden Befehl in vim zu vergleichen::w !vimdiffWithStdin %
Tobias Heinicke
Noch einfacher : :w !vimdiff % /dev/stdin. Ich weiß nicht, ob es einen ähnlichen Trick für Windows gibt.
Deft_code
11

Ich mag immer Diffchanges - nett, einfach, funktioniert.

Turm
quelle
Dies funktioniert viel besser als die höher bewerteten Optionen. Dies gibt die Möglichkeit, es umzuschalten.
Steven Lu
1
@StevenLu - Meh ... was kannst du tun? Auf jeden Fall froh, dass es dir gefällt. Ich finde es praktischer als den anderen Ansatz.
Turm
Ich mache das zweite @Steven, Ihre vorgeschlagenen Diffchanges sind ausgezeichnet. Vielen Dank!
AS
Dies kann auch als Plugin vom selben Entwickler installiert werden: github.com/jmcantrell/vim-diffchanges
Sumanth Lingappa
10

von 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
0x89
quelle
... wie unter vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig dokumentiert . Vorteil dieses über w !diff % -ist , dass es über Remote - Quellen auch funktioniert (zB vim sftp://example.com/foo.txt)
Lekensteyn
1
Ich mag das besser, weil wir den Unterschied direkt im Vim-Puffer selbst sehen, anstatt in einem Terminal
Niko Bellic
Wie kehren Sie zur Normalität zurück, wenn Sie die Unterschiede untersucht haben?
Niko Bellic
Sie können die if-Klausel entfernen, indem Sie den Befehl durch den Befehl ersetzen! (siehe: h E174)
Elig
@NikoBellic Schließen Sie zuerst das "alte" Fenster (als Arbeitspuffer markiert) mit ': q'. Sie können zwischen den Fenstern wechseln, indem Sie im normalen Modus zweimal auf Strg-W tippen. Dann können Sie diff ausschalten, indem Sie schreiben: diffoff
brunch875
2

Geben Sie Folgendes ein und verwenden Sie den Befehl: 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()
Mykola Golubyev
quelle
2

Nicht genau das, wonach Sie suchen, aber SCMDiff.vim ist wirklich cool. Ein Tastendruck, und es hebt Ihre aktuelle Datei mit der Kopfrevision in einem Versionsverwaltungs-Repo hervor. Es soll mit vielen SCMS funktionieren. Ich benutze es notgedrungen.

Prestomation
quelle
2

Hier gibt es ein Plugin, das auf unterschiedlichen Antworten basiert: https://github.com/gangleri/vim-diffsaved

Es bietet die :w !diff % -Methode und die involviertere diffthis.

Abgesehen davon erlaubt undotree dies auch, aber auch viel mehr (unterscheidet sich zwischen verschiedenen Rückgängig-Checkpoints). Ähnlich wie bei Gundo .

blau gefärbt
quelle
1

Ich kann das empfehlen Histwin Plugin .

Es unterscheidet sich zwar nicht von der aktuell gespeicherten Version der Datei (wie die anderen Antworten), kann jedoch Änderungen seit Beginn der Bearbeitung und sogar vimdiff wiederholen , um die Änderungen in Ordnung. Der Unterschied zeigt, ob Sie zwischenzeitlich speichern.

Zusätzlich wird eine Liste von angezeigt aller Rückgängig-Verlaufszweige und Sie können zwischen ihnen wechseln oder unterscheiden.

PS: Während das Plugin seit jeder Dateiänderung nicht automatisch Momente im Bearbeitungsverlauf verfolgt, können Sie den Moment, in dem Sie die Datei speichern, explizit "markieren", damit Sie später damit vimdiff können, wenn Sie dies möchten. Vielleicht könnte dies automatisiert werden?

catchmeifyoutry
quelle
1

Wenn Sie vim zum Vergleich wie in vimdiff verwenden möchten, können Sie Folgendes tun:

Bearbeiten Sie Ihre .vimrc und fügen Sie hinzu:

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

Von dort aus sehen Sie Ihre Änderungen und können die Diff-Ansicht mit beenden qall like in vimdiff im Befehlsmodus F8 drücken. Ersetzen Sie F8 durch eine beliebige Taste.

Bearbeiten: -M hinzugefügt, um Änderungen zu verbieten, da diese nicht gespeichert werden.

Tobias Heinicke
quelle
Dieser Befehl beginnt für mich zu funktionieren und zeigt mir den Unterschied nebeneinander. Sobald ich jedoch versuche, etwas zu bearbeiten, wird das Vim-Fenster verrückt. Ich beginne zu tippen und erhalte eine Bash-Eingabeaufforderung hinter den Wörtern in vim auf beiden Seiten des Bildschirms. Es scheint also das Diff anzuzeigen, aber dann stürzt vim ab. Außerdem bekomme ich bei diesem Fehler Vim: Error reading input, exiting...irgendwelche Ideen, was hier falsch läuft?
Trevor
@ Trevor: Ich konnte nur raten, was die Probleme sind. Es ist in der Tat nicht sicher, Änderungen vorzunehmen, während Sie sich so unterscheiden. Daher habe ich den Parameter "-M" hinzugefügt, um ihn vollständig zu verbieten. Es tut uns leid.
Tobias Heinicke
1

git unterstützt den folgenden Befehl

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

Ordnen Sie es einem Befehl zu, indem Sie Folgendes zu Ihrem ~ / .vimrc hinzufügen

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

Jetzt ausführen :GitDiff zu einem praktischen kleinen Befehl, um den Unterschied vor jedem Speichern schnell anzuzeigen.

CyclicUniverse
quelle
0

Sie können vim dazu bringen, ein letztes Backup und ein Original-Backup zu erstellen mit:

:set backup
:set patchmode=.orig 

Danach können Sie sie in einem Split öffnen:

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

Und von dort aus:

:vimdiff in each buffer

Wenn Sie keine Reste mehr haben, aber Vimdiff wollen, können Sie auch Folgendes tun:

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

und dann: differfthis bei jedem Split

Chipfall
quelle
0

Änderungen, die Sie gerade bearbeitet haben [ Puffer ], dh diejenigen, die sich von der zuletzt gespeicherten Version (im Arbeitsverzeichnis ) unterscheiden, können sich von der letzten Indexversion ( Git ) unterscheiden. Ich habe beide abgebildet:

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

Beispiel von vimdiff vs Gdiff.

  • vimdiff: : vimdiff
  • Gdiff: Gdiff Wenn Sie Änderungen vornehmen, sehen Sie nur Gdiff, was möglicherweise oder möglicherweise dieselben Änderungen wie vimdiff hat: Wenn Sie Änderungen vornehmen, sehen Sie nur Gdiff, was möglicherweise dieselben Änderungen wie vimdiff aufweist oder NICHT

Darüber hinaus zu einfachen vimdiffHomonym-Datei in anderen Pfad:

    " 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
Xopi García
quelle
1
Man könnte einfach 1 Map erstellen, die ausgeführt wird: a Gdiffwenn möglich und ansonsten (zB kein Git-Projekt) dann a ausführen :vimdiff. Mit try-catch-endtry. Aber so :DiffWithSavedfehlt es in einem Git-Projekt.
Xopi García
-2

Befolgen Sie die obigen Vorschläge, dass ich Git Diff verwende, das mir sehr gefällt:

:w !git diff  % -
Alex
quelle