dirb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/README.md +71 -0
  2. data/Rakefile +54 -0
  3. data/VERSION +1 -0
  4. data/lib/dirb.rb +93 -0
  5. data/spec/dirb_spec.rb +138 -0
  6. metadata +79 -0
@@ -0,0 +1,71 @@
1
+ Dirb - Easy Diffing With Ruby
2
+ ============================
3
+
4
+ Need diffs in your ruby app? Dirb has you covered. It provides a convenient
5
+ way to generate a diff from two strings. Instead of reimplementing the LCS diff
6
+ algorithm Dirb uses battle tested Unix diff to generate diffs, and focuses on
7
+ providing a convenient interface, and getting out of your way.
8
+
9
+ It provides several built in format options. Pass `:text`, `:color`, or
10
+ `:html` to `Dirb::Diff#to_s` to force that format, or set
11
+ `Dirb::Diff.default_format`
12
+
13
+ $ irb
14
+ >> require 'rubygems'
15
+ >> require 'dirb'
16
+ => true
17
+ >> string1 = <<-TXT
18
+ >" Hello how are you
19
+ >" I'm fine
20
+ >" That's great
21
+ >" TXT
22
+ => "Hello how are you\nI'm fine\nThat's great\n"
23
+ >> string2 = <<-TXT
24
+ >" Hello how are you?
25
+ >" I'm fine
26
+ >" That's swell
27
+ >" TXT
28
+ => "Hello how are you?\nI'm fine\nThat's swell\n"
29
+ >> puts Dirb::Diff.new(string1, string2)
30
+ -Hello how are you
31
+ +Hello how are you?
32
+ I'm fine
33
+ -That's great
34
+ +That's swell
35
+ => nil
36
+ >> puts Dirb::Diff.new(string1, string2).to_s(:html)
37
+ <ul class="diff">
38
+ <li class="del"><del>Hello how are you</del></li>
39
+ <li class="ins"><ins>Hello how are you?</ins></li>
40
+ <li class="unchanged"><span>I'm fine</span></li>
41
+ <li class="del"><del>That's great</del></li>
42
+ <li class="ins"><ins>That's swell</ins></li>
43
+ </ul>
44
+ => nil
45
+ >> Dirb::Diff.default_format = :color
46
+ => :color
47
+ irb(main):015:0> puts Dirb::Diff.new(string1, string2) # prints color in the terminal
48
+ -Hello how are you
49
+ +Hello how are you?
50
+ I'm fine
51
+ -That's great
52
+ +That's swell
53
+ => nil
54
+
55
+
56
+ Creating custom formatted output is easy too. `Dirb::Diff` provides an
57
+ enumberable interface which lets you iterate over lines in the diff.
58
+
59
+ >> Dirb::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").each do |line|
60
+ >* case line
61
+ >> when /^\+/ then puts "line #{line.chomp} added"
62
+ >> when /^-/ then puts "line #{line.chomp} removed"
63
+ >> end
64
+ >> end
65
+ line +baz added
66
+ => [" foo\n", " bar\n", "+baz\n"]
67
+
68
+ Use `#map`, `#inject`, or any of Enumerable's methods. Go crazy.
69
+
70
+ Report bugs or request features at http://github.com/samg/Dirb/issues
71
+
@@ -0,0 +1,54 @@
1
+ require 'spec/rake/spectask'
2
+ require 'rake/rdoctask'
3
+ require 'rake/gempackagetask'
4
+
5
+ task :default => :spec
6
+
7
+ desc "Run all specs in spec directory"
8
+ Spec::Rake::SpecTask.new(:spec) do |t|
9
+ t.spec_files = FileList['spec/**/*_spec.rb']
10
+ end
11
+
12
+ Rake::RDocTask.new do |rd|
13
+ rd.main = "README"
14
+ rd.rdoc_dir = 'doc'
15
+ rd.rdoc_files.include("README", "**/*.rb")
16
+ end
17
+
18
+ begin
19
+ require 'jeweler'
20
+ Jeweler::Tasks.new do |s|
21
+ s.name = %q{dirb}
22
+ s.version = "0.1.0"
23
+
24
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
25
+ s.authors = ["Sam Goldstein"]
26
+ s.date = %q{2010-06-28}
27
+ s.description = %q{Convenient diffing in ruby}
28
+ s.email = %q{sgrock@gmail.com}
29
+ s.has_rdoc = true
30
+ s.homepage = "http://github.com/samg/dirb/tree/master"
31
+ s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
32
+ s.require_paths = ["lib"]
33
+ s.summary = %q{A convenient way to diff string in ruby}
34
+
35
+ if s.respond_to? :specification_version then
36
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
37
+ s.specification_version = 2
38
+
39
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
40
+ s.add_runtime_dependency(%q<mime-types>, [">= 1.16"])
41
+ s.add_runtime_dependency(%q<diff-lcs>, [">= 1.1.2"])
42
+ else
43
+ s.add_dependency(%q<mime-types>, [">= 1.16"])
44
+ s.add_dependency(%q<diff-lcs>, [">= 1.1.2"])
45
+ end
46
+ else
47
+ s.add_dependency(%q<mime-types>, [">= 1.16"])
48
+ s.add_dependency(%q<diff-lcs>, [">= 1.1.2"])
49
+ end
50
+ end
51
+ rescue LoadError
52
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
53
+ end
54
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,93 @@
1
+ require 'rubygems'
2
+ require 'tempfile'
3
+ require 'open3'
4
+ module Dirb
5
+ class Diff
6
+ class << self
7
+ attr_writer :default_format
8
+ def default_format
9
+ @default_format || :text
10
+ end
11
+ end
12
+ include Enumerable
13
+ attr_reader :string1, :string2, :diff_options, :diff
14
+ def initialize(string1, string2, diff_options = "-U 10000")
15
+ @string1, @string2 = string1, string2
16
+ @diff_options = diff_options
17
+ end
18
+
19
+ def diff
20
+ @diff ||= Open3.popen3(
21
+ *[diff_bin, diff_options, tempfile(string1), tempfile(string2)]
22
+ ) { |i, o, e| o.read }
23
+ @diff = @string1.gsub(/^/, " ") if @diff =~ /\A\s*\Z/
24
+ @diff
25
+ end
26
+
27
+ def each &block
28
+ diff.each_line.reject{|x| x =~ /^---|\+\+\+|@@/ }.each &block
29
+ end
30
+
31
+ def tempfile(string)
32
+ t = Tempfile.new('dirb')
33
+ t.print(string)
34
+ t.flush
35
+ t.path
36
+ end
37
+
38
+ def to_s(format = nil)
39
+ format ||= self.class.default_format
40
+ formats = Format.instance_methods(false)
41
+ if formats.include? format.to_s
42
+ enum = self.each
43
+ enum.extend Format
44
+ enum.send format
45
+ else
46
+ raise ArgumentError,
47
+ "Format #{format.inspect} not found in #{formats.inspect}"
48
+ end
49
+ end
50
+ private
51
+
52
+ def diff_bin
53
+ bin = `which diff`.chomp
54
+ if bin.empty?
55
+ raise "Can't find a diff executable in PATH #{ENV['PATH']}"
56
+ end
57
+ bin
58
+ end
59
+
60
+ module Format
61
+ def color
62
+ map do |line|
63
+ case line
64
+ when /^\+/
65
+ "\033[32m#{line.chomp}\033[0m"
66
+ when /^-/
67
+ "\033[31m#{line.chomp}\033[0m"
68
+ else
69
+ line.chomp
70
+ end
71
+ end.join("\n") + "\n"
72
+ end
73
+
74
+ def text
75
+ to_a.join
76
+ end
77
+
78
+ def html
79
+ lines = map do |line|
80
+ case line
81
+ when /^\+/
82
+ ' <li class="ins"><ins>' + line.gsub(/^./, '').chomp + '</ins></li>'
83
+ when /^-/
84
+ ' <li class="del"><del>' + line.gsub(/^./, '').chomp + '</del></li>'
85
+ when /^ /
86
+ ' <li class="unchanged"><span>' + line.gsub(/^./, '').chomp + '</span></li>'
87
+ end
88
+ end
89
+ %'<ul class="diff">\n#{lines.join("\n")}\n</ul>\n'
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,138 @@
1
+ require 'spec'
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'dirb')
3
+
4
+ describe Dirb::Diff do
5
+ describe "#to_s" do
6
+ describe "with no line different" do
7
+ before do
8
+ @string1 = "foo\nbar\nbang\n"
9
+ @string2 = "foo\nbar\nbang\n"
10
+ end
11
+
12
+ it "should show everything" do
13
+ Dirb::Diff.new(@string1, @string2).to_s.should == <<-DIFF
14
+ foo
15
+ bar
16
+ bang
17
+ DIFF
18
+ end
19
+ end
20
+ describe "with one line different" do
21
+ before do
22
+ @string1 = "foo\nbar\nbang\n"
23
+ @string2 = "foo\nbang\n"
24
+ end
25
+
26
+ it "should show one line removed" do
27
+ Dirb::Diff.new(@string1, @string2).to_s.should == <<-DIFF
28
+ foo
29
+ -bar
30
+ bang
31
+ DIFF
32
+ end
33
+
34
+ it "to_s should accept a format key" do
35
+ Dirb::Diff.new(@string1, @string2).to_s(:color).
36
+ should == " foo\n\e[31m-bar\e[0m\n bang\n"
37
+ end
38
+
39
+ it "should accept a default format option" do
40
+ old_format = Dirb::Diff.default_format
41
+ Dirb::Diff.default_format = :color
42
+ Dirb::Diff.new(@string1, @string2).to_s.
43
+ should == " foo\n\e[31m-bar\e[0m\n bang\n"
44
+ Dirb::Diff.default_format = old_format
45
+ end
46
+
47
+ it "should show one line added" do
48
+ Dirb::Diff.new(@string2, @string1).to_s.should == <<-DIFF
49
+ foo
50
+ +bar
51
+ bang
52
+ DIFF
53
+ end
54
+ end
55
+
56
+ describe "with one line changed" do
57
+ before do
58
+ @string1 = "foo\nbar\nbang\n"
59
+ @string2 = "foo\nbong\nbang\n"
60
+ end
61
+ it "should show one line added and one removed" do
62
+ Dirb::Diff.new(@string1, @string2).to_s.should == <<-DIFF
63
+ foo
64
+ -bar
65
+ +bong
66
+ bang
67
+ DIFF
68
+ end
69
+ end
70
+
71
+ describe "with totally different strings" do
72
+ before do
73
+ @string1 = "foo\nbar\nbang\n"
74
+ @string2 = "one\ntwo\nthree\n"
75
+ end
76
+ it "should show one line added and one removed" do
77
+ Dirb::Diff.new(@string1, @string2).to_s.should == <<-DIFF
78
+ -foo
79
+ -bar
80
+ -bang
81
+ +one
82
+ +two
83
+ +three
84
+ DIFF
85
+ end
86
+ end
87
+
88
+ describe "with a somewhat complicated diff" do
89
+ before do
90
+ @string1 = "foo\nbar\nbang\nwoot\n"
91
+ @string2 = "one\ntwo\nthree\nbar\nbang\nbaz\n"
92
+ @diff = Dirb::Diff.new(@string1, @string2)
93
+ end
94
+ it "should show one line added and one removed" do
95
+ @diff.to_s.should == <<-DIFF
96
+ -foo
97
+ +one
98
+ +two
99
+ +three
100
+ bar
101
+ bang
102
+ -woot
103
+ +baz
104
+ DIFF
105
+ end
106
+
107
+ it "should make an awesome html diff" do
108
+ @diff.to_s(:html).should == <<-HTML
109
+ <ul class="diff">
110
+ <li class="del"><del>foo</del></li>
111
+ <li class="ins"><ins>one</ins></li>
112
+ <li class="ins"><ins>two</ins></li>
113
+ <li class="ins"><ins>three</ins></li>
114
+ <li class="unchanged"><span>bar</span></li>
115
+ <li class="unchanged"><span>bang</span></li>
116
+ <li class="del"><del>woot</del></li>
117
+ <li class="ins"><ins>baz</ins></li>
118
+ </ul>
119
+ HTML
120
+ end
121
+
122
+ it "should accept overrides to diff's options" do
123
+ @diff = Dirb::Diff.new(@string1, @string2, "--rcs")
124
+ @diff.to_s.should == <<-DIFF
125
+ d1 1
126
+ a1 3
127
+ one
128
+ two
129
+ three
130
+ d4 1
131
+ a4 1
132
+ baz
133
+ DIFF
134
+ end
135
+ end
136
+ end
137
+ end
138
+
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dirb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sam Goldstein
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-06-28 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mime-types
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "1.16"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: diff-lcs
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.2
34
+ version:
35
+ description: Convenient diffing in ruby
36
+ email: sgrock@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.md
43
+ files:
44
+ - README.md
45
+ - Rakefile
46
+ - VERSION
47
+ - lib/dirb.rb
48
+ - spec/dirb_spec.rb
49
+ has_rdoc: true
50
+ homepage: http://github.com/samg/dirb/tree/master
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --inline-source
56
+ - --charset=UTF-8
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ requirements: []
72
+
73
+ rubyforge_project:
74
+ rubygems_version: 1.3.5
75
+ signing_key:
76
+ specification_version: 2
77
+ summary: A convenient way to diff string in ruby
78
+ test_files:
79
+ - spec/dirb_spec.rb