dirb 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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