Puis-je voir les modifications avant d'enregistrer mon fichier dans Vim?


135

J'utilise Vim. J'ouvre un dossier. Je le modifie et je veux voir ce que j'ai modifié avant de l'enregistrer.

Comment puis-je faire cela dans Vim?

Réponses:


57

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

Voici une fonction et une commande pour voir une différence entre le fichier actuellement édité et sa version non modifiée dans le système de fichiers. Mettez-le simplement dans votre vimrc ou dans le répertoire du plugin, ouvrez un fichier, faites quelques modifications sans les enregistrer, et faites-le :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()

Pour sortir de la vue diff, vous pouvez utiliser la :diffoffcommande.

Voici une fonction similaire, adaptée pour imiter la 'cvs diff'commande ...


7
@ luc-hermitte L'alternative n'est-elle pas :w !diff % -supérieure lorsque vous utilisez vim sur un grand nombre de boîtes en constante évolution pour lesquelles vous ne pouvez pas facilement changer le .vimrc? (À condition qu'ils aient installé un diff.)
thomanski

1
Vim n'est pas l'outil du dernier espoir. Celui qui fonctionnera quand rien d'autre n'est disponible. C'est mon principal outil de travail.
Luc Hermitte

12
Fournir simplement un lien n'est pas vraiment une réponse
Skurpi

3
La réponse de Chaos est supérieure et dans la réponse de Tobias, l'explication est complète.
Avi Cohen le

1
Pouvez-vous s'il vous plaît ajouter du contenu au lieu d'un simple lien? SO guidelines ...
Błażej Michalik

160
:w !diff % -

4
Existe-t-il un moyen de faire cela avec vimdiff? J'ai essayé: w! Vimdiff% - mais sans succès.
Joe J

14
Quelqu'un peut-il expliquer cela? Je ne comprends pas ce qui se passe. Je comprends que vous vous lancez diff. %fait référence au chemin de fichier actuellement ouvert. Pourquoi tout cela est-il un argument de la :wcommande? Aussi, comment est- -il affecté au contenu du tampon de travail? Est-ce automatique dans vim, que le contenu du tampon (ou peut-être une plage spécifique dans le tampon) soit affecté à stdin pour les commandes shell?
Nathan Wallace

9
@NathanWallace: C'est un argument de :wparce que nous écrivons le fichier dans la commande (on stdin). Dans la commande, lui -dit de lire à partir de stdin.
chaos

14
Ou utilisez :w !git diff % -pour une version colorisée, si vous avez installé git!
Dergachev

5
@Dergachev J'obtiens l'erreur fatal: bad flag '-' used after filenamelorsque je cours :w !git diff % -.
Niveaux de gris

100

Parce que certaines personnes ont demandé une explication pour la commande

:w !diff % -

Voici ma tentative d'écrire une réponse plus détaillée:

Je suppose que vous travaillez sur un système avec catet echoinstallé (par exemple presque tous les systèmes GNU / Linux, Mac OS, BSD et autres systèmes de type UNIX).

La commande ci-dessus fonctionne comme suit:

  1. La syntaxe pour enregistrer un fichier dans vim est:

    :w <filename>
    
  2. La syntaxe pour exécuter une commande shell dans vim est:

    :!<command>
    
  3. À l'intérieur de l'environnement shell émis par vim, %il se trouve qu'il pointe vers le nom de fichier actuel. Vous pouvez le vérifier en exécutant ce qui suit:

    :!echo %
    

    Cela devrait afficher le nom du fichier (ou une erreur, si vim a été exécuté sans nom de fichier).

    En utilisant cat, nous pouvons également afficher le contenu du fichier:

    :!cat %
    

    Cela devrait renvoyer le contenu des fichiers dans son dernier état enregistré ou une erreur s'il n'a jamais été enregistré.

  4. Le programme diff est capable de lire à partir de l'entrée standard (stdin). Sa page de manuel indique ce qui suit:

    [...] Si un FICHIER est '-', lisez l'entrée standard. [...]

  5. L'exécution de la commande save sans nom de fichier mais plutôt avec une commande shell derrière elle oblige vim à écrire le contenu des fichiers sur stdin du shell au lieu de l'enregistrer dans un fichier physique. Vous pouvez le vérifier en exécutant

    :w !cat
    

    Cela devrait toujours imprimer le contenu actuel des fichiers (qui aurait été écrit dans un fichier à la place).

Mettre ensemble (ou tl; dr): Le fichier est "enregistré" dans stdin, diff est exécuté avec le nom de fichier et stdin en entrée.

Connaître celui-ci pourrait également comparer des fichiers avec vimdiff faisant quelque chose comme ça - c'est juste une idée que vous ne voulez pas faire ceci:

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

(Ensuite, ouvrez en lecture seule et fermez vimdiff en utilisant :qall)


Une approche plus sensée pour utiliser vimdiff consisterait à créer un script shell contenant ce qui suit vim - -c ":vnew $1 |windo diffthis", en le rendant exécutable, en le sauvegardant dans le PATH comme par exemple vimdiffWithStdin, puis en le comparant avec la commande suivante dans vim::w !vimdiffWithStdin %
Tobias Heinicke

Encore plus simple: :w !vimdiff % /dev/stdin. Je ne sais pas si une astuce similaire existe pour Windows.
deft_code

12

J'ai toujours aimé les différences - sympa, simple, ça marche.


Cela fonctionne BEAUCOUP mieux que les options les plus votées. Cela donne la possibilité de le basculer.
Steven Lu

1
@StevenLu - Meh ... que pouvez-vous faire? En tout cas, content que vous l'aimiez. Je trouve cela plus pratique que l'autre approche.
Tour

Moi, je fais deuxième @Steven, vos suggestions de différences sont excellentes. Merci!
AS

Cela peut également être installé en tant que plugin du même développeur: github.com/jmcantrell/vim-diffchanges
Sumanth Lingappa

joli plugin, mais il ne supprime pas le patch qu'il crée par la suite? Edit: Mon mauvais! Cela fait. Je ne l'utilisais pas de la bonne manière. J'ai dû utiliser :DiffChangesDiffToggle.
aderchox il y a

10

depuis 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

... comme documenté à vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig . L' avantage de cette plus w !diff % -est que cela fonctionne sur les sources à distance aussi (par exemple: vim sftp://example.com/foo.txt)
Lekensteyn

1
J'aime mieux cela parce que nous voyons la différence juste à l'intérieur du tampon vim lui-même plutôt que dans un terminal
Niko Bellic

Comment revenez-vous à la normale une fois que vous avez fini d'examiner les différences?
Niko Bellic

Vous pouvez vous débarrasser de la clause if en remplaçant command par command! (voir: h E174)
elig

@NikoBellic Fermez d'abord la "vieille" fenêtre (marquée comme tampon de travail) avec ': q'. Vous pouvez passer d'une fenêtre à l'autre en appuyant deux fois sur ctrl-W en mode normal. Ensuite, vous pouvez désactiver diff en écrivant: diffoff
brunch875

2

Source ce qui suit et utilisez: Commande 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

Pas exactement ce que vous recherchez, mais SCMDiff.vim est vraiment cool. Une pression sur une touche, et il met en évidence votre fichier actuel avec la révision principale dans un dépôt de contrôle de source. Il est destiné à fonctionner avec de nombreux SCMS. Je l'utilise avec forforce.


2

Il existe un plugin, basé sur différentes réponses ici: https://github.com/gangleri/vim-diffsaved

Il fournit la :w !diff % -méthode et la plus impliquée diffthis.

En dehors de cela, undotree permet cela aussi, mais aussi beaucoup plus (diffs entre les différents points de contrôle d'annulation). Similaire à Gundo .


1

Je peux recommander le plugin histwin .

Bien qu'il ne diffère pas de la version enregistrée actuelle du fichier (comme les autres réponses), il peut afficher les modifications depuis que vous avez commencé à éditer , et même rejouer vos modifications dans l'ordre. La différence apparaît si vous enregistrez de manière intermédiaire.

De plus, il affiche une liste de toutes les branches de l'historique des annulations et vous permet de basculer ou de comparer entre elles.

PS: Bien que le plugin ne suive pas automatiquement les moments dans l'historique des éditions depuis chaque changement de fichier, vous pouvez explicitement "taguer" le moment où vous enregistrez le fichier de sorte que vous puissiez plus tard vimdiff avec, si vous le souhaitez. Peut-être que cela pourrait être automatisé?


1

Si vous souhaitez utiliser vim à des fins de comparaison comme dans vimdiff, vous pouvez faire quelque chose comme ceci:

Modifiez votre .vimrc et ajoutez:

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

À partir de là, vous verrez vos modifications et pourrez quitter la vue diff en utilisant qallcomme dans vimdiff en appuyant sur F8 en mode commande. Remplacez F8 par n'importe quelle clé de votre choix.

Edit: Ajout de -M pour interdire toute modification, car il n'est pas enregistré.


Cette commande commence à fonctionner pour moi, elle me montre les différences côte à côte. Cependant, dès que j'essaye de modifier quoi que ce soit, la fenêtre vim devient folle. Je commence à taper et j'obtiens une invite de bash derrière les mots vim de chaque côté de l'écran. Il semble donc afficher le diff, mais vim plante alors. De plus, j'obtiens cette erreur Vim: Error reading input, exiting...des idées de ce qui ne va pas ici?
Trevor

@Trevor: Je ne pouvais que deviner quels sont les problèmes. Il n'est en effet pas épargné d'apporter des modifications en différant ainsi. Par conséquent, j'ai ajouté le paramètre "-M" pour l'interdire complètement. Désolé.
Tobias Heinicke

1

git prend en charge la commande suivante

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

mappez-le à une commande en ajoutant ce qui suit à votre ~ / .vimrc

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

Maintenant, l'exécution :GitDiffdevient une petite commande pratique pour afficher rapidement le diff avant chaque sauvegarde.


0

Vous pouvez faire en sorte que vim crée une dernière sauvegarde et une sauvegarde d'origine avec:

:set backup
:set patchmode=.orig 

Par la suite, vous pouvez les ouvrir dans un split:

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

Et à partir de là, faites:

:vimdiff in each buffer

Si vous ne voulez plus de restes mais que vous voulez vimdiff, vous pouvez également faire:

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

puis faire: diffère à chaque fractionnement


0

Les modifications que vous venez de modifier [ tampon ], à savoir celles qui diffèrent de la dernière version enregistrée (en travaillant dir ectory), ceux - ci peuvent différer avec la dernière version index ( Git ). J'ai mappé les deux:

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

Exemple de vimdiff vs Gdiff.

  • vimdiff: : vimdiff
  • Gdiff: Gdiff Commitant les changements, vous ne voyez que Gdiff, ce qui pourrait ou pourrait avoir les mêmes changements que vimdiff: en validant les modifications, vous ne voyez que Gdiff, ce qui pourrait ou ne pourrait PAS avoir les mêmes modifications que vimdiff

De plus, vers un vimdifffichier homonyme facile dans un autre chemin:

    " 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
On pourrait juste faire 1 map qui s'exécute: a Gdiffsi possible et sinon (par exemple pas un projet Git) puis effectuer a :vimdiff. Avec try-catch-endtry. Mais cette manière :DiffWithSaveddans un projet Git fait défaut.
Xopi García

-2

Suivez ce qui précède suggère que j'utilise git diff que j'aime beaucoup:

:w !git diff  % -
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.