Posso vedere le modifiche prima di salvare il mio file in Vim?


135

Io uso Vim. Apro un file. Lo modifico e voglio vedere cosa ho modificato prima di salvarlo.

Come posso farlo in Vim?

Risposte:


57

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

Ecco una funzione e un comando per vedere una differenza tra il file attualmente modificato e la sua versione non modificata nel filesystem. Inseriscilo nel tuo vimrc o nella directory dei plugin, apri un file, apporta alcune modifiche senza salvarle, ed esegui :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()

Per uscire dalla visualizzazione diff è possibile utilizzare il :diffoffcomando.

Di seguito è una funzione simile, adattata per imitare il 'cvs diff'comando ...


7
@ luc-hermitte L'alternativa non è :w !diff % -superiore quando usi vim su un numero sempre crescente di scatole per le quali non puoi facilmente cambiare il .vimrc? (A condizione che abbiano installato diff.)
Thomann

1
Vim non è lo strumento dell'ultima speranza. Quello che funzionerà quando non è disponibile nient'altro. È il mio principale strumento di lavoro.
Luc Hermitte,

12

3
La risposta del caos è superiore e nella risposta di Tobias la spiegazione è completa.
Avi Cohen,

1
Puoi per favore aggiungere un po 'di contenuto anziché solo un link? Linee guida SO ...
Błażej Michalik

160
:w !diff % -

4
C'è un modo per farlo con vimdiff? Ho provato: w! Vimdiff% - ma senza successo.
Joe J,

14
Qualcuno può spiegarlo? Non capisco cosa sta succedendo. Capisco che stai sborsando diff. %si riferisce al percorso file attualmente aperto. Perché tutto ciò è un argomento per il :wcomando? Inoltre, come -viene assegnato al contenuto del buffer di lavoro? È automatico in vim che il contenuto del buffer (o forse un intervallo specifico nel buffer) venga assegnato a stdin per i comandi della shell?
Nathan Wallace,

9
@NathanWallace: è un argomento :wperché stiamo scrivendo il file sul comando (on stdin). Nel comando, -dice di leggere da stdin.
caos,

14
Oppure usa :w !git diff % -per una versione colorata, se hai installato git!
Dergachev,

5
@Dergachev Ottengo l'errore fatal: bad flag '-' used after filenamequando corro :w !git diff % -.
Scala di grigi,

100

Perché alcune persone hanno chiesto una spiegazione per il comando

:w !diff % -

Ecco il mio tentativo di scrivere una risposta più dettagliata:

Presumo che tu stia lavorando su un sistema con cate echoinstallato (ad esempio quasi tutti i sistemi GNU / Linux, Mac OS, BSD e altri sistemi simili a UNIX).

Il comando sopra funziona come segue:

  1. La sintassi per il salvataggio di un file in vim è:

    :w <filename>
    
  2. La sintassi per l'esecuzione di un comando shell in vim è:

    :!<command>
    
  3. All'interno dell'ambiente shell emesso da vim %sembra puntare al nome file corrente. Puoi verificarlo eseguendo quanto segue:

    :!echo %
    

    Questo dovrebbe generare il nome del file (o un errore, se vim è stato eseguito senza un nome file).

    Usando cat possiamo anche generare il contenuto del file:

    :!cat %
    

    Ciò dovrebbe restituire il contenuto dei file nell'ultimo stato salvato o un errore se non è mai stato salvato.

  4. Il programma diff è in grado di leggere dallo standard input (stdin). La sua pagina man indica quanto segue:

    [...] Se un FILE è '-', leggi l'input standard. [...]

  5. L'esecuzione del comando save senza un nome file ma piuttosto un comando shell dietro di esso fa sì che vim scriva il contenuto dei file sullo stdin della shell invece di salvarlo in un file fisico. Puoi verificarlo eseguendo

    :w !cat
    

    Questo dovrebbe sempre stampare il contenuto corrente dei file (che sarebbe stato invece scritto in un file).

Mettendolo insieme (o tl; dr): il file viene "salvato" su stdin, diff viene eseguito con il nome file e stdin come input.

Sapendo che questo potrebbe anche confrontare i file con vimdiff facendo qualcosa del genere - questa è solo un'idea che non vuoi fare questo:

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

(Quindi apri di sola lettura e chiudi vimdiff usando :qall)


Un approccio più sano per usare vimdiff sarebbe la creazione di uno script di shell contenente quanto segue vim - -c ":vnew $1 |windo diffthis", rendendolo eseguibile, salvandolo nel PERCORSO come ad esempio vimdiffWithStdine confrontandolo con il seguente comando in vim::w !vimdiffWithStdin %
Tobias Heinicke

Ancora più semplice: :w !vimdiff % /dev/stdin. Non so se esiste un trucco simile per Windows.
deft_code

12

Mi piacciono sempre i cambi : piacevoli, semplici, funziona.


Funziona MOLTO meglio delle opzioni più votate. Questo dà la possibilità di attivarlo.
Steven Lu,

1
@StevenLu - Meh ... cosa puoi fare? In ogni caso, felice che ti piaccia. Lo trovo più pratico dell'altro approccio.
Rook,

Io faccio il secondo @Steven, i tuoi cambi di suggerimento suggeriti sono eccellenti. Grazie!
AS

Questo può anche essere installato come plugin dallo stesso sviluppatore: github.com/jmcantrell/vim-diffchanges
Sumanth Lingappa

bel plugin, ma non cancella la patch che crea in seguito? Modifica: Mio cattivo! Lo fa. Lo stavo usando nel modo sbagliato. Ho dovuto usare :DiffChangesDiffToggle.
aderchox

10

da 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

... come documentato su vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig . Vantaggio di questo corso w !diff % -è che funziona fonti oltre a distanza troppo (ad esempio: vim sftp://example.com/foo.txt)
Lekensteyn

1
Mi piace di più perché vediamo la differenza proprio all'interno del buffer vim stesso anziché in un terminale
Niko Bellic,

Come si torna alla normalità dopo aver esaminato le differenze?
Niko Bellic,

È possibile eliminare la clausola if sostituendo comando con comando! (vedi: h E174)
idoneità

@NikoBellic Per prima cosa chiudere la "vecchia" finestra (contrassegnata come buffer di memoria virtuale) con ': q'. Puoi passare da una finestra all'altra toccando due volte ctrl-W mentre sei in modalità normale. Quindi puoi disattivare diff scrivendo: diffoff
brunch875 il

2

Sorgere il seguente e utilizzare: DIFF command

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

Non è esattamente quello che stai cercando, ma SCMDiff.vim è davvero interessante. Un tasto premuto, e diff-evidenzia il tuo file corrente con la revisione principale in un repository di controllo del codice sorgente. È pensato per funzionare con molti SCMS. Lo uso con forza.



1

Posso consigliare il plugin histwin .

Sebbene non differisca dall'attuale versione salvata del file (come le altre risposte), può vimdiff le modifiche da quando hai iniziato a modificare e persino riprodurre le modifiche in ordine. La differenza mostra se si salva in modo intermittente.

Inoltre, visualizza un elenco di tutti i rami della cronologia degli annullamenti e consente di alternare o diff.

PS: Sebbene il plug-in non tenga traccia automaticamente dei momenti nella cronologia delle modifiche da quando cambia ogni file, puoi esplicitamente "taggare" il momento in cui salvi il file in modo tale da poterlo successivamente vimdiff, se lo desideri. Forse questo potrebbe essere automatizzato?


1

Se vuoi usare vim per il confronto come in vimdiff, potresti fare qualcosa del genere:

Modifica il tuo .vimrc e aggiungi:

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

Da lì in poi vedrai le tue modifiche e potrai uscire dalla vista diff usando qall like in vimdiff premendo F8 in modalità comando. Sostituisci F8 con qualsiasi chiave che ti piace.

Modifica: aggiunto -M per non consentire alcuna modifica, perché non viene salvata.


Questo comando inizia a funzionare per me, mi mostra la differenza fianco a fianco. Tuttavia, non appena provo a modificare qualcosa, la finestra di VIM diventa pazza. Comincio a digitare e ricevo un prompt bash dietro le parole in vim su entrambi i lati dello schermo. Quindi sembra mostrare il diff, ma poi vim si arresta in modo anomalo. Inoltre, ricevo questo errore Vim: Error reading input, exiting...qualche idea di cosa non va qui?
Trevor,

@Trevor: potrei solo indovinare quali sono i problemi. In effetti, non è necessario apportare modifiche mentre si differenzia in questo modo. Quindi ho aggiunto il parametro "-M" per non consentirlo del tutto. Scusate.
Tobias Heinicke,

1

git supporta il seguente comando

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

mappalo a un comando aggiungendo quanto segue al tuo ~ / .vimrc

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

Ora l'esecuzione :GitDiffdiventa un piccolo comando utile per mostrare rapidamente il diff prima di ogni salvataggio.


0

Puoi fare in modo che vim crei un ultimo backup e un backup originale con:

:set backup
:set patchmode=.orig 

Successivamente, puoi aprirli in una divisione:

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

E da lì fai:

:vimdiff in each buffer

Se sei morto senza avanzi ma vuoi vimdiff, puoi anche fare:

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

e poi fai: diffthis su ogni divisione


0

Le modifiche appena modificate [ buffer ], ovvero quelle che differiscono dall'ultima versione salvata (nella directory di lavoro ), potrebbero differire dall'ultima versione dell'indice ( Git ). Ho mappato entrambi:

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

Esempio di vimdiff vs Gdiff.

  • vimdiff: : vimdiff
  • Gdiff: Gdiff Commettendo modifiche, vedi solo Gdiff, cosa potrebbe o potrebbe avere le stesse modifiche di vimdiff: commettendo modifiche, vedi solo Gdiff, cosa potrebbe o potrebbe NON avere le stesse modifiche di vimdiff

Inoltre, per semplificare il vimdifffile omonimo in un altro percorso:

    " 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
Si potrebbe semplicemente creare 1 mappa che viene eseguita: a Gdiffse possibile e altrimenti (es. Non un progetto Git) quindi eseguire a :vimdiff. Con try-catch-endtry. Ma in questo modo :DiffWithSavedin un progetto Git manca.
Xopi García,

-2

Seguire i suggerimenti di cui sopra che uso git diff che mi piace molto:

:w !git diff  % -
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.