Technology moves fast! ⚡ Don't get left behind.🚶 Subscribe to our mailing list to keep up with latest and greatest in open source projects! 🏆


Subscribe to our mailing list

diffy

Easy Diffing in Ruby

Subscribe to updates I use diffy


Statistics on diffy

Number of watchers on Github 905
Number of open issues 36
Average time to close an issue 2 months
Main language Ruby
Average time to merge a PR 15 days
Open pull requests 9+
Closed pull requests 12+
Last commit over 1 year ago
Repo Created over 8 years ago
Repo Last Updated about 1 year ago
Size 139 KB
Homepage http://rubygems.o...
Organization / Authorsamg
Contributors17
Page Updated
Do you use diffy? Leave a review!
View open issues (36)
View diffy activity
View on github
Fresh, new opensource launches 🚀🚀🚀
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating diffy for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

Diffy - Easy Diffing With Ruby Build Status

Need diffs in your ruby app? Diffy has you covered. It provides a convenient way to generate a diff from two strings or files. Instead of reimplementing the LCS diff algorithm Diffy uses battle tested Unix diff to generate diffs, and focuses on providing a convenient interface, and getting out of your way.

Supported Formats

It provides several built in format options which can be passed to Diffy::Diff#to_s.

  • :text - Plain text output
  • :color - ANSI colorized text suitable for use in a terminal
  • :html - HTML output. Since version 2.0 this format does inline highlighting of the character changes between lines.
  • :html_simple - HTML output without inline highlighting. This may be useful in situations where high performance is required or simpler output is desired.

A default format can be set like so:

Diffy::Diff.default_format = :html

Installation

on Unix

gem install diffy

on Windows:

  1. Ensure that you have a working diff on your machine and in your search path.

    There are several options:

    1. Install Diff::LCS, which includes ldiff. RSpec depends on Diff::LCS so you may already have it installed.
    2. If you're using RubyInstaller, install the devkit.
    3. Install unxutils http://sourceforge.net/projects/unxutils

      note that these tools contain diff 2.7 which has a different handling of whitespace in the diff results. This makes Diffy spec tests yielding one fail on Windows.

    4. Install these two individually from the gnuwin32 project http://gnuwin32.sourceforge.net/

      note that this delivers diff 2.8 which makes Diffy spec pass even on Windows.

  2. Install the gem by

     gem install diffy
    

Getting Started

Here's an example of using Diffy to diff two strings

$ irb
>> string1 = <<-TXT
>" Hello how are you
>" I'm fine
>" That's great
>" TXT
=> "Hello how are you\nI'm fine\nThat's great\n"
>> string2 = <<-TXT
>" Hello how are you?
>" I'm fine
>" That's swell
>" TXT
=> "Hello how are you?\nI'm fine\nThat's swell\n"
>> puts Diffy::Diff.new(string1, string2)
-Hello how are you
+Hello how are you?
 I'm fine
-That's great
+That's swell

HTML Output

Outputing the diff as html is easy too. Here's an example using the :html_simple formatter.

>> puts Diffy::Diff.new(string1, string2).to_s(:html_simple)
<div class="diff">
  <ul>
    <li class="del"><del>Hello how are you</del></li>
    <li class="ins"><ins>Hello how are you?</ins></li>
    <li class="unchanged"><span>I'm fine</span></li>
    <li class="del"><del>That's great</del></li>
    <li class="ins"><ins>That's swell</ins></li>
  </ul>
</div>

The :html formatter will give you inline highlighting a la github.

>> puts Diffy::Diff.new("foo\n", "Foo\n").to_s(:html)
<div class="diff">
  <ul>
    <li class="del"><del><strong>f</strong>oo</del></li>
    <li class="ins"><ins><strong>F</strong>oo</ins></li>
  </ul>
</div>

There's some pretty nice css provided in Diffy::CSS.

