Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using svn diff in combination with vimdiff to get tabbed diff page per modified file

Tags:

vim

diff

svn

Is it possible to get use svn in combination with vim to get a series of tab pages which contain a diff of each file? It would be a much better alternative to svn diff | view -, but instead of a linear list of diffs it would use vimdiff.

In the past, I have found a way to do this and get svn diff to open multiple vims for each file edited, but being able to go back and review old files would be very useful. Therefore, given a set of tuples of files S, I need a vim shell command which will open each file in the first position of the tuples of S in a different tab page and diff it with the corresponding file in the second position of the tuples in S.

like image 704
solinent Avatar asked Jan 31 '12 18:01

solinent


1 Answers

You can specify the diff command you want to use in Subversion via the --diff-cmd command line switch, or by specifying it in the Subversion configuration (which is $HOME/.subversion/config for the Unix command line client).

The main thing is to understand what parameters are passed to your SVN diff command:

  • 4th to Last Parameter - Program Title on the left side
  • 3rd to Last Parameter - Program Title on the right side
  • 2nd to Last Parameter - Temporary file on the left side
  • Last Parameter - Temporary file on the right side

The first parameters passed are the switches to the Subversion diff command. For example:

  • -u
  • -L

You can use this information to create a script to view the files in VIM. Here's a simple Perl one:

#! /usr/bin/env perl

use strict;
use warnings;

my $diff = "/usr/bin/vimdiff";

my $num_of_params = $#ARGV;

my $file1 = $ARGV[$num_of_params - 1];
my $file2 = $ARGV[$num_of_params];

my $title1 = $ARGV[$num_of_params - 4];
my $title2 = $ARGV[$num_of_params - 3];

my $title = "$title1 - $title2";
$title =~ s/\t/    /g;
$title =~ s/ /\\ /g;

system qq($diff -c "set titlestring=$title" "$file1" "$file2");

You must make sure that your system command (like vimdiff) holds the command line. I tried to use mvim on my Mac, but the temporary files were deleted before the mvim command was executed.

Now, you can do this:

$ svn diff --diff-cmd mydiff -rPREV

And, if your script is in your PATH and is executable, it should work.


Thanks to ZyX

Here's the improved program taking in ZyX's suggestions. I had to make some changes. My diff command is actually mvim on my machine, and I need to pass in two parameters (-d to say it's a diff, and -f to say not to throw mvim into the background). This meant passing $DIFF as ZyX suggested would cause my system command to think that mvim -d -f is my command, and I get an error. To solve this, I store the command in an array. I've also made the array constant while I was at it.

Here's the program below. Change DIFF to point to your diff command (which is probably vimdiff, gvim -d -f, or vim -d. If you're on Windows, and the full path is under C:/Program Files/Vim, you can use C:/Progr~1/Vim to get rid of the space. Otherwise, you'll need to do:

use constant DIFF => ('C:/Program Files/Vim/VIM73/gvim', '-f', '-d')

since you won't be able to use qw. Can we say Thank you Microsoft for putting a space in the directory name where all commands are stored for no good reason? I knew you could. BTW, if the directory where your editor is located is in your PATH, you don't need to specify the full directory name.

#! /usr/bin/env perl

use strict;
use warnings;

use constant DIFF => qw(mvim -d -f);

my $parameters = $#ARGV;
my $file1 = $ARGV[$parameters - 1];
my $file2 = $ARGV[$parameters];
my $title1 = $ARGV[$parameters - 4];
my $title2 = $ARGV[$parameters - 2];

$ENV{TITLE} = "$title1  -   $title2";

system DIFF, '-c', 'let &titlestring=$TITLE', $file1, $file2;
like image 114
David W. Avatar answered Oct 07 '22 03:10

David W.