diff-lcs 1.1.2 → 1.1.3

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.
@@ -10,7 +10,7 @@
10
10
  # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
11
11
  # Ruby licence.
12
12
  #
13
- # $Id: array.rb,v 1.3 2004/08/08 20:33:09 austin Exp $
13
+ # $Id$
14
14
  #++
15
15
  # Includes Diff::LCS into the Array built-in class.
16
16
 
@@ -10,7 +10,7 @@
10
10
  # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
11
11
  # Ruby licence.
12
12
  #
13
- # $Id: block.rb,v 1.3 2004/08/08 20:33:09 austin Exp $
13
+ # $Id$
14
14
  #++
15
15
  # Contains Diff::LCS::Block for bin/ldiff.
16
16
 
@@ -10,7 +10,7 @@
10
10
  # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
11
11
  # Ruby licence.
12
12
  #
13
- # $Id: callbacks.rb,v 1.4 2004/09/14 18:51:26 austin Exp $
13
+ # $Id$
14
14
  #++
15
15
  # Contains definitions for all default callback objects.
16
16
 
@@ -10,7 +10,7 @@
10
10
  # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
11
11
  # Ruby licence.
12
12
  #
13
- # $Id: change.rb,v 1.4 2004/08/08 20:33:09 austin Exp $
13
+ # $Id$
14
14
  #++
15
15
  # Provides Diff::LCS::Change and Diff::LCS::ContextChange.
16
16
 
@@ -0,0 +1,151 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ require 'cgi'
4
+
5
+ class Diff::LCS::HTMLDiff
6
+ class << self
7
+ attr_accessor :can_expand_tabs #:nodoc:
8
+ end
9
+ self.can_expand_tabs = true
10
+
11
+ class Callbacks
12
+ attr_accessor :output
13
+ attr_accessor :match_class
14
+ attr_accessor :only_a_class
15
+ attr_accessor :only_b_class
16
+
17
+ def initialize(output, options = {})
18
+ @output = output
19
+ options ||= {}
20
+
21
+ @match_class = options[:match_class] || "match"
22
+ @only_a_class = options[:only_a_class] || "only_a"
23
+ @only_b_class = options[:only_b_class] || "only_b"
24
+ end
25
+
26
+ def htmlize(element, css_class)
27
+ element = "&nbsp;" if element.empty?
28
+ %Q|<pre class="#{__send__(css_class)}">#{element}</pre>\n|
29
+ end
30
+ private :htmlize
31
+
32
+ # This will be called with both lines are the same
33
+ def match(event)
34
+ @output << htmlize(event.old_element, :match_class)
35
+ end
36
+
37
+ # This will be called when there is a line in A that isn't in B
38
+ def discard_a(event)
39
+ @output << htmlize(event.old_element, :only_a_class)
40
+ end
41
+
42
+ # This will be called when there is a line in B that isn't in A
43
+ def discard_b(event)
44
+ @output << htmlize(event.new_element, :only_b_class)
45
+ end
46
+ end
47
+
48
+ DEFAULT_OPTIONS = {
49
+ :expand_tabs => nil,
50
+ :output => nil,
51
+ :css => nil,
52
+ :title => nil,
53
+ }
54
+
55
+ DEFAULT_CSS = <<-CSS
56
+ body { margin: 0; }
57
+ .diff
58
+ {
59
+ border: 1px solid black;
60
+ margin: 1em 2em;
61
+ }
62
+ p
63
+ {
64
+ margin-left: 2em;
65
+ }
66
+ pre
67
+ {
68
+ padding-left: 1em;
69
+ margin: 0;
70
+ font-family: Inconsolata, Consolas, Lucida, Courier, monospaced;
71
+ white-space: pre;
72
+ }
73
+ .match { }
74
+ .only_a
75
+ {
76
+ background-color: #fdd;
77
+ color: red;
78
+ text-decoration: line-through;
79
+ }
80
+ .only_b
81
+ {
82
+ background-color: #ddf;
83
+ color: blue;
84
+ border-left: 3px solid blue
85
+ }
86
+ h1 { margin-left: 2em; }
87
+ CSS
88
+
89
+ def initialize(left, right, options = nil)
90
+ @left = left
91
+ @right = right
92
+ @options = options
93
+
94
+ @options = DEFAULT_OPTIONS.dup if @options.nil?
95
+ end
96
+
97
+ def verify_options
98
+ @options[:expand_tabs] ||= 4
99
+ @options[:expand_tabs] = 4 if @options[:expand_tabs] < 0
100
+
101
+ @options[:output] ||= $stdout
102
+
103
+ @options[:css] ||= DEFAULT_CSS.dup
104
+
105
+ @options[:title] ||= "diff"
106
+ end
107
+ private :verify_options
108
+
109
+ attr_reader :options
110
+
111
+ def run
112
+ verify_options
113
+
114
+ if @options[:expand_tabs] > 0 && self.class.can_expand_tabs
115
+ formatter = Text::Format.new
116
+ formatter.tabstop = @options[:expand_tabs]
117
+
118
+ @left = left.map { |line| formatter.expand(line.chomp) }
119
+ @right = right.map { |line| formatter.expand(line.chomp) }
120
+ end
121
+
122
+ @left.map! { |line| CGI.escapeHTML(line.chomp) }
123
+ @right.map! { |line| CGI.escapeHTML(line.chomp) }
124
+
125
+ @options[:output] << <<-OUTPUT
126
+ <html>
127
+ <head>
128
+ <title>#{@options[:title]}</title>
129
+ <style type="text/css">
130
+ #{@options[:css]}
131
+ </style>
132
+ </head>
133
+ <body>
134
+ <h1>#{@options[:title]}</h1>
135
+ <p>Legend: <span class="only_a">Only in Old</span>&nbsp;
136
+ <span class="only_b">Only in New</span></p>
137
+ <div class="diff">
138
+ OUTPUT
139
+
140
+ callbacks = Callbacks.new(@options[:output])
141
+ Diff::LCS.traverse_sequences(@left, @right, callbacks)
142
+
143
+ @options[:output] << <<-OUTPUT
144
+ </div>
145
+ </body>
146
+ </html>
147
+ OUTPUT
148
+ end
149
+ end
150
+
151
+ # vim: ft=ruby
@@ -1,19 +1,3 @@
1
- #! /usr/env/bin ruby
2
- #--
3
- # Copyright 2004 Austin Ziegler <diff-lcs@halostatue.ca>
4
- # adapted from:
5
- # Algorithm::Diff (Perl) by Ned Konz <perl@bike-nomad.com>
6
- # Smalltalk by Mario I. Wolczko <mario@wolczko.com>
7
- # implements McIlroy-Hunt diff algorithm
8
- #
9
- # This program is free software. It may be redistributed and/or modified under
10
- # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
11
- # Ruby licence.
12
- #
13
- # $Id: hunk.rb,v 1.2 2004/08/08 20:33:09 austin Exp $
14
- #++
15
- # Contains Diff::LCS::Hunk for bin/ldiff.
16
-
17
1
  require 'diff/lcs/block'
18
2
 
19
3
  # A Hunk is a group of Blocks which overlap because of the context
@@ -66,6 +50,7 @@ class Diff::LCS::Hunk
66
50
  # Change the "start" and "end" fields to note that context should be added
67
51
  # to this hunk
68
52
  attr_accessor :flag_context
53
+ undef :flag_context=
69
54
  def flag_context=(context) #:nodoc:
70
55
  return if context.nil? or context.zero?
71
56
 
@@ -33,7 +33,7 @@ require 'diff/lcs/hunk'
33
33
  module Diff::LCS::Ldiff
34
34
  BANNER = <<-COPYRIGHT
35
35
  ldiff #{Diff::LCS::VERSION}
36
- Copyright 2004 Austin Ziegler
36
+ Copyright 2004-2011 Austin Ziegler
37
37
 
38
38
  Part of Diff::LCS.
39
39
  http://rubyforge.org/projects/ruwiki/
@@ -42,67 +42,51 @@ ldiff #{Diff::LCS::VERSION}
42
42
 
43
43
  This program is free software. It may be redistributed and/or modified under
44
44
  the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
45
- Ruby licence.
45
+ MIT licence.
46
46
 
47
- $Id: ldiff.rb,v 1.1 2004/09/26 01:37:49 austin Exp $
47
+ $Id$
48
48
  COPYRIGHT
49
-
49
+
50
50
  class << self
51
51
  attr_reader :format, :lines #:nodoc:
52
52
  attr_reader :file_old, :file_new #:nodoc:
53
53
  attr_reader :data_old, :data_new #:nodoc:
54
54
 
55
55
  def run(args, input = $stdin, output = $stdout, error = $stderr) #:nodoc:
56
+ @binary = nil
57
+
56
58
  args.options do |o|
57
59
  o.banner = "Usage: #{File.basename($0)} [options] oldfile newfile"
58
60
  o.separator ""
59
- o.on('-c',
60
- 'Displays a context diff with 3 lines of',
61
- 'context.') do |ctx|
61
+ o.on('-c', 'Displays a context diff with 3 lines of', 'context.') do |ctx|
62
62
  @format = :context
63
63
  @lines = 3
64
64
  end
65
- o.on('-C', '--context [LINES]', Numeric,
66
- 'Displays a context diff with LINES lines',
67
- 'of context. Default 3 lines.') do |ctx|
65
+ o.on('-C', '--context [LINES]', Numeric, 'Displays a context diff with LINES lines', 'of context. Default 3 lines.') do |ctx|
68
66
  @format = :context
69
67
  @lines = ctx || 3
70
68
  end
71
- o.on('-u',
72
- 'Displays a unified diff with 3 lines of',
73
- 'context.') do |ctx|
69
+ o.on('-u', 'Displays a unified diff with 3 lines of', 'context.') do |ctx|
74
70
  @format = :unified
75
71
  @lines = 3
76
72
  end
77
- o.on('-U', '--unified [LINES]', Numeric,
78
- 'Displays a unified diff with LINES lines',
79
- 'of context. Default 3 lines.') do |ctx|
73
+ o.on('-U', '--unified [LINES]', Numeric, 'Displays a unified diff with LINES lines', 'of context. Default 3 lines.') do |ctx|
80
74
  @format = :unified
81
75
  @lines = ctx || 3
82
76
  end
83
- o.on('-e',
84
- 'Creates an \'ed\' script to change',
85
- 'oldfile to newfile.') do |ctx|
77
+ o.on('-e', 'Creates an \'ed\' script to change', 'oldfile to newfile.') do |ctx|
86
78
  @format = :ed
87
79
  end
88
- o.on('-f',
89
- 'Creates an \'ed\' script to change',
90
- 'oldfile to newfile in reverse order.') do |ctx|
80
+ o.on('-f', 'Creates an \'ed\' script to change', 'oldfile to newfile in reverse order.') do |ctx|
91
81
  @format = :reverse_ed
92
82
  end
93
- o.on('-a', '--text',
94
- 'Treat the files as text and compare them',
95
- 'line-by-line, even if they do not seem',
96
- 'to be text.') do |txt|
83
+ o.on('-a', '--text', 'Treat the files as text and compare them', 'line-by-line, even if they do not seem', 'to be text.') do |txt|
97
84
  @binary = false
98
85
  end
99
- o.on('--binary',
100
- 'Treats the files as binary.') do |bin|
86
+ o.on('--binary', 'Treats the files as binary.') do |bin|
101
87
  @binary = true
102
88
  end
103
- o.on('-q', '--brief',
104
- 'Report only whether or not the files',
105
- 'differ, not the details.') do |ctx|
89
+ o.on('-q', '--brief', 'Report only whether or not the files', 'differ, not the details.') do |ctx|
106
90
  @format = :report
107
91
  end
108
92
  o.on_tail('--help', 'Shows this text.') do
@@ -123,7 +107,7 @@ $Id: ldiff.rb,v 1.1 2004/09/26 01:37:49 austin Exp $
123
107
  return 127
124
108
  end
125
109
 
126
- # Defaults are for old-style diff
110
+ # Defaults are for old-style diff
127
111
  @format ||= :old
128
112
  @lines ||= 0
129
113
 
@@ -138,15 +122,15 @@ $Id: ldiff.rb,v 1.1 2004/09/26 01:37:49 austin Exp $
138
122
  char_new = '+' * 3
139
123
  end
140
124
 
141
- # After we've read up to a certain point in each file, the number of
142
- # items we've read from each file will differ by FLD (could be 0).
125
+ # After we've read up to a certain point in each file, the number of
126
+ # items we've read from each file will differ by FLD (could be 0).
143
127
  file_length_difference = 0
144
128
 
145
129
  if @binary.nil? or @binary
146
130
  data_old = IO::read(file_old)
147
131
  data_new = IO::read(file_new)
148
132
 
149
- # Test binary status
133
+ # Test binary status
150
134
  if @binary.nil?
151
135
  old_txt = data_old[0...4096].grep(/\0/).empty?
152
136
  new_txt = data_new[0...4096].grep(/\0/).empty?
@@ -163,7 +147,7 @@ $Id: ldiff.rb,v 1.1 2004/09/26 01:37:49 austin Exp $
163
147
  data_new = IO::readlines(file_new).map! { |e| e.chomp }
164
148
  end
165
149
 
166
- # diff yields lots of pieces, each of which is basically a Block object
150
+ # diff yields lots of pieces, each of which is basically a Block object
167
151
  if @binary
168
152
  diffs = (data_old == data_new)
169
153
  else
@@ -185,8 +169,8 @@ $Id: ldiff.rb,v 1.1 2004/09/26 01:37:49 austin Exp $
185
169
  puts "#{char_new} #{file_new}\t#{ft}"
186
170
  end
187
171
 
