diff-lcs 1.3 → 1.4.2

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.
@@ -4,8 +4,7 @@ home :: https://github.com/halostatue/diff-lcs
4
4
  code :: https://github.com/halostatue/diff-lcs
5
5
  bugs :: https://github.com/halostatue/diff-lcs/issues
6
6
  rdoc :: http://rubydoc.info/github/halostatue/diff-lcs
7
- continuous integration :: {<img src="https://travis-ci.org/halostatue/diff-lcs.svg" />}[https://travis-ci.org/halostatue/diff-lcs]
8
- test coverage :: {<img src="https://coveralls.io/repos/halostatue/diff-lcs/badge.svg" alt="Coverage Status" />}[https://coveralls.io/r/halostatue/diff-lcs]
7
+ continuous integration :: {<img src="https://github.com/halostatue/diff-lcs/workflows/CI/badge.svg" />}[https://github.com/halostatue/diff-lcs/actions]
9
8
 
10
9
  == Description
11
10
 
@@ -13,10 +12,14 @@ Diff::LCS computes the difference between two Enumerable sequences using the
13
12
  McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities
14
13
  to create a simple HTML diff output format and a standard diff-like tool.
15
14
 
16
- This is release 1.3, providing a tentative fix to a long-standing issue related
17
- to incorrect detection of a patch direction. Also modernizes the gem
18
- infrastructure, testing infrastructure, and provides a warning-free experience
19
- to Ruby 2.4 users.
15
+ This is release 1.4, providing a simple extension that allows for
16
+ Diff::LCS::Change objects to be treated implicitly as arrays. Ruby versions
17
+ below 2.5 are soft-deprecated.
18
+
19
+ This means that older versions are no longer part of the CI test suite. If any
20
+ changes have been introduced that break those versions, bug reports and patches
21
+ will be accepted, but it will be up to the reporter to verify any fixes prior
22
+ to release. A future release will completely break compatibility.
20
23
 
21
24
  == Synopsis
22
25
 
@@ -78,7 +81,3 @@ The algorithm is described in A Fast Algorithm for Computing Longest Common
78
81
  Subsequences</em>, CACM, vol.20, no.5, pp.350-353, May 1977, with a few minor
79
82
  improvements to improve the speed. A simplified description of the algorithm,
80
83
  originally written for the Perl version, was written by Mark-Jason Dominus.
81
-
82
- :include: Contributing.rdoc
83
-
84
- :include: License.rdoc
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'rubygems'
4
4
  require 'rspec'
@@ -11,47 +11,30 @@ Hoe.plugin :gemspec2
11
11
  Hoe.plugin :git
12
12
  Hoe.plugin :travis
13
13
 
14
- spec = Hoe.spec 'diff-lcs' do
14
+ _spec = Hoe.spec 'diff-lcs' do
15
15
  developer('Austin Ziegler', 'halostatue@gmail.com')
16
16
 
17
17
  require_ruby_version '>= 1.8'
18
18
 
19
19
  self.history_file = 'History.md'
20
20
  self.readme_file = 'README.rdoc'
21
- self.licenses = [ 'MIT', 'Artistic-2.0', 'GPL-2.0+' ]
21
+ self.licenses = ['MIT', 'Artistic-2.0', 'GPL-2.0+']
22
22
 
23
23
  extra_dev_deps << ['hoe-doofus', '~> 1.0']
24
24
  extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
25
25
  extra_dev_deps << ['hoe-git', '~> 1.6']
26
26
  extra_dev_deps << ['hoe-rubygems', '~> 1.0']
27
- extra_dev_deps << ['hoe-travis', '~> 1.2']
28
27
  extra_dev_deps << ['rspec', '>= 2.0', '< 4']
29
- extra_dev_deps << ['rake', '>= 10.0', '< 12']
28
+ extra_dev_deps << ['rake', '>= 10.0', '< 14']
30
29
  extra_dev_deps << ['rdoc', '>= 0']
31
30
  end
32
31
 
33
- unless Rake::Task.task_defined? :test
34
- task :test => :spec
35
- Rake::Task['travis'].prerequisites.replace(%w(spec))
36
- end
37
-
38
32
  if RUBY_VERSION >= '2.0' && RUBY_ENGINE == 'ruby'
39
33
  namespace :spec do
40
- task :coveralls do
41
- if ENV['CI'] or ENV['TRAVIS']
42
- ENV['COVERALLS'] = 'yes'
43
- Rake::Task['spec'].execute
44
- else
45
- Rake::Task['spec:coverage'].execute
46
- end
47
- end
48
-
49
34
  desc "Runs test coverage. Only works Ruby 2.0+ and assumes 'simplecov' is installed."
50
35
  task :coverage do
51
36
  ENV['COVERAGE'] = 'yes'
52
37
  Rake::Task['spec'].execute
53
38
  end
54
39
  end
55
-
56
- # Rake::Task['travis'].prerequisites.replace(%w(spec:coveralls))
57
40
  end
@@ -1 +1,3 @@
1
- Autotest.add_discovery { "rspec2" }
1
+ # frozen_string_literal: true
2
+
3
+ Autotest.add_discovery { 'rspec2' }
@@ -1,4 +1,5 @@
1
- #!ruby -w
1
+ #! /usr/bin/env ruby -w
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'diff/lcs'
4
5
  require 'diff/lcs/htmldiff'
@@ -10,8 +11,8 @@ rescue LoadError
10
11
  end
11
12
 
12
13
  if ARGV.size < 2 or ARGV.size > 3
13
- $stderr.puts "usage: #{File.basename($0)} old new [output.html]"
14
- $stderr.puts " #{File.basename($0)} old new > output.html"
14
+ warn "usage: #{File.basename($0)} old new [output.html]"
15
+ warn " #{File.basename($0)} old new > output.html"
15
16
  exit 127
16
17
  end
17
18
 
@@ -23,10 +24,12 @@ options = { :title => "diff #{ARGV[0]} #{ARGV[1]}" }
23
24
  htmldiff = Diff::LCS::HTMLDiff.new(left, right, options)
24
25
 
25
26
  if ARGV[2]
26
- File.open(ARGV[2], "w") do |f|
27
+ File.open(ARGV[2], 'w') do |f|
27
28
  htmldiff.options[:output] = f
28
29
  htmldiff.run
29
30
  end
30
31
  else
31
32
  htmldiff.run
32
33
  end
34
+
35
+ # vim: ft=ruby
data/bin/ldiff CHANGED
@@ -1,6 +1,9 @@
1
- #!ruby -w
1
+ #! /usr/bin/env ruby -w
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'diff/lcs'
4
5
  require 'diff/lcs/ldiff'
5
6
 
6
7
  exit Diff::LCS::Ldiff.run(ARGV)
8
+
9
+ # vim: ft=ruby
@@ -1,3 +1,3 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'diff/lcs'
@@ -1,24 +1,24 @@
1
- # -*- ruby encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
3
+ module Diff; end unless defined? Diff # rubocop:disable Style/Documentation
2
4
 
3
- module Diff; end unless defined? Diff
4
5
  # == How Diff Works (by Mark-Jason Dominus)
5
6
  #
6
- # I once read an article written by the authors of +diff+; they said that
7
- # they hard worked very hard on the algorithm until they found the right
8
- # one.
7
+ # I once read an article written by the authors of +diff+; they said that they
8
+ # hard worked very hard on the algorithm until they found the right one.
9
9
  #
10
- # I think what they ended up using (and I hope someone will correct me,
11
- # because I am not very confident about this) was the `longest common
12
- # subsequence' method. In the LCS problem, you have two sequences of items:
10
+ # I think what they ended up using (and I hope someone will correct me, because
11
+ # I am not very confident about this) was the `longest common subsequence'
12
+ # method. In the LCS problem, you have two sequences of items:
13
13
  #
14
14
  # a b c d f g h j q z
15
15
  # a b c d e f g i j k r x y z
16
16
  #
17
17
  # and you want to find the longest sequence of items that is present in both
18
18
  # original sequences in the same order. That is, you want to find a new
19
- # sequence *S* which can be obtained from the first sequence by deleting
20
- # some items, and from the second sequence by deleting other items. You also
21
- # want *S* to be as long as possible. In this case *S* is:
19
+ # sequence *S* which can be obtained from the first sequence by deleting some
20
+ # items, and from the second sequence by deleting other items. You also want
21
+ # *S* to be as long as possible. In this case *S* is:
22
22
  #
23
23
  # a b c d f g j z
24
24
  #
@@ -30,9 +30,9 @@ module Diff; end unless defined? Diff
30
30
  # This module solves the LCS problem. It also includes a canned function to
31
31
  # generate +diff+-like output.
32
32
  #
33
- # It might seem from the example above that the LCS of two sequences is
34
- # always pretty obvious, but that's not always the case, especially when the
35
- # two sequences have many repeated elements. For example, consider
33
+ # It might seem from the example above that the LCS of two sequences is always
34
+ # pretty obvious, but that's not always the case, especially when the two
35
+ # sequences have many repeated elements. For example, consider
36
36
  #
37
37
  # a x b y c z p d q
38
38
  # a b c a x b y c z
@@ -43,29 +43,28 @@ module Diff; end unless defined? Diff
43
43
  # a x b y c z p d q
44
44
  # a b c a b y c z
45
45
  #
46
- # This finds the common subsequence +a b c z+. But actually, the LCS is +a x
47
- # b y c z+:
46
+ # This finds the common subsequence +a b c z+. But actually, the LCS is +a x b
47
+ # y c z+:
48
48
  #
49
49
  # a x b y c z p d q
50
50
  # a b c a x b y c z
51
51
  module Diff::LCS
52
- VERSION = '1.3'
52
+ VERSION = '1.4.2'
53
53
  end
54
54
 
55
55
  require 'diff/lcs/callbacks'
56
56
  require 'diff/lcs/internals'
57
57
 
58
- module Diff::LCS
58
+ module Diff::LCS # rubocop:disable Style/Documentation
59
59
  # Returns an Array containing the longest common subsequence(s) between
60
- # +self+ and +other+. See Diff::LCS#LCS.
60
+ # +self+ and +other+. See Diff::LCS#lcs.
61
61
  #
62
62
  # lcs = seq1.lcs(seq2)
63
63
  def lcs(other, &block) #:yields self[i] if there are matched subsequences:
64
64
  Diff::LCS.lcs(self, other, &block)
65
65
  end
66
66
 
67
- # Returns the difference set between +self+ and +other+. See
68
- # Diff::LCS#diff.
67
+ # Returns the difference set between +self+ and +other+. See Diff::LCS#diff.
69
68
  def diff(other, callbacks = nil, &block)
70
69
  Diff::LCS.diff(self, other, callbacks, &block)
71
70
  end
@@ -79,29 +78,27 @@ module Diff::LCS
79
78
  # Traverses the discovered longest common subsequences between +self+ and
80
79
  # +other+. See Diff::LCS#traverse_sequences.
81
80
  def traverse_sequences(other, callbacks = nil, &block)
82
- traverse_sequences(self, other, callbacks ||
83
- Diff::LCS.YieldingCallbacks, &block)
81
+ traverse_sequences(self, other, callbacks || Diff::LCS::SequenceCallbacks, &block)
84
82
  end
85
83
 
86
84
  # Traverses the discovered longest common subsequences between +self+ and
87
85
  # +other+ using the alternate, balanced algorithm. See
88
86
  # Diff::LCS#traverse_balanced.
89
87
  def traverse_balanced(other, callbacks = nil, &block)
90
- traverse_balanced(self, other, callbacks ||
91
- Diff::LCS.YieldingCallbacks, &block)
88
+ traverse_balanced(self, other, callbacks || Diff::LCS::BalancedCallbacks, &block)
92
89
  end
93
90
 
94
- # Attempts to patch +self+ with the provided +patchset+. A new sequence
95
- # based on +self+ and the +patchset+ will be created. See Diff::LCS#patch.
96
- # Attempts to autodiscover the direction of the patch.
91
+ # Attempts to patch +self+ with the provided +patchset+. A new sequence based
92
+ # on +self+ and the +patchset+ will be created. See Diff::LCS#patch. Attempts
93
+ # to autodiscover the direction of the patch.
97
94
  def patch(patchset)
98
95
  Diff::LCS.patch(self, patchset)
99
96
  end
100
- alias_method :unpatch, :patch
97
+ alias unpatch patch
101
98
 
102
- # Attempts to patch +self+ with the provided +patchset+. A new sequence
103
- # based on +self+ and the +patchset+ will be created. See Diff::LCS#patch.
104
- # Does no patch direction autodiscovery.
99
+ # Attempts to patch +self+ with the provided +patchset+. A new sequence based
100
+ # on +self+ and the +patchset+ will be created. See Diff::LCS#patch. Does no
101
+ # patch direction autodiscovery.
105
102
  def patch!(patchset)
106
103
  Diff::LCS.patch!(self, patchset)
107
104
  end
@@ -114,8 +111,8 @@ module Diff::LCS
114
111
  end
115
112
 
116
113
  # Attempts to patch +self+ with the provided +patchset+, using #patch!. If
117
- # the sequence this is used on supports #replace, the value of +self+ will
118
- # be replaced. See Diff::LCS#patch. Does no patch direction autodiscovery.
114
+ # the sequence this is used on supports #replace, the value of +self+ will be
115
+ # replaced. See Diff::LCS#patch. Does no patch direction autodiscovery.
119
116
  def patch_me(patchset)
120
117
  if respond_to? :replace
121
118
  replace(patch!(patchset))
@@ -124,10 +121,9 @@ module Diff::LCS
124
121
  end
125
122
  end
126
123
 
127
- # Attempts to unpatch +self+ with the provided +patchset+, using
128
- # #unpatch!. If the sequence this is used on supports #replace, the value
129
- # of +self+ will be replaced. See Diff::LCS#unpatch. Does no patch direction
130
- # autodiscovery.
124
+ # Attempts to unpatch +self+ with the provided +patchset+, using #unpatch!.
125
+ # If the sequence this is used on supports #replace, the value of +self+ will
126
+ # be replaced. See Diff::LCS#unpatch. Does no patch direction autodiscovery.
131
127
  def unpatch_me(patchset)
132
128
  if respond_to? :replace
133
129
  replace(unpatch!(patchset))
@@ -142,29 +138,28 @@ class << Diff::LCS
142
138
  matches = Diff::LCS::Internals.lcs(seq1, seq2)
143
139
  ret = []
144
140
  string = seq1.kind_of? String
145
- matches.each_with_index do |e, i|
146
- unless matches[i].nil?
147
- v = string ? seq1[i, 1] : seq1[i]
148
- v = block[v] if block
149
- ret << v
150
- end
141
+ matches.each_with_index do |_e, i|
142
+ next if matches[i].nil?
143
+
144
+ v = string ? seq1[i, 1] : seq1[i]
145
+ v = block[v] if block
146
+ ret << v
151
147
  end
152
148
  ret
153
149
  end
154
- alias_method :LCS, :lcs
150
+ alias LCS lcs
155
151
 
156
152
  # #diff computes the smallest set of additions and deletions necessary to
157
- # turn the first sequence into the second, and returns a description of
158
- # these changes.
153
+ # turn the first sequence into the second, and returns a description of these
154
+ # changes.
159
155
  #
160
156
  # See Diff::LCS::DiffCallbacks for the default behaviour. An alternate
161
157
  # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks. If a
162
158
  # Class argument is provided for +callbacks+, #diff will attempt to
163
- # initialise it. If the +callbacks+ object (possibly initialised) responds
164
- # to #finish, it will be called.
159
+ # initialise it. If the +callbacks+ object (possibly initialised) responds to
160
+ # #finish, it will be called.
165
161
  def diff(seq1, seq2, callbacks = nil, &block) # :yields diff changes:
166
- diff_traversal(:diff, seq1, seq2, callbacks || Diff::LCS::DiffCallbacks,
167
- &block)
162
+ diff_traversal(:diff, seq1, seq2, callbacks || Diff::LCS::DiffCallbacks, &block)
168
163
  end
169
164
 
170
165
  # #sdiff computes all necessary components to show two sequences and their
@@ -179,18 +174,31 @@ class << Diff::LCS
179
174
  # See Diff::LCS::SDiffCallbacks for the default behaviour. An alternate
180
175
  # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks. If a
181
176
  # Class argument is provided for +callbacks+, #diff will attempt to
182
- # initialise it. If the +callbacks+ object (possibly initialised) responds
183
- # to #finish, it will be called.
177
+ # initialise it. If the +callbacks+ object (possibly initialised) responds to
178
+ # #finish, it will be called.
179
+ #
180
+ # Each element of a returned array is a Diff::LCS::ContextChange object,
181
+ # which can be implicitly converted to an array.
182
+ #
183
+ # Diff::LCS.sdiff(a, b).each do |action, (old_pos, old_element), (new_pos, new_element)|
184
+ # case action
185
+ # when '!'
186
+ # # replace
187
+ # when '-'
188
+ # # delete
189
+ # when '+'
190
+ # # insert
191
+ # end
192
+ # end
184
193
  def sdiff(seq1, seq2, callbacks = nil, &block) #:yields diff changes:
185
- diff_traversal(:sdiff, seq1, seq2, callbacks || Diff::LCS::SDiffCallbacks,
186
- &block)
194
+ diff_traversal(:sdiff, seq1, seq2, callbacks || Diff::LCS::SDiffCallbacks, &block)
187
195
  end
188
196
 
189
- # #traverse_sequences is the most general facility provided by this
190
- # module; #diff and #lcs are implemented as calls to it.
197
+ # #traverse_sequences is the most general facility provided by this module;
198
+ # #diff and #lcs are implemented as calls to it.
191
199
  #
192
- # The arguments to #traverse_sequences are the two sequences to traverse,
193
- # and a callback object, like this:
200
+ # The arguments to #traverse_sequences are the two sequences to traverse, and
201
+ # a callback object, like this:
194
202
  #
195
203
  # traverse_sequences(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new)
196
204
  #
@@ -218,56 +226,55 @@ class << Diff::LCS
218
226
  # ^
219
227
  # b---+
220
228
  #
221
- # If there are two arrows (+a+ and +b+) pointing to elements of sequences
222
- # +A+ and +B+, the arrows will initially point to the first elements of
223
- # their respective sequences. #traverse_sequences will advance the arrows
224
- # through the sequences one element at a time, calling a method on the
225
- # user-specified callback object before each advance. It will advance the
226
- # arrows in such a way that if there are elements <tt>A[i]</tt> and
227
- # <tt>B[j]</tt> which are both equal and part of the longest common
228
- # subsequence, there will be some moment during the execution of
229
- # #traverse_sequences when arrow +a+ is pointing to <tt>A[i]</tt> and
230
- # arrow +b+ is pointing to <tt>B[j]</tt>. When this happens,
231
- # #traverse_sequences will call <tt>callbacks#match</tt> and then it will
232
- # advance both arrows.
233
- #
234
- # Otherwise, one of the arrows is pointing to an element of its sequence
235
- # that is not part of the longest common subsequence. #traverse_sequences
236
- # will advance that arrow and will call <tt>callbacks#discard_a</tt> or
237
- # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced. If
238
- # both arrows point to elements that are not part of the longest common
239
- # subsequence, then #traverse_sequences will advance one of them and call
240
- # the appropriate callback, but it is not specified which it will call.
241
- #
242
- # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>,
243
- # and <tt>callbacks#discard_b</tt> are invoked with an event comprising
244
- # the action ("=", "+", or "-", respectively), the indicies +i+ and +j+,
245
- # and the elements <tt>A[i]</tt> and <tt>B[j]</tt>. Return values are
246
- # discarded by #traverse_sequences.
229
+ # If there are two arrows (+a+ and +b+) pointing to elements of sequences +A+
230
+ # and +B+, the arrows will initially point to the first elements of their
231
+ # respective sequences. #traverse_sequences will advance the arrows through
232
+ # the sequences one element at a time, calling a method on the user-specified
233
+ # callback object before each advance. It will advance the arrows in such a
234
+ # way that if there are elements <tt>A[i]</tt> and <tt>B[j]</tt> which are
235
+ # both equal and part of the longest common subsequence, there will be some
236
+ # moment during the execution of #traverse_sequences when arrow +a+ is
237
+ # pointing to <tt>A[i]</tt> and arrow +b+ is pointing to <tt>B[j]</tt>. When
238
+ # this happens, #traverse_sequences will call <tt>callbacks#match</tt> and
239
+ # then it will advance both arrows.
240
+ #
241
+ # Otherwise, one of the arrows is pointing to an element of its sequence that
242
+ # is not part of the longest common subsequence. #traverse_sequences will
243
+ # advance that arrow and will call <tt>callbacks#discard_a</tt> or
244
+ # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced. If both
245
+ # arrows point to elements that are not part of the longest common
246
+ # subsequence, then #traverse_sequences will advance one of them and call the
247
+ # appropriate callback, but it is not specified which it will call.
248
+ #
249
+ # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>, and
250
+ # <tt>callbacks#discard_b</tt> are invoked with an event comprising the
251
+ # action ("=", "+", or "-", respectively), the indicies +i+ and +j+, and the
252
+ # elements <tt>A[i]</tt> and <tt>B[j]</tt>. Return values are discarded by
253
+ # #traverse_sequences.
247
254
  #
248
255
  # === End of Sequences
249
256
  #
250
257
  # If arrow +a+ reaches the end of its sequence before arrow +b+ does,
251
- # #traverse_sequence will try to call <tt>callbacks#finished_a</tt> with
252
- # the last index and element of +A+ (<tt>A[-1]</tt>) and the current index
253
- # and element of +B+ (<tt>B[j]</tt>). If <tt>callbacks#finished_a</tt>
254
- # does not exist, then <tt>callbacks#discard_b</tt> will be called on each
255
- # element of +B+ until the end of the sequence is reached (the call will
256
- # be done with <tt>A[-1]</tt> and <tt>B[j]</tt> for each element).
258
+ # #traverse_sequence will try to call <tt>callbacks#finished_a</tt> with the
259
+ # last index and element of +A+ (<tt>A[-1]</tt>) and the current index and
260
+ # element of +B+ (<tt>B[j]</tt>). If <tt>callbacks#finished_a</tt> does not
261
+ # exist, then <tt>callbacks#discard_b</tt> will be called on each element of
262
+ # +B+ until the end of the sequence is reached (the call will be done with
263
+ # <tt>A[-1]</tt> and <tt>B[j]</tt> for each element).
257
264
  #
258
265
  # If +b+ reaches the end of +B+ before +a+ reaches the end of +A+,
259
266
  # <tt>callbacks#finished_b</tt> will be called with the current index and
260
267
  # element of +A+ (<tt>A[i]</tt>) and the last index and element of +B+
261
- # (<tt>A[-1]</tt>). Again, if <tt>callbacks#finished_b</tt> does not exist
262
- # on the callback object, then <tt>callbacks#discard_a</tt> will be called
263
- # on each element of +A+ until the end of the sequence is reached
264
- # (<tt>A[i]</tt> and <tt>B[-1]</tt>).
268
+ # (<tt>A[-1]</tt>). Again, if <tt>callbacks#finished_b</tt> does not exist on
269
+ # the callback object, then <tt>callbacks#discard_a</tt> will be called on
270
+ # each element of +A+ until the end of the sequence is reached (<tt>A[i]</tt>
271
+ # and <tt>B[-1]</tt>).
265
272
  #
266
273
  # There is a chance that one additional <tt>callbacks#discard_a</tt> or
267
- # <tt>callbacks#discard_b</tt> will be called after the end of the
268
- # sequence is reached, if +a+ has not yet reached the end of +A+ or +b+
269
- # has not yet reached the end of +B+.
270
- def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks, &block) #:yields change events:
274
+ # <tt>callbacks#discard_b</tt> will be called after the end of the sequence
275
+ # is reached, if +a+ has not yet reached the end of +A+ or +b+ has not yet
276
+ # reached the end of +B+.
277
+ def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks) #:yields change events:
271
278
  callbacks ||= Diff::LCS::SequenceCallbacks
272
279
  matches = Diff::LCS::Internals.lcs(seq1, seq2)
273
280
 
@@ -293,6 +300,7 @@ class << Diff::LCS
293
300
  else
294
301
  loop do
295
302
  break unless bj < b_line
303
+
296
304
  bx = string ? seq2[bj, 1] : seq2[bj]
297
305
  event = Diff::LCS::ContextChange.new('+', i, ax, bj, bx)
298
306
  event = yield event if block_given?
@@ -309,12 +317,12 @@ class << Diff::LCS
309
317
  end
310
318
  ai += 1
311
319
 
312
- # The last entry (if any) processed was a match. +ai+ and +bj+ point
313
- # just past the last matching lines in their sequences.
320
+ # The last entry (if any) processed was a match. +ai+ and +bj+ point just
321
+ # past the last matching lines in their sequences.
314
322
  while (ai < a_size) or (bj < b_size)
315
323
  # last A?
316
324
  if ai == a_size and bj < b_size
317
- if callbacks.respond_to?(:finished_a) and not run_finished_a
325
+ if callbacks.respond_to?(:finished_a) and !run_finished_a
318
326
  ax = string ? seq1[-1, 1] : seq1[-1]
319
327
  bx = string ? seq2[bj, 1] : seq2[bj]
320
328
  event = Diff::LCS::ContextChange.new('>', (a_size - 1), ax, bj, bx)
@@ -336,7 +344,7 @@ class << Diff::LCS
336
344
 
337
345
  # last B?
338
346
  if bj == b_size and ai < a_size
339
- if callbacks.respond_to?(:finished_b) and not run_finished_b
347
+ if callbacks.respond_to?(:finished_b) and !run_finished_b
340
348
  ax = string ? seq1[ai, 1] : seq1[ai]
341
349
  bx = string ? seq2[-1, 1] : seq2[-1]
342
350
  event = Diff::LCS::ContextChange.new('<', ai, ax, (b_size - 1), bx)
@@ -365,25 +373,25 @@ class << Diff::LCS
365
373
  ai += 1
366
374
  end
367
375
 
368
- if bj < b_size
369
- ax = string ? seq1[ai, 1] : seq1[ai]
370
- bx = string ? seq2[bj, 1] : seq2[bj]
371
- event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
372
- event = yield event if block_given?
373
- callbacks.discard_b(event)
374
- bj += 1
375
- end
376
+ next unless bj < b_size
377
+
378
+ ax = string ? seq1[ai, 1] : seq1[ai]
379
+ bx = string ? seq2[bj, 1] : seq2[bj]
380
+ event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
381
+ event = yield event if block_given?
382
+ callbacks.discard_b(event)
383
+ bj += 1
376
384
  end
377
385
  end
378
386
 
379
387
  # #traverse_balanced is an alternative to #traverse_sequences. It uses a
380
- # different algorithm to iterate through the entries in the computed
381
- # longest common subsequence. Instead of viewing the changes as insertions
382
- # or deletions from one of the sequences, #traverse_balanced will report
388
+ # different algorithm to iterate through the entries in the computed longest
389
+ # common subsequence. Instead of viewing the changes as insertions or
390
+ # deletions from one of the sequences, #traverse_balanced will report
383
391
  # <em>changes</em> between the sequences.
384
392
  #
385
- # The arguments to #traverse_balanced are the two sequences to traverse
386
- # and a callback object, like this:
393
+ # The arguments to #traverse_balanced are the two sequences to traverse and a
394
+ # callback object, like this:
387
395
  #
388
396
  # traverse_balanced(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new)
389
397
  #
@@ -419,24 +427,23 @@ class << Diff::LCS
419
427
  #
420
428
  # === Matches
421
429
  #
422
- # If there are two arrows (+a+ and +b+) pointing to elements of sequences
423
- # +A+ and +B+, the arrows will initially point to the first elements of
424
- # their respective sequences. #traverse_sequences will advance the arrows
425
- # through the sequences one element at a time, calling a method on the
426
- # user-specified callback object before each advance. It will advance the
427
- # arrows in such a way that if there are elements <tt>A[i]</tt> and
428
- # <tt>B[j]</tt> which are both equal and part of the longest common
429
- # subsequence, there will be some moment during the execution of
430
- # #traverse_sequences when arrow +a+ is pointing to <tt>A[i]</tt> and
431
- # arrow +b+ is pointing to <tt>B[j]</tt>. When this happens,
432
- # #traverse_sequences will call <tt>callbacks#match</tt> and then it will
433
- # advance both arrows.
430
+ # If there are two arrows (+a+ and +b+) pointing to elements of sequences +A+
431
+ # and +B+, the arrows will initially point to the first elements of their
432
+ # respective sequences. #traverse_sequences will advance the arrows through
433
+ # the sequences one element at a time, calling a method on the user-specified
434
+ # callback object before each advance. It will advance the arrows in such a
435
+ # way that if there are elements <tt>A[i]</tt> and <tt>B[j]</tt> which are
436
+ # both equal and part of the longest common subsequence, there will be some
437
+ # moment during the execution of #traverse_sequences when arrow +a+ is
438
+ # pointing to <tt>A[i]</tt> and arrow +b+ is pointing to <tt>B[j]</tt>. When
439
+ # this happens, #traverse_sequences will call <tt>callbacks#match</tt> and
440
+ # then it will advance both arrows.
434
441
  #
435
442
  # === Discards
436
443
  #
437
- # Otherwise, one of the arrows is pointing to an element of its sequence
438
- # that is not part of the longest common subsequence. #traverse_sequences
439
- # will advance that arrow and will call <tt>callbacks#discard_a</tt> or
444
+ # Otherwise, one of the arrows is pointing to an element of its sequence that
445
+ # is not part of the longest common subsequence. #traverse_sequences will
446
+ # advance that arrow and will call <tt>callbacks#discard_a</tt> or
440
447
  # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced.
441
448
  #
442
449
  # === Changes
@@ -450,14 +457,14 @@ class << Diff::LCS
450
457
  #
451
458
  # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>,
452
459
  # <tt>callbacks#discard_b</tt>, and <tt>callbacks#change</tt> are invoked
453
- # with an event comprising the action ("=", "+", "-", or "!",
454
- # respectively), the indicies +i+ and +j+, and the elements
455
- # <tt>A[i]</tt> and <tt>B[j]</tt>. Return values are discarded by
456
- # #traverse_balanced.
460
+ # with an event comprising the action ("=", "+", "-", or "!", respectively),
461
+ # the indicies +i+ and +j+, and the elements <tt>A[i]</tt> and <tt>B[j]</tt>.
462
+ # Return values are discarded by #traverse_balanced.
457
463
  #
458
464
  # === Context
459
- # Note that +i+ and +j+ may not be the same index position, even if +a+
460
- # and +b+ are considered to be pointing to matching or changed elements.
465
+ #
466
+ # Note that +i+ and +j+ may not be the same index position, even if +a+ and
467
+ # +b+ are considered to be pointing to matching or changed elements.
461
468
  def traverse_balanced(seq1, seq2, callbacks = Diff::LCS::BalancedCallbacks)
462
469
  matches = Diff::LCS::Internals.lcs(seq1, seq2)
463
470
  a_size = seq1.size
@@ -475,6 +482,7 @@ class << Diff::LCS
475
482
  end
476
483
 
477
484
  break if ma >= matches.size # end of matches?
485
+
478
486
  mb = matches[ma]
479
487
 
480
488
  # Change(seq2)
@@ -489,7 +497,6 @@ class << Diff::LCS
489
497
  event = yield event if block_given?
490
498
  callbacks.change(event)
491
499
  ai += 1
492
- bj += 1
493
500
  else
494
501
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
495
502
  event = yield event if block_given?
@@ -499,8 +506,9 @@ class << Diff::LCS
499
506
  event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
500
507
  event = yield event if block_given?
501
508
  callbacks.discard_b(event)
502
- bj += 1
503
509
  end
510
+
511
+ bj += 1
504
512
  when [true, false]
505
513
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
506
514
  event = yield event if block_given?
@@ -535,7 +543,6 @@ class << Diff::LCS
535
543
  event = yield event if block_given?
536
544
  callbacks.change(event)
537
545
  ai += 1
538
- bj += 1
539
546
  else
540
547
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
541
548
  event = yield event if block_given?
@@ -545,8 +552,9 @@ class << Diff::LCS
545
552
  event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
546
553
  event = yield event if block_given?
547
554
  callbacks.discard_b(event)
548
- bj += 1
549
555
  end
556
+
557
+ bj += 1
550
558
  when [true, false]
551
559
  event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
552
560
  event = yield event if block_given?
@@ -562,9 +570,9 @@ class << Diff::LCS
562
570
  end
563
571
 
564
572
  PATCH_MAP = { #:nodoc:
565
- :patch => { '+' => '+', '-' => '-', '!' => '!', '=' => '=' },
566
- :unpatch => { '+' => '-', '-' => '+', '!' => '!', '=' => '=' }
567
- }
573
+ :patch => { '+' => '+', '-' => '-', '!' => '!', '=' => '=' }.freeze,
574
+ :unpatch => { '+' => '-', '-' => '+', '!' => '!', '=' => '=' }.freeze
575
+ }.freeze
568
576
 
