diffident 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZTM4NGJjMWI2MDQ4OTllNTE5MmI4NDlmODkzM2IxZWYwYzQ1M2E0OA==
5
+ data.tar.gz: !binary |-
6
+ Njg4ZDk3OWFkMjg4YzMwOGFkNDMxODEwYmFiNzIzNWNlNDVmMjRiNA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NmYzYjk1NDE3NTJmY2VhMjEyOWZiYjg3YzgyN2ZjZTExMjIzZDk5NDg4ZGVh
10
+ OTQ1M2ZmZmYwYWUyZGMwNzVjZjMyODRjOGY2NGQzNGU1MzE5OGM4NGU1Mjcz
11
+ YzUzNzU3NDVkN2IwM2YwNjY4YTIyOGIyZTJiNmY2MDIwYWM2ZWM=
12
+ data.tar.gz: !binary |-
13
+ N2ZlMWVlZTIxZDFhZTJiOTQ3ZWJkNGYxODczYmMzMWU0YWU4Y2IwYTYxMzc0
14
+ NmY4YjU3MWI3YzY2YjBhMDBhYzdiMjk1YTJlOTJhNThmZjM2NGU3NDk3YWMy
15
+ ZWYyNTg5MWZiNmY0YzdiNzQ2MjFlYWNiNzFmNzRjZDFlNDE0NzQ=
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 my codeworks
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # Diffident
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/diffident.png)](http://badge.fury.io/rb/diffident)
4
+ [![Build Status](https://travis-ci.org/my-codeworks/diffident.png?branch=master)](https://travis-ci.org/my-codeworks/diffident)
5
+ [![Code Climate](https://codeclimate.com/github/my-codeworks/diffident.png)](https://codeclimate.com/github/my-codeworks/diffident)
6
+
7
+ > Based on the [differ](http://github.com/pvande/differ) gem by Pieter Vande Bruggen
8
+
9
+ Diffident is a flexible, pure-Ruby diff library, suitable for use in both command line scripts and web applications. The flexibility comes from the fact that diffs can be built at completely arbitrary levels of granularity (some common ones are built-in), and can be output in a variety of formats.
10
+
11
+ It also gives you raw access to the diff structure, should you need it, so you can build whatever you need that needs a diff.
12
+
13
+ ## Internals
14
+
15
+ Diffident uses the ruby StringScan object to walk through the input and collect Diffidentances. It records additions, subtractions, changes and can merge two diffs that might additionally contain conflicts.
16
+
17
+ ## Installation
18
+
19
+ ### Bundler
20
+
21
+ Add this to your `Gemfile`
22
+
23
+ ```ruby
24
+ gem 'diffident'
25
+ ```
26
+
27
+ and run bundle to install
28
+
29
+ ```bash
30
+ bundle install
31
+ ```
32
+
33
+ ### Manual
34
+
35
+ Install it via `gem`
36
+
37
+ ```bash
38
+ sudo gem install diffident
39
+ ```
40
+
41
+ and require it in your project
42
+
43
+ ```ruby
44
+ require 'diffident'
45
+ ```
46
+
47
+ ## How do I use this thing?
48
+
49
+ There are a number of ways to use Diffident, depending on your situation and needs. Lets examplify:
50
+
51
+ ```ruby
52
+ @original = "Epic lolcat fail!"
53
+ @current = "Epic wolfman fail!"
54
+ ```
55
+
56
+ There are a number of built-in diff_by_* methods to choose from for standard use:
57
+
58
+ ```ruby
59
+ Diffident.diff_by_line(@current, @original)
60
+ # => {"Epic lolcat fail!" >> "Epic wolfman fail!"}
61
+
62
+ Diffident.diff_by_word(@current, @original)
63
+ # => Epic {"lolcat" >> "wolfman"} fail!
64
+
65
+ Diffident.diff_by_char(@current, @original)
66
+ # => Epic {+"wo"}l{-"olcat "}f{+"m"}a{+"n fa"}il!
67
+ ```
68
+
69
+ ### Ok, but that doesn't quite cover my case, I have to split by "whatever".
70
+
71
+ No problem, you can call diff directly and supply your own boundary string:
72
+
73
+ ```ruby
74
+ Diffident.diff(@current, @original) # Implicitly by line by default
75
+ # => {"Epic lolcat fail!" >> "Epic wolfman fail!"}
76
+
77
+ Diffident.diff(@current, @original, 'i')
78
+ # => Epi{"c lolcat fa" >> "c wolfman fa"}il
79
+ ```
80
+
81
+ ### Yeah, thats nice. But a simple string might not always cut it...
82
+
83
+ Well, you can supply a regex instead of your string if you have to:
84
+
85
+ ```ruby
86
+ Diffident.diff(@original, @current, /[a-z]i/)
87
+ # => E{"c wolfman f" >> "c lolcat f"}l!
88
+ ```
89
+
90
+ Include a capture group if you want to keep the separator:
91
+
92
+ ```ruby
93
+ Diffident.diff(@original, @current, /([a-z]i)/)
94
+ # => Epi{"c wolfman f" >> "c lolcat f"}ail!
95
+ ```
96
+
97
+ ### Ok, ok, but I don't like having to write "Diffident" everywhere.
98
+
99
+ If you would like something a little more inline you can `require 'diffident/string'` to get some added inline string magic:
100
+
101
+ ```ruby
102
+ @current.diff(@original) # Implicitly by line by default
103
+ # => {"Epic lolcat fail!" >> "Epic wolfman fail!"}
104
+ ```
105
+
106
+ Or a lot more inline:
107
+
108
+ ```ruby
109
+ @current - @original # Implicitly by line by default
110
+ # => {"Epic lolcat fail!" >> "Epic wolfman fail!"}
111
+
112
+ Diffident.separator = ' ' # Custom string
113
+ @current - @original
114
+ # => Epic {"lolcat" >> "wolfman"} fail!
115
+
116
+ Diffident.separator = /[a-z]i/ # Custom regex without capture group
117
+ @original - @current
118
+ # => E{"c wolfman f" >> "c lolcat f"}l!
119
+
120
+ Diffident.separator = /([a-z]i)/ # Custom regex with capture group
121
+ @original - @current
122
+ # => Epi{"c wolfman f" >> "c lolcat f"}ail!
123
+ ```
124
+
125
+ So we've pretty much got you covered.
126
+
127
+ ## What about output formatting?
128
+
129
+ Need a diffidentent output format? We've got a few of those too:
130
+
131
+ ```ruby
132
+ Diffident.format = :ascii # Default
133
+ Diffident.format = :color
134
+ Diffident.format = :html
135
+
136
+ Diffident.format = MyCustomFormatModule
137
+ ```
138
+
139
+ The formatter must respond to the call method that takes an instant of the Change class as an argument and returns a string.
140
+
141
+ ### But I don't want to change the system-wide default for only a single diff output!
142
+
143
+ Yeah, we either:
144
+
145
+ ```ruby
146
+ diff = @current - @original
147
+ diff.format_as(:color)
148
+ ```
149
+
150
+ Or with your own formatter:
151
+
152
+ ```ruby
153
+ diff = @current - @original
154
+ diff.format_as(->(c){c.to_s})
155
+ ```
156
+
157
+ ## Copyright
158
+
159
+ > Know always right from wrong, and let others see your good works. - Pieter Vande Bruggen
160
+
161
+ The MIT License (MIT)
162
+
163
+ Copyright (c) 2013 my codeworks.
164
+
165
+ Permission is hereby granted, free of charge, to any person obtaining a copy
166
+ of this software and associated documentation files (the "Software"), to deal
167
+ in the Software without restriction, including without limitation the rights
168
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
169
+ copies of the Software, and to permit persons to whom the Software is
170
+ furnished to do so, subject to the following conditions:
171
+
172
+ The above copyright notice and this permission notice shall be included in
173
+ all copies or substantial portions of the Software.
174
+
175
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
176
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
178
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
179
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
180
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
181
+ THE SOFTWARE.
@@ -0,0 +1,30 @@
1
+ module Diffident
2
+ class Change # :nodoc:
3
+ attr_accessor :insert, :delete
4
+ def initialize(options = {})
5
+ @insert = options[:insert] || ''
6
+ @delete = options[:delete] || ''
7
+ end
8
+
9
+ def insert?
10
+ !@insert.empty?
11
+ end
12
+
13
+ def delete?
14
+ !@delete.empty?
15
+ end
16
+
17
+ def change?
18
+ !@insert.empty? && !@delete.empty?
19
+ end
20
+
21
+ def to_s
22
+ Diffident.format.call(self)
23
+ end
24
+ alias :inspect :to_s
25
+
26
+ def ==(other)
27
+ self.insert == other.insert && self.delete == other.delete
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,95 @@
1
+ module Diffident
2
+ class Diff
3
+ def initialize
4
+ @raw = []
5
+ end
6
+
7
+ def same(*str)
8
+ return if str.empty?
9
+ if @raw.last.is_a? String
10
+ @raw.last << sep
11
+ elsif @raw.last.is_a? Change
12
+ if @raw.last.change?
13
+ @raw << sep
14
+ else
15
+ change = @raw.pop
16
+ if change.insert? && @raw.last
17
+ @raw.last << sep if change.insert.sub!(/^#{Regexp.quote(sep)}/, '')
18
+ end
19
+ if change.delete? && @raw.last
20
+ @raw.last << sep if change.delete.sub!(/^#{Regexp.quote(sep)}/, '')
21
+ end
22
+ @raw << change
23
+
24
+ @raw.last.insert << sep if @raw.last.insert?
25
+ @raw.last.delete << sep if @raw.last.delete?
26
+ @raw << ''
27
+ end
28
+ else
29
+ @raw << ''
30
+ end
31
+ @raw.last << str.join(sep)
32
+ end
33
+
34
+ def delete(*str)
35
+ return if str.empty?
36
+ if @raw.last.is_a? Change
37
+ change = @raw.pop
38
+ if change.insert? && @raw.last
39
+ @raw.last << sep if change.insert.sub!(/^#{Regexp.quote(sep)}/, '')
40
+ end
41
+ change.delete << sep if change.delete?
42
+ else
43
+ change = Change.new(:delete => @raw.empty? ? '' : sep)
44
+ end
45
+
46
+ @raw << change
47
+ @raw.last.delete << str.join(sep)
48
+ end
49
+
50
+ def insert(*str)
51
+ return if str.empty?
52
+ if @raw.last.is_a? Change
53
+ change = @raw.pop
54
+ if change.delete? && @raw.last
55
+ @raw.last << sep if change.delete.sub!(/^#{Regexp.quote(sep)}/, '')
56
+ end
57
+ change.insert << sep if change.insert?
58
+ else
59
+ change = Change.new(:insert => @raw.empty? ? '' : sep)
60
+ end
61
+
62
+ @raw << change
63
+ @raw.last.insert << str.join(sep)
64
+ end
65
+
66
+ def ==(other)
67
+ @raw == other.raw_array
68
+ end
69
+
70
+ def to_s
71
+ @raw.join()
72
+ end
73
+
74
+ def format_as(f)
75
+ f = Diffident.format_for(f)
76
+ @raw.inject('') do |sum, part|
77
+ part = case part
78
+ when String then part
79
+ when Change then f.call(part)
80
+ end
81
+ sum << part
82
+ end
83
+ end
84
+
85
+ protected
86
+ def raw_array
87
+ @raw
88
+ end
89
+
90
+ private
91
+ def sep
92
+ Diffident.separator.is_a?(Regexp) ? '' : "#{Diffident.separator}"
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,27 @@
1
+ module Diffident
2
+ module Format
3
+ module Ascii
4
+ class << self
5
+ def call(change)
6
+ (change.change? && as_change(change)) ||
7
+ (change.delete? && as_delete(change)) ||
8
+ (change.insert? && as_insert(change)) ||
9
+ ''
10
+ end
11
+
12
+ private
13
+ def as_insert(change)
14
+ "{+#{change.insert.inspect}}"
15
+ end
16
+
17
+ def as_delete(change)
18
+ "{-#{change.delete.inspect}}"
19
+ end
20
+
21
+ def as_change(change)
22
+ "{#{change.delete.inspect} >> #{change.insert.inspect}}"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module Diffident
2
+ module Format
3
+ module Color
4
+ class << self
5
+ def call(change)
6
+ (change.change? && as_change(change)) ||
7
+ (change.delete? && as_delete(change)) ||
8
+ (change.insert? && as_insert(change)) ||
9
+ ''
10
+ end
11
+
12
+ private
13
+ def as_insert(change)
14
+ "\033[32m#{change.insert}\033[0m"
15
+ end
16
+
17
+ def as_delete(change)
18
+ "\033[31m#{change.delete}\033[0m"
19
+ end
20
+
21
+ def as_change(change)
22
+ as_delete(change) << as_insert(change)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module Diffident
2
+ module Format
3
+ module HTML
4
+ class << self
5
+ def call(change)
6
+ (change.change? && as_change(change)) ||
7
+ (change.delete? && as_delete(change)) ||
8
+ (change.insert? && as_insert(change)) ||
9
+ ''
10
+ end
11
+
12
+ private
13
+ def as_insert(change)
14
+ %Q{<ins class="Diffident">#{change.insert}</ins>}
15
+ end
16
+
17
+ def as_delete(change)
18
+ %Q{<del class="Diffident">#{change.delete}</del>}
19
+ end
20
+
21
+ def as_change(change)
22
+ as_delete(change) << as_insert(change)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ module Diffident
2
+ module StringDiffident
3
+ def diff(old)
4
+ Diffident.diff(self, old, Diffident.separator || "\n")
5
+ end
6
+ alias :- :diff
7
+ end
8
+ end
9
+
10
+ String.class_eval do
11
+ include Diffident::StringDiffident
12
+ end
@@ -0,0 +1,43 @@
1
+ module Diffident
2
+ class Tokenizer
3
+
4
+ def initialize(this, base, separator)
5
+ @this = this.split(separator)
6
+ @base = base.split(separator)
7
+ @diff = Diff.new
8
+ end
9
+
10
+ def run
11
+ advance until @base.empty? || @this.empty?
12
+ @diff.insert(*@this) || @diff.delete(*@base)
13
+ return @diff
14
+ end
15
+
16
+ private
17
+
18
+ def advance
19
+ del, add = @base.shift, @this.shift
20
+
21
+ prioritize_insert = @this.length > @base.length
22
+ insert = @this.index(del)
23
+ delete = @base.index(add)
24
+
25
+ if del == add
26
+ @diff.same(add)
27
+ elsif insert && prioritize_insert
28
+ change(:insert, @this.unshift(add), insert)
29
+ elsif delete
30
+ change(:delete, @base.unshift(del), delete)
31
+ elsif insert
32
+ change(:insert, @this.unshift(add), insert)
33
+ else
34
+ @diff.insert(add) && @diff.delete(del)
35
+ end
36
+ end
37
+
38
+ def change(method, array, index)
39
+ @diff.send(method, *array.slice!(0..index))
40
+ @diff.same(array.shift)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ module Diffident
2
+ VERSION = "0.1.0"
3
+ end
data/lib/diffident.rb ADDED
@@ -0,0 +1,64 @@
1
+ require 'diffident/change'
2
+ require 'diffident/diff'
3
+ require 'diffident/tokenizer'
4
+ require 'diffident/format/ascii'
5
+ require 'diffident/format/color'
6
+ require 'diffident/format/html'
7
+
8
+ module Diffident
9
+ class << self
10
+
11
+ def separator=(separator)
12
+ @@separator = separator
13
+ end
14
+
15
+ def separator
16
+ @@separator
17
+ end
18
+
19
+ def diff(this, base, new_sep = "\n")
20
+ old_sep = self.separator
21
+ self.separator = new_sep
22
+
23
+ tokenizer = Diffident::Tokenizer.new(this, base, new_sep)
24
+ tokenizer.run
25
+ ensure
26
+ self.separator = old_sep
27
+ end
28
+
29
+ def diff_by_char(to, from)
30
+ diff(to, from, '')
31
+ end
32
+
33
+ def diff_by_word(to, from)
34
+ diff(to, from, /\b/)
35
+ end
36
+
37
+ def diff_by_line(to, from)
38
+ diff(to, from, "\n")
39
+ end
40
+
41
+ def format=(f)
42
+ @format = format_for(f)
43
+ end
44
+
45
+ def format
46
+ return @format || Format::Ascii
47
+ end
48
+
49
+ def format_for(f)
50
+ if f.respond_to? :call
51
+ f
52
+ else
53
+ case f
54
+ when :ascii then Format::Ascii
55
+ when :color then Format::Color
56
+ when :html then Format::HTML
57
+ when nil then nil
58
+ else raise "Unknown format type #{f.inspect}"
59
+ end
60
+ end
61
+ end
62
+
63
+ end
64
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: diffident
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jonas Schubert Erlandsson
8
+ - Pieter van de Bruggen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '1.3'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '1.3'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: ! 'diffident: To show modest reserve, a gem to create and manipulate
57
+ text diffs. This gem provides a pure ruby implementation of a diff tool. It gives
58
+ access to several methods by which to get a diff from strings and ways to format
59
+ the output. It also gives direct access to the internal diff structure so that you
60
+ can manipulate and extend it any way you need to.'
61
+ email: jonas.schubert.erlandsson@my-codeworks.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - lib/diffident/change.rb
67
+ - lib/diffident/diff.rb
68
+ - lib/diffident/format/ascii.rb
69
+ - lib/diffident/format/color.rb
70
+ - lib/diffident/format/html.rb
71
+ - lib/diffident/string.rb
72
+ - lib/diffident/tokenizer.rb
73
+ - lib/diffident/version.rb
74
+ - lib/diffident.rb
75
+ - LICENSE
76
+ - README.md
77
+ homepage: http://github.com/my-codeworks/diffident
78
+ licenses:
79
+ - MIT
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.0.3
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: A pure ruby implementation for generating and merging string diffs
101
+ test_files: []
102
+ has_rdoc: