Class: Refiner
Overview
Compute longest common substring based diff between two strings.
The diff format is first the old string:
-
in red
-
with each line prefixed with minuses
-
removed characters highlighted in inverse video
Then comes the new string:
-
in green
-
with each line prefixed with plusses
-
added characters highlighted in inverse video
Constant Summary collapse
- REFINEMENT_THRESHOLD =
If either old or new would get more than this percentage of chars highlighted, consider this to be a replacement rather than a change and just don’t highlight anything.
30
Constants included from Colors
Colors::BOLD, Colors::CYAN, Colors::ESC, Colors::GREEN, Colors::NOT_REVERSE, Colors::RED, Colors::RESET, Colors::REVERSE
Instance Attribute Summary collapse
-
#refined_new ⇒ Object
readonly
Returns the value of attribute refined_new.
-
#refined_old ⇒ Object
readonly
Returns the value of attribute refined_old.
Instance Method Summary collapse
- #censor_highlights(old, new, old_highlights, new_highlights) ⇒ Object
- #collect_highlights(diff, old_highlights, new_highlights) ⇒ Object
-
#initialize(old, new) ⇒ Refiner
constructor
A new instance of Refiner.
- #should_highlight?(old, new) ⇒ Boolean
Methods included from Colors
Constructor Details
#initialize(old, new) ⇒ Refiner
Returns a new instance of Refiner.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/refiner.rb', line 65 def initialize(old, new) old_highlights = Set.new new_highlights = Set.new if should_highlight?(old, new) collect_highlights(Diff::LCS.diff(old, new), old_highlights, new_highlights) censor_highlights(old, new, old_highlights, new_highlights) end @refined_old = DiffString.new('-', RED) old.each_char.with_index do |char, index| @refined_old.add(char, old_highlights.include?(index)) end @refined_new = DiffString.new('+', GREEN) new.each_char.with_index do |char, index| @refined_new.add(char, new_highlights.include?(index)) end end |
Instance Attribute Details
#refined_new ⇒ Object (readonly)
Returns the value of attribute refined_new.
20 21 22 |
# File 'lib/refiner.rb', line 20 def refined_new @refined_new end |
#refined_old ⇒ Object (readonly)
Returns the value of attribute refined_old.
19 20 21 |
# File 'lib/refiner.rb', line 19 def refined_old @refined_old end |
Instance Method Details
#censor_highlights(old, new, old_highlights, new_highlights) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/refiner.rb', line 42 def censor_highlights(old, new, old_highlights, new_highlights) old_highlights_percentage = 100 * old_highlights.size / old.length new_highlights_percentage = 100 * new_highlights.size / new.length if old_highlights_percentage > REFINEMENT_THRESHOLD \ || new_highlights_percentage > REFINEMENT_THRESHOLD # We'll consider this a replacement rather than a change, don't # highlight it. old_highlights.clear new_highlights.clear end end |
#collect_highlights(diff, old_highlights, new_highlights) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/refiner.rb', line 27 def collect_highlights(diff, old_highlights, new_highlights) diff.each do |section| section.each do |highlight| case highlight.action when '-' old_highlights << highlight.position when '+' new_highlights << highlight.position else fail("Unsupported diff type: <#{type}>") end end end end |
#should_highlight?(old, new) ⇒ Boolean
55 56 57 58 59 60 61 62 63 |
# File 'lib/refiner.rb', line 55 def should_highlight?(old, new) return false if old.empty? || new.empty? # The 15_000 constant has been determined using the "benchmark" # program in our bin/ directory. return false if old.length + new.length > 15_000 return true end |