groonga 0.0.7 → 0.9.0
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.
- data/NEWS.ja.rdoc +56 -0
- data/NEWS.rdoc +58 -0
- data/Rakefile +2 -3
- data/benchmark/read-write-many-small-items.rb +16 -32
- data/benchmark/write-many-small-items.rb +14 -28
- data/example/bookmark.rb +19 -17
- data/example/index-html.rb +11 -1
- data/example/search/config.ru +14 -9
- data/ext/rb-grn-array.c +6 -6
- data/ext/rb-grn-column.c +348 -18
- data/ext/rb-grn-context.c +8 -4
- data/ext/rb-grn-database.c +6 -7
- data/ext/rb-grn-exception.c +101 -5
- data/ext/rb-grn-expression.c +206 -23
- data/ext/rb-grn-fix-size-column.c +6 -39
- data/ext/rb-grn-hash.c +24 -24
- data/ext/rb-grn-index-column.c +74 -19
- data/ext/rb-grn-logger.c +48 -0
- data/ext/rb-grn-object.c +281 -67
- data/ext/rb-grn-operation.c +1 -1
- data/ext/rb-grn-patricia-trie-cursor.c +10 -1
- data/ext/rb-grn-patricia-trie.c +268 -7
- data/ext/rb-grn-query.c +52 -1
- data/ext/rb-grn-record.c +8 -2
- data/ext/rb-grn-snippet.c +63 -1
- data/ext/rb-grn-table-cursor-key-support.c +15 -1
- data/ext/rb-grn-table-cursor.c +57 -0
- data/ext/rb-grn-table-key-support.c +382 -46
- data/ext/rb-grn-table.c +729 -192
- data/ext/rb-grn-type.c +63 -12
- data/ext/rb-grn-utils.c +156 -158
- data/ext/rb-grn-variable.c +18 -0
- data/ext/rb-grn.h +85 -21
- data/ext/rb-groonga.c +13 -3
- data/extconf.rb +19 -4
- data/html/developer.html +1 -1
- data/html/header.html.erb +1 -1
- data/html/index.html +4 -4
- data/lib/groonga.rb +10 -0
- data/lib/groonga/expression-builder.rb +81 -42
- data/lib/groonga/patricia-trie.rb +13 -0
- data/lib/groonga/record.rb +158 -13
- data/lib/groonga/schema.rb +339 -33
- data/pkg-config.rb +6 -1
- data/test-unit/lib/test/unit.rb +23 -42
- data/test-unit/lib/test/unit/assertionfailederror.rb +11 -0
- data/test-unit/lib/test/unit/assertions.rb +87 -9
- data/test-unit/lib/test/unit/autorunner.rb +20 -11
- data/test-unit/lib/test/unit/collector.rb +1 -8
- data/test-unit/lib/test/unit/collector/load.rb +2 -3
- data/test-unit/lib/test/unit/color-scheme.rb +13 -1
- data/test-unit/lib/test/unit/diff.rb +223 -37
- data/test-unit/lib/test/unit/error.rb +4 -0
- data/test-unit/lib/test/unit/failure.rb +31 -5
- data/test-unit/lib/test/unit/notification.rb +8 -4
- data/test-unit/lib/test/unit/omission.rb +51 -3
- data/test-unit/lib/test/unit/pending.rb +4 -0
- data/test-unit/lib/test/unit/testcase.rb +55 -4
- data/test-unit/lib/test/unit/ui/console/testrunner.rb +190 -4
- data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +14 -0
- data/test-unit/lib/test/unit/ui/testrunner.rb +8 -0
- data/test-unit/lib/test/unit/version.rb +1 -1
- data/test-unit/sample/{tc_adder.rb → test_adder.rb} +3 -1
- data/test-unit/sample/{tc_subtracter.rb → test_subtracter.rb} +3 -1
- data/test-unit/sample/test_user.rb +1 -0
- data/test-unit/test/collector/test-descendant.rb +2 -4
- data/test-unit/test/collector/test_objectspace.rb +7 -5
- data/test-unit/test/run-test.rb +2 -0
- data/test-unit/test/test-color-scheme.rb +7 -0
- data/test-unit/test/test-diff.rb +48 -7
- data/test-unit/test/test-omission.rb +1 -1
- data/test-unit/test/test-testcase.rb +47 -0
- data/test-unit/test/test_assertions.rb +79 -10
- data/test/groonga-test-utils.rb +6 -1
- data/test/test-array.rb +29 -14
- data/test/test-column.rb +107 -55
- data/test/test-context.rb +5 -0
- data/test/test-database.rb +2 -37
- data/test/test-exception.rb +9 -1
- data/test/test-expression-builder.rb +23 -5
- data/test/test-expression.rb +44 -8
- data/test/test-fix-size-column.rb +16 -5
- data/test/test-gqtp.rb +70 -0
- data/test/test-hash.rb +142 -43
- data/test/test-index-column.rb +9 -9
- data/test/test-patricia-trie.rb +79 -20
- data/test/test-procedure.rb +4 -2
- data/test/test-record.rb +32 -20
- data/test/test-remote.rb +3 -2
- data/test/test-schema.rb +226 -92
- data/test/test-table-cursor.rb +103 -1
- data/test/test-table-offset-and-limit.rb +102 -0
- data/test/test-table-select-normalize.rb +4 -4
- data/test/test-table-select.rb +52 -8
- data/test/test-table.rb +235 -116
- data/test/test-type.rb +2 -2
- data/test/test-variable-size-column.rb +21 -5
- data/test/test-vector-column.rb +76 -0
- data/{TUTORIAL.ja.rdoc → text/TUTORIAL.ja.rdoc} +52 -52
- data/text/expression.rdoc +284 -0
- metadata +11 -7
- data/test-unit/sample/ts_examples.rb +0 -7
|
@@ -11,16 +11,23 @@ module Test
|
|
|
11
11
|
# when an assertion fails.
|
|
12
12
|
class Failure
|
|
13
13
|
attr_reader :test_name, :location, :message
|
|
14
|
-
|
|
14
|
+
attr_reader :expected, :actual, :user_message
|
|
15
|
+
attr_reader :inspected_expected, :inspected_actual
|
|
16
|
+
|
|
15
17
|
SINGLE_CHARACTER = 'F'
|
|
16
18
|
LABEL = "Failure"
|
|
17
19
|
|
|
18
20
|
# Creates a new Failure with the given location and
|
|
19
21
|
# message.
|
|
20
|
-
def initialize(test_name, location, message)
|
|
22
|
+
def initialize(test_name, location, message, options={})
|
|
21
23
|
@test_name = test_name
|
|
22
24
|
@location = location
|
|
23
25
|
@message = message
|
|
26
|
+
@expected = options[:expected]
|
|
27
|
+
@actual = options[:actual]
|
|
28
|
+
@inspected_expected = options[:inspected_expected]
|
|
29
|
+
@inspected_actual = options[:inspected_actual]
|
|
30
|
+
@user_message = options[:user_message]
|
|
24
31
|
end
|
|
25
32
|
|
|
26
33
|
# Returns a single character representation of a failure.
|
|
@@ -51,6 +58,19 @@ module Test
|
|
|
51
58
|
def to_s
|
|
52
59
|
long_display
|
|
53
60
|
end
|
|
61
|
+
|
|
62
|
+
def critical?
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def diff
|
|
67
|
+
@diff ||= compute_diff
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
def compute_diff
|
|
72
|
+
Assertions::AssertionMessage.delayed_diff(@expected, @actual).inspect
|
|
73
|
+
end
|
|
54
74
|
end
|
|
55
75
|
|
|
56
76
|
module FailureHandler
|
|
@@ -64,12 +84,18 @@ module Test
|
|
|
64
84
|
def handle_assertion_failed_error(exception)
|
|
65
85
|
return false unless exception.is_a?(AssertionFailedError)
|
|
66
86
|
problem_occurred
|
|
67
|
-
add_failure(exception.message, exception.backtrace
|
|
87
|
+
add_failure(exception.message, exception.backtrace,
|
|
88
|
+
:expected => exception.expected,
|
|
89
|
+
:actual => exception.actual,
|
|
90
|
+
:inspected_expected => exception.inspected_expected,
|
|
91
|
+
:inspected_actual => exception.inspected_actual,
|
|
92
|
+
:user_message => exception.user_message)
|
|
68
93
|
true
|
|
69
94
|
end
|
|
70
95
|
|
|
71
|
-
def add_failure(message, backtrace)
|
|
72
|
-
failure = Failure.new(name, filter_backtrace(backtrace), message
|
|
96
|
+
def add_failure(message, backtrace, options={})
|
|
97
|
+
failure = Failure.new(name, filter_backtrace(backtrace), message,
|
|
98
|
+
options)
|
|
73
99
|
current_result.add_failure(failure)
|
|
74
100
|
end
|
|
75
101
|
end
|
|
@@ -41,6 +41,10 @@ module Test
|
|
|
41
41
|
def to_s
|
|
42
42
|
long_display
|
|
43
43
|
end
|
|
44
|
+
|
|
45
|
+
def critical?
|
|
46
|
+
false
|
|
47
|
+
end
|
|
44
48
|
end
|
|
45
49
|
|
|
46
50
|
class NotifiedError < StandardError
|
|
@@ -79,16 +83,16 @@ module Test
|
|
|
79
83
|
module NotificationHandler
|
|
80
84
|
class << self
|
|
81
85
|
def included(base)
|
|
82
|
-
base.exception_handler(:
|
|
86
|
+
base.exception_handler(:handle_notified_error)
|
|
83
87
|
end
|
|
84
88
|
end
|
|
85
89
|
|
|
86
90
|
private
|
|
87
|
-
def
|
|
91
|
+
def handle_notified_error(exception)
|
|
88
92
|
return false unless exception.is_a?(NotifiedError)
|
|
89
93
|
notification = Notification.new(name,
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
filter_backtrace(exception.backtrace),
|
|
95
|
+
exception.message)
|
|
92
96
|
add_notification(notification)
|
|
93
97
|
true
|
|
94
98
|
end
|
|
@@ -41,6 +41,10 @@ module Test
|
|
|
41
41
|
def to_s
|
|
42
42
|
long_display
|
|
43
43
|
end
|
|
44
|
+
|
|
45
|
+
def critical?
|
|
46
|
+
true
|
|
47
|
+
end
|
|
44
48
|
end
|
|
45
49
|
|
|
46
50
|
class OmittedError < StandardError
|
|
@@ -56,7 +60,7 @@ module Test
|
|
|
56
60
|
end
|
|
57
61
|
end
|
|
58
62
|
|
|
59
|
-
# Omit the test
|
|
63
|
+
# Omit the test or part of the test.
|
|
60
64
|
#
|
|
61
65
|
# Example:
|
|
62
66
|
# def test_omission
|
|
@@ -80,12 +84,56 @@ module Test
|
|
|
80
84
|
end
|
|
81
85
|
end
|
|
82
86
|
|
|
87
|
+
# Omit the test or part of the test if _condition_ is
|
|
88
|
+
# true.
|
|
89
|
+
#
|
|
90
|
+
# Example:
|
|
91
|
+
# def test_omission
|
|
92
|
+
# omit_if("".empty?)
|
|
93
|
+
# # Not reached here
|
|
94
|
+
# end
|
|
95
|
+
#
|
|
96
|
+
# def test_omission_with_here
|
|
97
|
+
# omit_if(true) do
|
|
98
|
+
# # Not ran here
|
|
99
|
+
# end
|
|
100
|
+
# omit_if(false) do
|
|
101
|
+
# # Reached here
|
|
102
|
+
# end
|
|
103
|
+
# # Reached here too
|
|
104
|
+
# end
|
|
83
105
|
def omit_if(condition, *args, &block)
|
|
84
|
-
|
|
106
|
+
if condition
|
|
107
|
+
omit(*args, &block)
|
|
108
|
+
else
|
|
109
|
+
block.call if block
|
|
110
|
+
end
|
|
85
111
|
end
|
|
86
112
|
|
|
113
|
+
# Omit the test or part of the test if _condition_ is
|
|
114
|
+
# not true.
|
|
115
|
+
#
|
|
116
|
+
# Example:
|
|
117
|
+
# def test_omission
|
|
118
|
+
# omit_unless("string".empty?)
|
|
119
|
+
# # Not reached here
|
|
120
|
+
# end
|
|
121
|
+
#
|
|
122
|
+
# def test_omission_with_here
|
|
123
|
+
# omit_unless(true) do
|
|
124
|
+
# # Reached here
|
|
125
|
+
# end
|
|
126
|
+
# omit_unless(false) do
|
|
127
|
+
# # Not ran here
|
|
128
|
+
# end
|
|
129
|
+
# # Reached here too
|
|
130
|
+
# end
|
|
87
131
|
def omit_unless(condition, *args, &block)
|
|
88
|
-
|
|
132
|
+
if condition
|
|
133
|
+
block.call if block
|
|
134
|
+
else
|
|
135
|
+
omit(*args, &block)
|
|
136
|
+
end
|
|
89
137
|
end
|
|
90
138
|
|
|
91
139
|
private
|
|
@@ -94,10 +94,15 @@ module Test
|
|
|
94
94
|
DESCENDANTS << sub_class
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
@@added_methods =
|
|
97
|
+
@@added_methods = {}
|
|
98
98
|
def method_added(name) # :nodoc:
|
|
99
99
|
super
|
|
100
|
-
@@added_methods
|
|
100
|
+
added_methods = (@@added_methods[self] ||= [])
|
|
101
|
+
stringified_name = name.to_s
|
|
102
|
+
if added_methods.include?(stringified_name)
|
|
103
|
+
attribute(:redefined, true, {}, stringified_name)
|
|
104
|
+
end
|
|
105
|
+
added_methods << stringified_name
|
|
101
106
|
end
|
|
102
107
|
|
|
103
108
|
# Rolls up all of the test* methods in the fixture into
|
|
@@ -212,6 +217,39 @@ module Test
|
|
|
212
217
|
@@test_order = order
|
|
213
218
|
end
|
|
214
219
|
|
|
220
|
+
# Defines a test in declarative syntax.
|
|
221
|
+
#
|
|
222
|
+
# The following two test definitions are the same:
|
|
223
|
+
#
|
|
224
|
+
# description "register user"
|
|
225
|
+
# def test_register_user
|
|
226
|
+
# ...
|
|
227
|
+
# end
|
|
228
|
+
#
|
|
229
|
+
# test "register user" do
|
|
230
|
+
# ...
|
|
231
|
+
# end
|
|
232
|
+
def test(test_description, &block)
|
|
233
|
+
normalized_description = test_description.gsub(/[^a-zA-Z\d_]+/, '_')
|
|
234
|
+
method_name = "test_#{normalized_description}".to_sym
|
|
235
|
+
define_method(method_name, &block)
|
|
236
|
+
description(test_description, method_name)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Describes a test.
|
|
240
|
+
#
|
|
241
|
+
# The following example associates "register a
|
|
242
|
+
# normal user" description with "test_register"
|
|
243
|
+
# test.
|
|
244
|
+
#
|
|
245
|
+
# description "register a normal user"
|
|
246
|
+
# def test_register
|
|
247
|
+
# ...
|
|
248
|
+
# end
|
|
249
|
+
def description(value, target=nil)
|
|
250
|
+
attribute(:description, value, {}, target || [])
|
|
251
|
+
end
|
|
252
|
+
|
|
215
253
|
# :stopdoc:
|
|
216
254
|
private
|
|
217
255
|
def collect_test_names
|
|
@@ -233,9 +271,10 @@ module Test
|
|
|
233
271
|
end
|
|
234
272
|
|
|
235
273
|
def sort_test_names_in_defined_order(test_names)
|
|
274
|
+
added_methods = @@added_methods[self]
|
|
236
275
|
test_names.sort do |test1, test2|
|
|
237
|
-
test1_defined_order =
|
|
238
|
-
test2_defined_order =
|
|
276
|
+
test1_defined_order = added_methods.index(test1)
|
|
277
|
+
test2_defined_order = added_methods.index(test2)
|
|
239
278
|
if test1_defined_order and test2_defined_order
|
|
240
279
|
test1_defined_order <=> test2_defined_order
|
|
241
280
|
elsif test1_defined_order
|
|
@@ -374,6 +413,15 @@ module Test
|
|
|
374
413
|
"#{@method_name}(#{self.class.name})"
|
|
375
414
|
end
|
|
376
415
|
|
|
416
|
+
# Returns a description for the test. A description
|
|
417
|
+
# will be associated by Test::Unit::TestCase.test or
|
|
418
|
+
# Test::Unit::TestCase.description.
|
|
419
|
+
#
|
|
420
|
+
# Returns a name for the test for no description test.
|
|
421
|
+
def description
|
|
422
|
+
self[:description] || name
|
|
423
|
+
end
|
|
424
|
+
|
|
377
425
|
# Overridden to return #name.
|
|
378
426
|
def to_s
|
|
379
427
|
name
|
|
@@ -396,6 +444,9 @@ module Test
|
|
|
396
444
|
end
|
|
397
445
|
|
|
398
446
|
def run_test
|
|
447
|
+
if self.class.get_attribute(@method_name, :redefined)
|
|
448
|
+
notify("#{self.class}\##{@method_name} was redefined")
|
|
449
|
+
end
|
|
399
450
|
__send__(@method_name)
|
|
400
451
|
end
|
|
401
452
|
|
|
@@ -84,7 +84,7 @@ module Test
|
|
|
84
84
|
def add_fault(fault)
|
|
85
85
|
@faults << fault
|
|
86
86
|
output_progress(fault.single_character_display, fault_color(fault))
|
|
87
|
-
@already_outputted = true
|
|
87
|
+
@already_outputted = true if fault.critical?
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
def started(result)
|
|
@@ -101,9 +101,7 @@ module Test
|
|
|
101
101
|
@faults.each_with_index do |fault, index|
|
|
102
102
|
nl
|
|
103
103
|
output_single("%3d) " % (index + 1))
|
|
104
|
-
|
|
105
|
-
output(label, fault_color(fault))
|
|
106
|
-
output(detail)
|
|
104
|
+
output_fault(fault)
|
|
107
105
|
end
|
|
108
106
|
nl
|
|
109
107
|
output("Finished in #{elapsed_time} seconds.")
|
|
@@ -118,6 +116,65 @@ module Test
|
|
|
118
116
|
output("%g%% passed" % pass_percentage, result_color)
|
|
119
117
|
end
|
|
120
118
|
|
|
119
|
+
def output_fault(fault)
|
|
120
|
+
if @use_color and fault.is_a?(Failure) and
|
|
121
|
+
fault.inspected_expected and fault.inspected_actual
|
|
122
|
+
output_single(fault.label, fault_color(fault))
|
|
123
|
+
output(":")
|
|
124
|
+
output_fault_backtrace(fault)
|
|
125
|
+
output_fault_message(fault)
|
|
126
|
+
else
|
|
127
|
+
label, detail = format_fault(fault).split(/\r?\n/, 2)
|
|
128
|
+
output(label, fault_color(fault))
|
|
129
|
+
output(detail)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def output_fault_backtrace(fault)
|
|
134
|
+
backtrace = fault.location
|
|
135
|
+
if backtrace.size == 1
|
|
136
|
+
output(fault.test_name +
|
|
137
|
+
backtrace[0].sub(/\A(.+:\d+).*/, ' [\\1]') +
|
|
138
|
+
":")
|
|
139
|
+
else
|
|
140
|
+
output(fault.test_name)
|
|
141
|
+
backtrace.each_with_index do |entry, i|
|
|
142
|
+
if i.zero?
|
|
143
|
+
prefix = "["
|
|
144
|
+
postfix = ""
|
|
145
|
+
elsif i == backtrace.size - 1
|
|
146
|
+
prefix = " "
|
|
147
|
+
postfix = "]:"
|
|
148
|
+
else
|
|
149
|
+
prefix = " "
|
|
150
|
+
postfix = ""
|
|
151
|
+
end
|
|
152
|
+
output(" #{prefix}#{entry}#{postfix}")
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def output_fault_message(fault)
|
|
158
|
+
output(fault.user_message) if fault.user_message
|
|
159
|
+
output_single("<")
|
|
160
|
+
output_single(fault.inspected_expected, color("success"))
|
|
161
|
+
output("> expected but was")
|
|
162
|
+
output_single("<")
|
|
163
|
+
output_single(fault.inspected_actual, color("failure"))
|
|
164
|
+
output(">")
|
|
165
|
+
from, to = prepare_for_diff(fault.expected, fault.actual)
|
|
166
|
+
if from and to
|
|
167
|
+
differ = ColorizedReadableDiffer.new(from.split(/\r?\n/),
|
|
168
|
+
to.split(/\r?\n/),
|
|
169
|
+
self)
|
|
170
|
+
if differ.need_diff?
|
|
171
|
+
output("")
|
|
172
|
+
output("diff:")
|
|
173
|
+
differ.diff
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
121
178
|
def format_fault(fault)
|
|
122
179
|
fault.long_display
|
|
123
180
|
end
|
|
@@ -268,6 +325,135 @@ module Test
|
|
|
268
325
|
0
|
|
269
326
|
end
|
|
270
327
|
end
|
|
328
|
+
|
|
329
|
+
class ColorizedReadableDiffer < Diff::ReadableDiffer
|
|
330
|
+
def initialize(from, to, runner)
|
|
331
|
+
@runner = runner
|
|
332
|
+
super(from, to)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def need_diff?(options={})
|
|
336
|
+
operations.each do |tag,|
|
|
337
|
+
return true if [:replace, :equal].include?(tag)
|
|
338
|
+
end
|
|
339
|
+
false
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
private
|
|
343
|
+
def output_single(something, color=nil)
|
|
344
|
+
@runner.send(:output_single, something, color)
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def output(something, color=nil)
|
|
348
|
+
@runner.send(:output, something, color)
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def color(name)
|
|
352
|
+
@runner.send(:color, name)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def cut_off_ratio
|
|
356
|
+
0
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def default_ratio
|
|
360
|
+
0
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def tag(mark, color_name, contents)
|
|
364
|
+
_color = color(color_name)
|
|
365
|
+
contents.each do |content|
|
|
366
|
+
output_single(mark, _color)
|
|
367
|
+
output_single(" ")
|
|
368
|
+
output(content)
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def tag_deleted(contents)
|
|
373
|
+
tag("-", "diff-deleted-tag", contents)
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def tag_inserted(contents)
|
|
377
|
+
tag("+", "diff-inserted-tag", contents)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def tag_equal(contents)
|
|
381
|
+
tag(" ", "normal", contents)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def tag_difference(contents)
|
|
385
|
+
tag("?", "diff-difference-tag", contents)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def diff_line(from_line, to_line)
|
|
389
|
+
to_operations = []
|
|
390
|
+
from_line, to_line, _operations = line_operations(from_line, to_line)
|
|
391
|
+
|
|
392
|
+
no_replace = true
|
|
393
|
+
_operations.each do |tag,|
|
|
394
|
+
if tag == :replace
|
|
395
|
+
no_replace = false
|
|
396
|
+
break
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
output_single("?", color("diff-difference-tag"))
|
|
401
|
+
output_single(" ")
|
|
402
|
+
_operations.each do |tag, from_start, from_end, to_start, to_end|
|
|
403
|
+
from_width = compute_width(from_line, from_start, from_end)
|
|
404
|
+
to_width = compute_width(to_line, to_start, to_end)
|
|
405
|
+
case tag
|
|
406
|
+
when :replace
|
|
407
|
+
output_single(from_line[from_start...from_end],
|
|
408
|
+
color("diff-deleted"))
|
|
409
|
+
if (from_width < to_width)
|
|
410
|
+
output_single(" " * (to_width - from_width))
|
|
411
|
+
end
|
|
412
|
+
to_operations << Proc.new do
|
|
413
|
+
output_single(to_line[to_start...to_end],
|
|
414
|
+
color("diff-inserted"))
|
|
415
|
+
if (to_width < from_width)
|
|
416
|
+
output_single(" " * (from_width - to_width))
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
when :delete
|
|
420
|
+
output_single(from_line[from_start...from_end],
|
|
421
|
+
color("diff-deleted"))
|
|
422
|
+
unless no_replace
|
|
423
|
+
to_operations << Proc.new {output_single(" " * from_width)}
|
|
424
|
+
end
|
|
425
|
+
when :insert
|
|
426
|
+
if no_replace
|
|
427
|
+
output_single(to_line[to_start...to_end],
|
|
428
|
+
color("diff-inserted"))
|
|
429
|
+
else
|
|
430
|
+
output_single(" " * to_width)
|
|
431
|
+
to_operations << Proc.new do
|
|
432
|
+
output_single(to_line[to_start...to_end],
|
|
433
|
+
color("diff-inserted"))
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
when :equal
|
|
437
|
+
output_single(from_line[from_start...from_end])
|
|
438
|
+
unless no_replace
|
|
439
|
+
to_operations << Proc.new {output_single(" " * to_width)}
|
|
440
|
+
end
|
|
441
|
+
else
|
|
442
|
+
raise "unknown tag: #{tag}"
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
output("")
|
|
446
|
+
|
|
447
|
+
unless to_operations.empty?
|
|
448
|
+
output_single("?", color("diff-difference-tag"))
|
|
449
|
+
output_single(" ")
|
|
450
|
+
to_operations.each do |operation|
|
|
451
|
+
operation.call
|
|
452
|
+
end
|
|
453
|
+
output("")
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
271
457
|
end
|
|
272
458
|
end
|
|
273
459
|
end
|