>> puts Diffy::CSS
.diff{overflow:auto;}
.diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;}
.diff del, .diff ins{display:block;text-decoration:none;}
.diff li{padding:0; display:table-row;margin: 0;height:1em;}
.diff li.ins{background:#dfd; color:#080}
.diff li.del{background:#fee; color:#b00}
.diff li:hover{background:#ffc}
/* try 'whitespace:pre;' if you don't want lines to wrap */
.diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;}
.diff del strong{font-weight:normal;background:#fcc;}
.diff ins strong{font-weight:normal;background:#9f9;}
.diff li.diff-comment { display: none; }
.diff li.diff-block-info { background: none repeat scroll 0 0 gray; }

There's also a colorblind-safe version of the pallete provided in Diffy::CSS_COLORBLIND_1.

Side-by-side comparisons

Side-by-side comparisons, or split views as called by some, are supported by using the Diffy::SplitDiff class. This class takes a diff returned from Diffy::Diff and splits it in two parts (or two sides): left and right. The left side represents deletions while the right side represents insertions.

The class is used as follows:

Diffy::SplitDiff.new(string1, string2, options = {})

The optional options hash is passed along to the main Diff::Diff class, so all default options such as full diff output are supported. The output format may be changed by passing the format with the options hash (see below), and all default formats are supported.

Unlike Diffy::Diff, Diffy::SplitDiff does not use #to_s to output the resulting diff. Instead, two self-explanatory methods are used to output the diff: #left and #right. Using the earlier example, this is what they look like in action:

>> puts Diffy::SplitDiff.new(string1, string2).left
-Hello how are you
 I'm fine
-That's great
>> puts Diffy::SplitDiff.new(string1, string2).right
+Hello how are you?
 I'm fine
+That's swell

Changing the split view output format

The output format may be changed by passing the format with the options hash:

Diffy::SplitDiff.new(string1, string2, :format => :html)

This will result in the following:

>> puts Diffy::SplitDiff.new(string1, string2, :format => :html).left
<div class="diff">
  <ul>
    <li class="del"><del>Hello how are you</del></li>
    <li class="unchanged"><span>I&#39;m fine</span></li>
    <li class="del"><del>That&#39;s <strong>great</strong></del></li>
  </ul>
</div>
>> puts Diffy::SplitDiff.new(string1, string2, :format => :html).right
<div class="diff">
  <ul>
    <li class="ins"><ins>Hello how are you<strong>?</strong></ins></li>
    <li class="unchanged"><span>I&#39;m fine</span></li>
    <li class="ins"><ins>That&#39;s <strong>swell</strong></ins></li>
  </ul>
</div>

Other Diff Options

Diffing files instead of strings

You can diff files instead of strings by using the :source option.

>> puts Diffy::Diff.new('/tmp/foo', '/tmp/bar', :source => 'files')

Full Diff Output

By default Diffy removes the superfluous diff output. This is because its default is to show the complete diff'ed file (diff -U 10000 is the default).

Diffy does support full output, just use the :include_diff_info => true option when initializing:

>> Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n", :include_diff_info => true).to_s(:text)
=>--- /Users/chaffeqa/Projects/stiwiki/tmp/diffy20111116-82153-ie27ex   2011-11-16 20:16:41.000000000 -0500
+++ /Users/chaffeqa/Projects/stiwiki/tmp/diffy20111116-82153-wzrhw5 2011-11-16 20:16:41.000000000 -0500
@@ -1,2 +1,3 @@
 foo
 bar
+baz

And even deals a bit with the formatting!

Empty Diff Behavior

By default Diffy will return empty string if there are no differences in inputs. In previous versions the full text of its first input was returned in this case. To restore this behaviour simply use the :allow_empty_diff => false option when initializing.

Plus and Minus symbols in HTML output

By default Diffy doesn't include the +, -, and at the beginning of line for HTML output.

You can use the :include_plus_and_minus_in_html option to include those symbols in the output.

>> puts Diffy::Diff.new(string1, string2, :include_plus_and_minus_in_html => true).to_s(:html_simple)
<div class="diff">
  <ul>
    <li class="del"><del><span class="symbol">-</span>Hello how are you</del></li>
    <li class="ins"><ins><span class="symbol">+</span>Hello how are you?</ins></li>
    <li class="unchanged"><span class="symbol"> </span><span>I'm fine</span></li>
    <li class="del"><del><span class="symbol">-</span>That's great</del></li>
    <li class="ins"><ins><span class="symbol">+</span>That's swell</ins></li>
  </ul>
</div>

Number of lines of context around changes

You can use the :context option to override the number of lines of context that are shown around each change (this defaults to 10000 to show the full file).

>> puts Diffy::Diff.new("foo\nfoo\nBAR\nbang\nbaz", "foo\nfoo\nbar\nbang\nbaz", :context => 1)
 foo
-BAR
+bar
 bang

Overriding the command line options passed to diff.

You can use the :diff option to override the command line options that are passed to unix diff. They default to -U 10000. This option will noop if combined with the :context option.

>> puts Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :diff => "-w")
  foo
 bar

Default Diff Options

You can set the default options for new Diffy::Diffs using the Diffy::Diff.default_options and Diffy::Diff.default_options= methods. Options passed to Diffy::Diff.new will be merged into the default options.

>> Diffy::Diff.default_options
=> {:diff=>"-U 10000", :source=>"strings", :include_diff_info=>false, :include_plus_and_minus_in_html=>false}
>> Diffy::Diff.default_options.merge!(:source => 'files')
=> {:diff=>"-U 10000", :source=>"files", :include_diff_info=>false, :include_plus_and_minus_in_html=>false}

Custom Formats

Diffy tries to make generating your own custom formatted output easy. Diffy::Diff provides an enumerable interface which lets you iterate over lines in the diff.

>> Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").each do |line|
>*   case line
>>   when /^\+/ then puts "line #{line.chomp} added"
>>   when /^-/ then puts "line #{line.chomp} removed"
>>   end
>> end
line +baz added
=> [" foo\n", " bar\n", "+baz\n"]

You can also use Diffy::Diff#each_chunk to iterate each grouping of additions, deletions, and unchanged in a diff.

>> Diffy::Diff.new("foo\nbar\nbang\nbaz\n", "foo\nbar\nbing\nbong\n").each_chunk.to_a
=> [" foo\n bar\n", "-bang\n-baz\n", "+bing\n+bong\n"]

Use #map, #inject, or any of Enumerable's methods. Go crazy.

Testing

Diffy includes a full set of rspec tests. When contributing please include tests for your changes.

Build Status


Report bugs or request features at http://github.com/samg/diffy/issues

diffy open issues Ask a question     (View All Issues)
  • over 2 years split diff: show matching lines at same height
  • almost 3 years A way to just get the inline additions / deletions?
  • almost 3 years File Diffy doesn't work
  • about 3 years Determine number of lines or characters changed
  • over 3 years diff should not ignore errors
  • over 3 years Allow diff command to be overriden
  • over 3 years Enable dumping & loading diff
  • almost 4 years Show line numbers
  • about 4 years Diff but not patch
  • about 4 years Command line option override not working as advertised
  • over 4 years Unchanged lines show as changed
  • over 4 years How to display as a side-by-side comparison split view?
  • over 4 years Doesn't work when :diff is specified as empty string
  • over 4 years Diffy css scss
  • over 4 years Multiple character highlights blocks per line.
  • almost 5 years Allow ignoring different line endings?
  • about 5 years Errno::EBADF: Bad file descriptor on JRuby 1.7.10
  • over 5 years Spaces in filepaths unsupported
  • over 5 years Diffy does not diff
  • over 5 years Errno:ENOENT in XP
  • over 5 years Does it provides only chars diff?
  • over 6 years Use Diffy to get true or false for if statement.
diffy open pull requests (View All Pulls)
  • Allow formatting pre-diffed content
  • Added Diff3 Support
  • Additional information for changed references
  • Fix broken headings in Markdown files
  • Use posix-spawn instead of Open3
  • Travis: jruby-9.1.10.0
  • Travis: CI matrix update; support 1.9.3 using newer Bundler
  • Empty @tempfiles variable after diff
  • Implemented 'empty?' method for determining whether a diff is empty
diffy questions on Stackoverflow (View All Questions)
  • How to display the differences between two files using the diffy gem?
  • Rails Diffy Gem: How to Use CSS
diffy list of languages used
More projects by samg View all
Other projects in Ruby