diff-lcs 1.6.1 → 2.0.0.beta.1

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.
@@ -1,22 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class << Diff::LCS
4
+ def callbacks_for(callbacks) # :nodoc:
5
+ callbacks.new
6
+ rescue
7
+ callbacks
8
+ end
9
+ private :callbacks_for
10
+
4
11
  def diff_traversal(method, seq1, seq2, callbacks, &block)
5
12
  callbacks = callbacks_for(callbacks)
13
+
6
14
  case method
7
15
  when :diff
8
16
  traverse_sequences(seq1, seq2, callbacks)
9
17
  when :sdiff
10
18
  traverse_balanced(seq1, seq2, callbacks)
11
19
  end
20
+
12
21
  callbacks.finish if callbacks.respond_to? :finish
13
22
 
14
23
  if block
15
24
  callbacks.diffs.map do |hunk|
16
25
  if hunk.is_a? Array
17
- hunk.map { |hunk_block| block[hunk_block] }
26
+ hunk.map { block.call(_1) }
18
27
  else
19
- block[hunk]
28
+ block.call(hunk)
20
29
  end
21
30
  end
22
31
  else
@@ -27,18 +36,16 @@ class << Diff::LCS
27
36
  end
28
37
 
29
38
  module Diff::LCS::Internals # :nodoc:
30
- end
31
-
32
- class << Diff::LCS::Internals
33
- # Compute the longest common subsequence between the sequenced
34
- # Enumerables +a+ and +b+. The result is an array whose contents is such
35
- # that
39
+ # Compute the longest common subsequence between the sequenced enumerable values `a` and
40
+ # `b`. The result is an array whose contents is such that
36
41
  #
37
- # result = Diff::LCS::Internals.lcs(a, b)
38
- # result.each_with_index do |e, i|
39
- # assert_equal(a[i], b[e]) unless e.nil?
40
- # end
41
- def lcs(a, b)
42
+ # ```ruby
43
+ # result = Diff::LCS::Internals.lcs(a, b)
44
+ # result.each_with_index do |e, i|
45
+ # assert_equal(a[i], b[e]) unless e.nil?
46
+ # end
47
+ # ```
48
+ def self.lcs(a, b)
42
49
  a_start = b_start = 0
43
50
  a_finish = a.size - 1
44
51
  b_finish = b.size - 1
@@ -58,21 +65,20 @@ class << Diff::LCS::Internals
58
65
  b_finish -= 1
59
66
  end
60
67
 
61
- # Now, compute the equivalence classes of positions of elements.
62
- # An explanation for how this works: https://codeforces.com/topic/92191
68
+ # Now, compute the equivalence classes of positions of elements. An explanation for
69
+ # how this works: https://codeforces.com/topic/92191
63
70
  b_matches = position_hash(b, b_start..b_finish)
64
71
 
65
72
  thresh = []
66
73
  links = []
67
- string = a.is_a?(String)
68
74
 
69
75
  (a_start..a_finish).each do |i|
70
- ai = string ? a[i, 1] : a[i]
76
+ ai = a[i]
71
77
  bm = b_matches[ai]
72
78
  k = nil
73
79
  bm.reverse_each do |j|
74
- # Although the threshold check is not mandatory for this to work,
75
- # it may have an optimization purpose
80
+ # Although the threshold check is not mandatory for this to work, it may have an
81
+ # optimization purpose.
76
82
  # An attempt to remove it: https://github.com/halostatue/diff-lcs/pull/72
77
83
  # Why it is reintroduced: https://github.com/halostatue/diff-lcs/issues/78
78
84
  if k && (thresh[k] > j) && (thresh[k - 1] < j)
@@ -95,11 +101,10 @@ class << Diff::LCS::Internals
95
101
  vector
96
102
  end
97
103
 
98
- # This method will analyze the provided patchset to provide a single-pass
99
- # normalization (conversion of the array form of Diff::LCS::Change objects to
100
- # the object form of same) and detection of whether the patchset represents
101
- # changes to be made.
102
- def analyze_patchset(patchset, depth = 0)
104
+ # This method will analyze the provided patchset to provide a single-pass normalization
105
+ # (conversion of the array form of Diff::LCS::Change objects to the object form of same)
106
+ # and detection of whether the patchset represents changes to be made.
107
+ def self.analyze_patchset(patchset, depth = 0)
103
108
  fail "Patchset too complex" if depth > 1
104
109
 
105
110
  has_changes = false
@@ -115,7 +120,7 @@ class << Diff::LCS::Internals
115
120
 
116
121
  patchset.each do |hunk|
117
122
  case hunk
118
- when Diff::LCS::Change
123
+ when Diff::LCS::Change, Diff::LCS::ContextChange
119
124
  has_changes ||= !hunk.unchanged?
120
125
  new_patchset << hunk
121
126
  when Array
@@ -137,15 +142,13 @@ class << Diff::LCS::Internals
137
142
  [has_changes, new_patchset]
138
143
  end
139
144
 
140
- # Examine the patchset and the source to see in which direction the
141
- # patch should be applied.
145
+ # Examine the patchset and the source to see in which direction the patch should be
146
+ # applied.
142
147
  #
143
- # WARNING: By default, this examines the whole patch, so this could take
144
- # some time. This also works better with Diff::LCS::ContextChange or
145
- # Diff::LCS::Change as its source, as an array will cause the creation
146
- # of one of the above.
147
- def intuit_diff_direction(src, patchset, limit = nil)
148
- string = src.is_a?(String)
148
+ # WARNING: By default, this examines the whole patch, so this could take some time. This
149
+ # also works better with Diff::LCS::ContextChange or Diff::LCS::Change as its source, as
150
+ # an array will cause the creation of one of the above.
151
+ def self.intuit_diff_direction(src, patchset, limit = nil)
149
152
  count = left_match = left_miss = right_match = right_miss = 0
150
153
 
151
154
  patchset.each do |change|
@@ -153,8 +156,8 @@ class << Diff::LCS::Internals
153
156
 
154
157
  case change
155
158
  when Diff::LCS::ContextChange
156
- le = string ? src[change.old_position, 1] : src[change.old_position]
157
- re = string ? src[change.new_position, 1] : src[change.new_position]
159
+ le = src[change.old_position]
160
+ re = src[change.new_position]
158
161
 
159
162
  case change.action
160
163
  when "-" # Remove details from the old string
@@ -183,10 +186,10 @@ class << Diff::LCS::Internals
183
186
  end
184
187
  end
185
188
  when Diff::LCS::Change
186
- # With a simplistic change, we can't tell the difference between
187
- # the left and right on '!' actions, so we ignore those. On '='
188
- # actions, if there's a miss, we miss both left and right.
189
- element = string ? src[change.position, 1] : src[change.position]
189
+ # With a simplistic change, we can't tell the difference between the left and
190
+ # right on '!' actions, so we ignore those. On '=' actions, if there's a miss, we
191
+ # miss both left and right.
192
+ element = src[change.position]
190
193
 
191
194
  case change.action
192
195
  when "-"
@@ -235,74 +238,67 @@ class << Diff::LCS::Internals
235
238
  :patch
236
239
  end
237
240
  else
238
- fail "The provided patchset does not appear to apply to the provided \
239
- enumerable as either source or destination value."
241
+ fail "The provided patchset does not appear to apply to the provided enumerable as either source or destination value."
240
242
  end
241
243
  end
242
244
  end
243
245
 