569
577
  # Applies a +patchset+ to the sequence +src+ according to the +direction+
570
578
  # (<tt>:patch</tt> or <tt>:unpatch</tt>), producing a new sequence.
@@ -577,23 +585,23 @@ class << Diff::LCS
577
585
  #
578
586
  # patch(s1, diff(s1, s2)) -> s2
579
587
  #
580
- # A +patchset+ can be considered to apply backward (<tt>:unpatch</tt>) if
581
- # the following expression is true:
588
+ # A +patchset+ can be considered to apply backward (<tt>:unpatch</tt>) if the
589
+ # following expression is true:
582
590
  #
583
591
  # patch(s2, diff(s1, s2)) -> s1
584
592
  #
585
- # If the +patchset+ contains no changes, the +src+ value will be returned
586
- # as either <tt>src.dup</tt> or +src+. A +patchset+ can be deemed as
587
- # having no changes if the following predicate returns true:
593
+ # If the +patchset+ contains no changes, the +src+ value will be returned as
594
+ # either <tt>src.dup</tt> or +src+. A +patchset+ can be deemed as having no
595
+ # changes if the following predicate returns true:
588
596
  #
589
597
  # patchset.empty? or
590
- # patchset.flatten.all? { |change| change.unchanged? }
598
+ # patchset.flatten(1).all? { |change| change.unchanged? }
591
599
  #
