diff-lcs 1.1.2 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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