244
- # Find the place at which +value+ would normally be inserted into the
245
- # Enumerable. If that place is already occupied by +value+, do nothing
246
- # and return +nil+. If the place does not exist (i.e., it is off the end
247
- # of the Enumerable), add it to the end. Otherwise, replace the element
248
- # at that point with +value+. It is assumed that the Enumerable's values
249
- # are numeric.
250
- #
251
- # This operation preserves the sort order.
252
- def replace_next_larger(enum, value, last_index = nil)
253
- # Off the end?
254
- if enum.empty? || (value > enum[-1])
255
- enum << value
256
- return enum.size - 1
257
- end
246
+ class << self
247
+ # Find the place at which `value` would normally be inserted into the Enumerable. If
248
+ # that place is already occupied by `value`, do nothing and return `nil`. If the place
249
+ # does not exist (i.e., it is off the end of the Enumerable), add it to the end.
250
+ # Otherwise, replace the element at that point with `value`. It is assumed that the
251
+ # Enumerable's values are numeric.
252
+ #
253
+ # This operation preserves the sort order.
254
+ def replace_next_larger(enum, value, last_index = nil)
255
+ # Off the end?
256
+ if enum.empty? || (value > enum[-1])
257
+ enum << value
258
+ return enum.size - 1
259
+ end
258
260
 
259
- # Binary search for the insertion point
260
- last_index ||= enum.size - 1
261
- first_index = 0
262
- while first_index <= last_index
263
- i = (first_index + last_index) >> 1
261
+ # Binary search for the insertion point
262
+ last_index ||= enum.size - 1
263
+ first_index = 0
264
+ while first_index <= last_index
265
+ i = (first_index + last_index) >> 1
264
266
 
265
- found = enum[i]
267
+ found = enum[i]
266
268
 
267
- return nil if value == found
269
+ return nil if value == found
268
270
 
269
- if value > found
270
- first_index = i + 1
271
- else
272
- last_index = i - 1
271
+ if value > found
272
+ first_index = i + 1
273
+ else
274
+ last_index = i - 1
275
+ end
273
276
  end
274
- end
275
277
 
276
- # The insertion point is in first_index; overwrite the next larger
277
- # value.
278
- enum[first_index] = value
279
- first_index
280
- end
281
- private :replace_next_larger
282
-
283
- # If +vector+ maps the matching elements of another collection onto this
284
- # Enumerable, compute the inverse of +vector+ that maps this Enumerable
285
- # onto the collection. (Currently unused.)
286
- def inverse_vector(a, vector)
287
- inverse = a.dup
288
- (0...vector.size).each do |i|
289
- inverse[vector[i]] = i unless vector[i].nil?
278
+ # The insertion point is in first_index; overwrite the next larger value.
279
+ enum[first_index] = value
280
+ first_index
290
281
  end
291
- inverse
292
- end
293
- private :inverse_vector
294
-
295
- # Returns a hash mapping each element of an Enumerable to the set of
296
- # positions it occupies in the Enumerable, optionally restricted to the
297
- # elements specified in the range of indexes specified by +interval+.
298
- def position_hash(enum, interval)
299
- string = enum.is_a?(String)
300
- hash = Hash.new { |h, k| h[k] = [] }
301
- interval.each do |i|
302
- k = string ? enum[i, 1] : enum[i]
303
- hash[k] << i
282
+ private :replace_next_larger
283
+
284
+ # If `vector` maps the matching elements of another collection onto this Enumerable,
285
+ # compute the inverse of `vector` that maps this Enumerable onto the collection.
286
+ # (Currently unused.)
287
+ def inverse_vector(a, vector)
288
+ inverse = a.dup
289
+ (0...vector.size).each do
290
+ inverse[vector[_1]] = i unless vector[_1].nil?
291
+ end
292
+ inverse
293
+ end
294
+ private :inverse_vector
295
+
296
+ # Returns a hash mapping each element of an Enumerable to the set of positions it
297
+ # occupies in the Enumerable, optionally restricted to the elements specified in the
298
+ # range of indexes specified by `interval`.
299
+ def position_hash(enum, interval)
300
+ Hash.new { |h, k| h[k] = [] }.tap { |hash| interval.each { hash[enum[_1]] << _1 } }
304
301
  end
305
- hash
302
+ private :position_hash
306
303
  end
307
- private :position_hash
308
304
  end
@@ -4,19 +4,17 @@ require "optparse"
4
4
  require "diff/lcs/hunk"
5
5
 
6
6
  class Diff::LCS::Ldiff # :nodoc:
7
- # standard:disable Layout/HeredocIndentation
8
- BANNER = <<-COPYRIGHT
9
- ldiff #{Diff::LCS::VERSION}
10
- Copyright 2004-2025 Austin Ziegler
7
+ BANNER = <<~COPYRIGHT
8
+ ldiff #{Diff::LCS::VERSION}
9
+ Copyright 2004-2025 Austin Ziegler
11
10
 
12
- Part of Diff::LCS.
13
- https://github.com/halostatue/diff-lcs
11
+ Part of Diff::LCS.
12
+ https://github.com/halostatue/diff-lcs
14
13
 
15
- This program is free software. It may be redistributed and/or modified under
16
- the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
17
- MIT licence.
14
+ This program is free software. It may be redistributed and/or modified under
15
+ the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
16
+ MIT licence.
18
17
  COPYRIGHT
19
- # standard:enable Layout/HeredocIndentation
20
18
 
21
19
  InputInfo = Struct.new(:filename, :data, :stat) do
22
20
  def initialize(filename)
@@ -56,12 +54,6 @@ ldiff #{Diff::LCS::VERSION}
56
54
  @format = :unified
57
55
  @lines = ctx || 3
58
56
  end
59
- o.on("-e", "Creates an 'ed' script to change", "oldfile to newfile.") do |_ctx|
60
- @format = :ed
61
- end
62
- o.on("-f", "Creates an 'ed' script to change", "oldfile to newfile in reverse order.") do |_ctx|
63
- @format = :reverse_ed
64
- end
65
57
  o.on(
66
58
  "-a", "--text",
67
59
  "Treat the files as text and compare them", "line-by-line, even if they do not seem", "to be text."
@@ -117,8 +109,8 @@ ldiff #{Diff::LCS::VERSION}
117
109
  char_new = "+" * 3
118
110
  end
119
111
 
120
- # After we've read up to a certain point in each file, the number of
121
- # items we've read from each file will differ by FLD (could be 0).
112
+ # After we've read up to a certain point in each file, the number of items we've read
113
+ # from each file will differ by FLD (could be 0).
122
114
  file_length_difference = 0
123
115
 
124
116
  # Test binary status
@@ -155,26 +147,23 @@ ldiff #{Diff::LCS::VERSION}
155
147
  ft = info_new.stat.mtime.localtime.strftime("%Y-%m-%d %H:%M:%S.000000000 %z")
156
148
  output << "#{char_new} #{info_new.filename}\t#{ft}\n"
157
149
  when :ed
158
- real_output = output
159
150
  output = []
160
151
  end
161
152
 
162
- # Loop over hunks. If a hunk overlaps with the last hunk, join them.
163
- # Otherwise, print out the old one.
153
+ # Loop over hunks. If a hunk overlaps with the last hunk, join them. Otherwise, print
154
+ # out the old one.
164
155
  oldhunk = hunk = nil
165
156
  diffs.each do |piece|
166
- begin
167
- hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, lines, file_length_difference)
168
- file_length_difference = hunk.file_length_difference
157
+ hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, lines, file_length_difference)
158
+ file_length_difference = hunk.file_length_difference
169
159
 
170
- next unless oldhunk
171
- next if lines.positive? && hunk.merge(oldhunk)
160
+ next unless oldhunk
161
+ next if lines.positive? && hunk.merge(oldhunk)
172
162
 
173
- output << oldhunk.diff(format)
174
- output << "\n" if format == :unified
175
- ensure
176
- oldhunk = hunk
177
- end
163
+ output << oldhunk.diff(format)
164
+ output << "\n" if format == :unified
165
+ ensure
166
+ oldhunk = hunk
178
167
  end
179
168
 
180
169
  last = oldhunk.diff(format, true)
@@ -182,8 +171,6 @@ ldiff #{Diff::LCS::VERSION}
182
171
 
183
172
  output << last
184
173
 
185
- output.reverse_each { |e| real_output << e.diff(:ed_finish, e == output[0]) } if format == :ed
186
-
187
- true
174
+ 1
188
175
  end
189
176
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Diff
4
4
  module LCS
5
- VERSION = "1.6.1"
5
+ VERSION = "2.0.0.beta.1"
6
6
  end
7
7
  end