592
600
  # === Patchsets
593
601
  #
594
- # A +patchset+ is always an enumerable sequence of changes, hunks of
595
- # changes, or a mix of the two. A hunk of changes is an enumerable
596
- # sequence of changes:
602
+ # A +patchset+ is always an enumerable sequence of changes, hunks of changes,
603
+ # or a mix of the two. A hunk of changes is an enumerable sequence of
604
+ # changes:
597
605
  #
598
606
  # [ # patchset
599
607
  # # change
@@ -602,18 +610,15 @@ class << Diff::LCS
602
610
  # ]
603
611
  # ]
604
612
  #
605
- # The +patch+ method accepts <tt>patchset</tt>s that are enumerable
606
- # sequences containing either Diff::LCS::Change objects (or a subclass) or
607
- # the array representations of those objects. Prior to application, array
613
+ # The +patch+ method accepts <tt>patchset</tt>s that are enumerable sequences
614
+ # containing either Diff::LCS::Change objects (or a subclass) or the array
615
+ # representations of those objects. Prior to application, array
608
616
  # representations of Diff::LCS::Change objects will be reified.
609
617
  def patch(src, patchset, direction = nil)
610
618
  # Normalize the patchset.
611
619
  has_changes, patchset = Diff::LCS::Internals.analyze_patchset(patchset)