188
- # Loop over hunks. If a hunk overlaps with the last hunk, join them.
189
- # Otherwise, print out the old one.
172
+ # Loop over hunks. If a hunk overlaps with the last hunk, join them.
173
+ # Otherwise, print out the old one.
190
174
  oldhunk = hunk = nil
191
175
 
192
176
  if @format == :ed
@@ -195,22 +179,22 @@ $Id: ldiff.rb,v 1.1 2004/09/26 01:37:49 austin Exp $
195
179
  end
196
180
 
197
181
  diffs.each do |piece|
198
- begin
199
- hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @lines,
200
- file_length_difference)
201
- file_length_difference = hunk.file_length_difference
202
-
203
- next unless oldhunk
204
-
205
- if (@lines > 0) and hunk.overlaps?(oldhunk)
206
- hunk.unshift(oldhunk)
207
- else
208
- output << oldhunk.diff(@format)
182
+ begin
183
+ hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @lines,
184
+ file_length_difference)
185
+ file_length_difference = hunk.file_length_difference
186
+
187
+ next unless oldhunk
188
+
189
+ if (@lines > 0) and hunk.overlaps?(oldhunk)
190
+ hunk.unshift(oldhunk)
191
+ else
192
+ output << oldhunk.diff(@format)
193
+ end
194
+ ensure
195
+ oldhunk = hunk
196
+ output << "\n"
209
197
  end
210
- ensure
211
- oldhunk = hunk
212
- output << "\n"
213
- end
214
198
  end
215
199
 
216
200
  output << oldhunk.diff(@format)
@@ -10,7 +10,7 @@
10
10
  # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
11
11
  # Ruby licence.
12
12
  #
13
- # $Id: string.rb,v 1.3 2004/08/08 20:33:09 austin Exp $
13
+ # $Id$
14
14
  #++
15
15
  # Includes Diff::LCS into String.
16
16
 
@@ -0,0 +1,35 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe "Diff::LCS.diff" do
6
+ include Diff::LCS::SpecHelper::Matchers
7
+
8
+ it "should correctly diff seq1 to seq2" do
9
+ diff_s1_s2 = Diff::LCS.diff(seq1, seq2)
10
+ change_diff(correct_forward_diff).should == diff_s1_s2
11
+ end
12
+
13
+ it "should correctly diff seq2 to seq1" do
14
+ diff_s2_s1 = Diff::LCS.diff(seq2, seq1)
15
+ change_diff(correct_backward_diff).should == diff_s2_s1
16
+ end
17
+
18
+ it "should correctly diff against an empty sequence" do
19
+ diff = Diff::LCS.diff(word_sequence, [])
20
+ correct_diff = [
21
+ [ [ '-', 0, 'abcd' ],
22
+ [ '-', 1, 'efgh' ],
23
+ [ '-', 2, 'ijkl' ],
24
+ [ '-', 3, 'mnopqrstuvwxyz' ] ]
25
+ ]
26
+
27
+ change_diff(correct_diff).should == diff
28
+
29
+ diff = Diff::LCS.diff([], word_sequence)
30
+ correct_diff.each { |hunk| hunk.each { |change| change[0] = '+' } }
31
+ change_diff(correct_diff).should == diff
32
+ end
33
+ end
34
+
35
+ # vim: ft=ruby
@@ -0,0 +1,36 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe "Diff::LCS.LCS and Diff::LCS.__lcs" do
6
+ include Diff::LCS::SpecHelper::Matchers
7
+
8
+ it "should return the correct raw values from Diff::LCS.__lcs" do
9
+ res = Diff::LCS.__lcs(seq1, seq2)
10
+ # The result of the LCS (less the +nil+ values) must be as long as the
11
+ # correct result.
12
+ res.compact.size.should == correct_lcs.size
13
+ res.should correctly_map_sequence(seq1).to_other_sequence(seq2)
14
+
15
+ # Compact these transformations and they should be the correct LCS.
16
+ x_seq1 = (0...res.size).map { |ix| res[ix] ? seq1[ix] : nil }.compact
17
+ x_seq2 = (0...res.size).map { |ix| res[ix] ? seq2[res[ix]] : nil }.compact
18
+
19
+ x_seq1.should == correct_lcs
20
+ x_seq2.should == correct_lcs
21
+ end
22
+
23
+ it "should return the correct compacted values from Diff::LCS.LCS" do
24
+ res = Diff::LCS.LCS(seq1, seq2)
25
+ res.should == correct_lcs
26
+ res.compact.should == res
27
+ end
28
+
29
+ it "should be transitive" do
30
+ res = Diff::LCS.LCS(seq2, seq1)
31
+ res.should == correct_lcs
32
+ res.compact.should == res
33
+ end
34
+ end
35
+
36
+ # vim: ft=ruby