612
620
 
613
- if not has_changes
614
- return src.dup if src.respond_to? :dup
615
- return src
616
- end
621
+ return src.respond_to?(:dup) ? src.dup : src unless has_changes
617
622
 
618
623
  string = src.kind_of?(String)
619
624
  # Start with a new empty type of the source's class
@@ -625,7 +630,7 @@ class << Diff::LCS
625
630
 
626
631
  patch_map = PATCH_MAP[direction]
627
632
 
628
- patchset.flatten.each do |change|
633
+ patchset.each do |change|
629
634
  # Both Change and ContextChange support #action
630
635
  action = patch_map[change.action]
631
636
 
@@ -657,8 +662,8 @@ class << Diff::LCS
657
662
  bj += 1
658
663
  end
659
664
 
660
- res << el
661
- bj += 1
665
+ res << el
666
+ bj += 1
662
667
  when '='
663
668
  # This only appears in sdiff output with the SDiff callback.
664
669
  # Therefore, we only need to worry about dealing with a single
@@ -674,10 +679,10 @@ class << Diff::LCS
674
679
  bj += 1
675
680
  end
676
681
 
677
- bj += 1
678
- ai += 1
682
+ bj += 1
683
+ ai += 1
679
684
 
680
- res << el
685
+ res << el
681
686
  end
682
687
  when Diff::LCS::Change
683
688
  case action
@@ -711,15 +716,17 @@ class << Diff::LCS
711
716
  res
712
717
  end
713
718
 
714
- # Given a set of patchset, convert the current version to the prior
715
- # version. Does no auto-discovery.
719
+ # Given a set of patchset, convert the current version to the prior version.
720
+ # Does no auto-discovery.
716
721
  def unpatch!(src, patchset)
717
722
  patch(src, patchset, :unpatch)
718
723
  end
719
724
 
720
- # Given a set of patchset, convert the current version to the next
721
- # version. Does no auto-discovery.
725
+ # Given a set of patchset, convert the current version to the next version.
726
+ # Does no auto-discovery.
722
727
  def patch!(src, patchset)
723
728
  patch(src, patchset, :patch)
724
729
  end
725
730
  end
731
+
732
+ require 'diff/lcs/backports'