canon 0.1.10 → 0.1.12
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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +19 -77
- data/README.adoc +220 -26
- data/docs/features/diff-formatting/colors-and-symbols.adoc +73 -22
- data/lib/canon/cli.rb +31 -2
- data/lib/canon/color_detector.rb +141 -0
- data/lib/canon/commands/diff_command.rb +19 -2
- data/lib/canon/config/env_schema.rb +5 -1
- data/lib/canon/config.rb +32 -1
- data/lib/canon/diff_formatter.rb +102 -12
- data/lib/canon/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0c7f014834dac890a353a1e85abe80dc834e81f20b853cfa00f51a06c423a699
|
|
4
|
+
data.tar.gz: 3b849925479fcec2777b22619bee9ab3d710fd33ce29b10bf2873c90d3095192
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7def7dca16c59b0e3f3952b12f814ad93b38cb108654903471320e0e3c7d55418af60068a114eb9d3fcd4e260bdc806c5cd65b9471b06a85b5c5a223f6373395
|
|
7
|
+
data.tar.gz: b36133cf1c3c0597e12b880057ebdc5af80689ab59bb8983ff631208d31db994151858521fb8897c88c00d1651e0ac25ad376584558a3b5b514cfd409c2f20be
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-01-21
|
|
3
|
+
# on 2026-01-21 09:17:44 UTC using RuboCop version 1.81.7.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -12,52 +12,13 @@ Gemspec/RequiredRubyVersion:
|
|
|
12
12
|
Exclude:
|
|
13
13
|
- 'canon.gemspec'
|
|
14
14
|
|
|
15
|
-
# Offense count:
|
|
16
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
17
|
-
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
18
|
-
# SupportedStyles: with_first_argument, with_fixed_indentation
|
|
19
|
-
Layout/ArgumentAlignment:
|
|
20
|
-
Exclude:
|
|
21
|
-
- 'lib/canon/comparison/xml_comparator.rb'
|
|
22
|
-
- 'lib/canon/diff/xml_serialization_formatter.rb'
|
|
23
|
-
- 'spec/canon/diff/xml_serialization_formatter_spec.rb'
|
|
24
|
-
|
|
25
|
-
# Offense count: 1
|
|
26
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
27
|
-
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
|
28
|
-
# SupportedHashRocketStyles: key, separator, table
|
|
29
|
-
# SupportedColonStyles: key, separator, table
|
|
30
|
-
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
|
31
|
-
Layout/HashAlignment:
|
|
32
|
-
Exclude:
|
|
33
|
-
- 'test_verify_equivalent.rb'
|
|
34
|
-
|
|
35
|
-
# Offense count: 709
|
|
15
|
+
# Offense count: 700
|
|
36
16
|
# This cop supports safe autocorrection (--autocorrect).
|
|
37
17
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
|
38
18
|
# URISchemes: http, https
|
|
39
19
|
Layout/LineLength:
|
|
40
20
|
Enabled: false
|
|
41
21
|
|
|
42
|
-
# Offense count: 4
|
|
43
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
44
|
-
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
45
|
-
# SupportedStyles: aligned, indented
|
|
46
|
-
Layout/MultilineOperationIndentation:
|
|
47
|
-
Exclude:
|
|
48
|
-
- 'lib/canon/diff/diff_classifier.rb'
|
|
49
|
-
- 'lib/canon/diff/xml_serialization_formatter.rb'
|
|
50
|
-
|
|
51
|
-
# Offense count: 17
|
|
52
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
53
|
-
# Configuration parameters: AllowInHeredoc.
|
|
54
|
-
Layout/TrailingWhitespace:
|
|
55
|
-
Exclude:
|
|
56
|
-
- 'lib/canon/comparison/xml_comparator.rb'
|
|
57
|
-
- 'lib/canon/diff/xml_serialization_formatter.rb'
|
|
58
|
-
- 'spec/canon/diff/xml_serialization_formatter_spec.rb'
|
|
59
|
-
- 'test_verify_equivalent.rb'
|
|
60
|
-
|
|
61
22
|
# Offense count: 48
|
|
62
23
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
63
24
|
Lint/DuplicateBranch:
|
|
@@ -98,7 +59,7 @@ Lint/UnusedMethodArgument:
|
|
|
98
59
|
- 'lib/canon/diff_formatter/by_line/xml_formatter.rb'
|
|
99
60
|
- 'lib/canon/diff_formatter/by_object/base_formatter.rb'
|
|
100
61
|
|
|
101
|
-
# Offense count:
|
|
62
|
+
# Offense count: 209
|
|
102
63
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
103
64
|
Metrics/AbcSize:
|
|
104
65
|
Enabled: false
|
|
@@ -109,22 +70,22 @@ Metrics/AbcSize:
|
|
|
109
70
|
Metrics/BlockLength:
|
|
110
71
|
Max: 84
|
|
111
72
|
|
|
112
|
-
# Offense count:
|
|
73
|
+
# Offense count: 177
|
|
113
74
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
114
75
|
Metrics/CyclomaticComplexity:
|
|
115
76
|
Enabled: false
|
|
116
77
|
|
|
117
|
-
# Offense count:
|
|
78
|
+
# Offense count: 363
|
|
118
79
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
119
80
|
Metrics/MethodLength:
|
|
120
81
|
Max: 110
|
|
121
82
|
|
|
122
|
-
# Offense count:
|
|
83
|
+
# Offense count: 44
|
|
123
84
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
|
124
85
|
Metrics/ParameterLists:
|
|
125
86
|
Max: 9
|
|
126
87
|
|
|
127
|
-
# Offense count:
|
|
88
|
+
# Offense count: 143
|
|
128
89
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
129
90
|
Metrics/PerceivedComplexity:
|
|
130
91
|
Enabled: false
|
|
@@ -165,7 +126,7 @@ Performance/CollectionLiteralInLoop:
|
|
|
165
126
|
- 'lib/canon/comparison/html_comparator.rb'
|
|
166
127
|
- 'lib/canon/xml/xml_base_handler.rb'
|
|
167
128
|
|
|
168
|
-
# Offense count:
|
|
129
|
+
# Offense count: 68
|
|
169
130
|
# Configuration parameters: Prefixes, AllowedPatterns.
|
|
170
131
|
# Prefixes: when, with, without
|
|
171
132
|
RSpec/ContextWording:
|
|
@@ -182,7 +143,13 @@ RSpec/DescribeMethod:
|
|
|
182
143
|
- 'spec/canon/comparison/multiple_differences_spec.rb'
|
|
183
144
|
- 'spec/canon/diff_formatter/character_map_customization_spec.rb'
|
|
184
145
|
|
|
185
|
-
# Offense count:
|
|
146
|
+
# Offense count: 1
|
|
147
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
148
|
+
RSpec/EmptyHook:
|
|
149
|
+
Exclude:
|
|
150
|
+
- 'spec/canon/color_detector_spec.rb'
|
|
151
|
+
|
|
152
|
+
# Offense count: 679
|
|
186
153
|
# Configuration parameters: CountAsOne.
|
|
187
154
|
RSpec/ExampleLength:
|
|
188
155
|
Max: 67
|
|
@@ -213,10 +180,11 @@ RSpec/IndexedLet:
|
|
|
213
180
|
- 'spec/canon/tree_diff/matchers/universal_matcher_spec.rb'
|
|
214
181
|
- 'spec/canon/tree_diff/operations/operation_detector_spec.rb'
|
|
215
182
|
|
|
216
|
-
# Offense count:
|
|
183
|
+
# Offense count: 5
|
|
217
184
|
# Configuration parameters: AssignmentOnly.
|
|
218
185
|
RSpec/InstanceVariable:
|
|
219
186
|
Exclude:
|
|
187
|
+
- 'spec/canon/color_detector_spec.rb'
|
|
220
188
|
- 'spec/canon/rspec_matchers_spec.rb'
|
|
221
189
|
|
|
222
190
|
# Offense count: 15
|
|
@@ -233,7 +201,7 @@ RSpec/MultipleDescribes:
|
|
|
233
201
|
Exclude:
|
|
234
202
|
- 'spec/canon/comparison/match_options_spec.rb'
|
|
235
203
|
|
|
236
|
-
# Offense count:
|
|
204
|
+
# Offense count: 522
|
|
237
205
|
RSpec/MultipleExpectations:
|
|
238
206
|
Max: 15
|
|
239
207
|
|
|
@@ -251,7 +219,7 @@ RSpec/NamedSubject:
|
|
|
251
219
|
- 'spec/canon/pretty_printer/json_spec.rb'
|
|
252
220
|
- 'spec/canon/pretty_printer/xml_spec.rb'
|
|
253
221
|
|
|
254
|
-
# Offense count:
|
|
222
|
+
# Offense count: 40
|
|
255
223
|
# Configuration parameters: AllowedGroups.
|
|
256
224
|
RSpec/NestedGroups:
|
|
257
225
|
Max: 4
|
|
@@ -311,35 +279,9 @@ Style/IdenticalConditionalBranches:
|
|
|
311
279
|
- 'lib/canon/diff_formatter/by_object/base_formatter.rb'
|
|
312
280
|
- 'lib/canon/diff_formatter/legend.rb'
|
|
313
281
|
|
|
314
|
-
# Offense count: 2
|
|
315
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
316
|
-
# Configuration parameters: InverseMethods, InverseBlocks.
|
|
317
|
-
Style/InverseMethods:
|
|
318
|
-
Exclude:
|
|
319
|
-
- 'lib/canon/comparison/markup_comparator.rb'
|
|
320
|
-
- 'lib/canon/comparison/xml_comparator/diff_node_builder.rb'
|
|
321
|
-
|
|
322
282
|
# Offense count: 1
|
|
323
283
|
# Configuration parameters: AllowedMethods.
|
|
324
284
|
# AllowedMethods: respond_to_missing?
|
|
325
285
|
Style/OptionalBooleanParameter:
|
|
326
286
|
Exclude:
|
|
327
287
|
- 'lib/canon/diff_formatter/debug_output.rb'
|
|
328
|
-
|
|
329
|
-
# Offense count: 3
|
|
330
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
331
|
-
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
|
|
332
|
-
# SupportedStyles: single_quotes, double_quotes
|
|
333
|
-
Style/StringLiterals:
|
|
334
|
-
Exclude:
|
|
335
|
-
- 'lib/canon/comparison/markup_comparator.rb'
|
|
336
|
-
- 'lib/canon/comparison/xml_comparator/diff_node_builder.rb'
|
|
337
|
-
- 'test_verify_equivalent.rb'
|
|
338
|
-
|
|
339
|
-
# Offense count: 12
|
|
340
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
341
|
-
# Configuration parameters: EnforcedStyleForMultiline.
|
|
342
|
-
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
|
343
|
-
Style/TrailingCommaInArguments:
|
|
344
|
-
Exclude:
|
|
345
|
-
- 'spec/canon/diff/xml_serialization_formatter_spec.rb'
|
data/README.adoc
CHANGED
|
@@ -224,68 +224,262 @@ expect(actual).to be_xml_equivalent_to(expected)
|
|
|
224
224
|
.show_diffs(:normative)
|
|
225
225
|
----
|
|
226
226
|
|
|
227
|
-
===
|
|
227
|
+
=== Input display options
|
|
228
228
|
|
|
229
|
-
When debugging test failures, it's often helpful to see the exact
|
|
230
|
-
|
|
231
|
-
`verbose_diff` option displays the original input strings in an RSpec-style
|
|
232
|
-
format with line numbers.
|
|
229
|
+
When debugging test failures, it's often helpful to see the exact inputs that were
|
|
230
|
+
passed to the comparison. Canon provides four input display options:
|
|
233
231
|
|
|
232
|
+
`show_raw_inputs`:: Show raw/original file contents (before preprocessing)
|
|
233
|
+
|
|
234
|
+
`show_preprocessed_inputs`:: Show what was actually compared (after preprocessing)
|
|
235
|
+
|
|
236
|
+
`show_line_numbered_inputs`:: Show raw inputs with line numbers (for reference)
|
|
237
|
+
|
|
238
|
+
`verbose_diff`:: Convenience flag that enables all three options above
|
|
239
|
+
|
|
240
|
+
You can enable any combination of them independently.
|
|
241
|
+
|
|
242
|
+
==== Show raw inputs
|
|
243
|
+
|
|
244
|
+
Display the raw file contents before any preprocessing. This shows exactly what's
|
|
245
|
+
in your files, useful for copying to specs.
|
|
246
|
+
|
|
247
|
+
**Ruby API:**
|
|
234
248
|
[source,ruby]
|
|
235
249
|
----
|
|
236
|
-
# Enable
|
|
250
|
+
# Enable raw input display in configuration
|
|
237
251
|
Canon::Config.configure do |config|
|
|
238
|
-
config.xml.diff.
|
|
252
|
+
config.xml.diff.show_raw_inputs = true
|
|
239
253
|
end
|
|
240
254
|
|
|
241
255
|
# Or programmatically for a specific comparison
|
|
242
256
|
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
243
257
|
verbose: true,
|
|
244
|
-
|
|
258
|
+
show_raw_inputs: true
|
|
245
259
|
)
|
|
246
260
|
----
|
|
247
261
|
|
|
262
|
+
**CLI usage:**
|
|
263
|
+
[source,bash]
|
|
264
|
+
----
|
|
265
|
+
# Show raw file contents (for copying to specs)
|
|
266
|
+
$ canon diff file1.xml file2.xml --show-raw-inputs
|
|
267
|
+
|
|
268
|
+
# Show both raw and preprocessed (full trace)
|
|
269
|
+
$ canon diff file1.xml file2.xml --show-raw-inputs --show-preprocessed-inputs
|
|
270
|
+
----
|
|
271
|
+
|
|
272
|
+
**Environment variables:**
|
|
273
|
+
[source,bash]
|
|
274
|
+
----
|
|
275
|
+
# Global (all formats)
|
|
276
|
+
export CANON_SHOW_RAW_INPUTS=true
|
|
277
|
+
|
|
278
|
+
# Format-specific
|
|
279
|
+
export CANON_XML_SHOW_RAW_INPUTS=true
|
|
280
|
+
export CANON_HTML_SHOW_RAW_INPUTS=true
|
|
281
|
+
export CANON_JSON_SHOW_RAW_INPUTS=true
|
|
282
|
+
export CANON_YAML_SHOW_RAW_INPUTS=true
|
|
283
|
+
----
|
|
284
|
+
|
|
248
285
|
**Output format:**
|
|
249
286
|
----
|
|
250
|
-
|
|
251
|
-
ORIGINAL INPUT STRINGS
|
|
252
|
-
==================================================================
|
|
287
|
+
=== ORIGINAL INPUTS (Raw) ===
|
|
253
288
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
289
|
+
EXPECTED:
|
|
290
|
+
----------------------------------------------------------------------
|
|
291
|
+
<root> hello
|
|
292
|
+
world</root>
|
|
293
|
+
|
|
294
|
+
RECEIVED:
|
|
295
|
+
----------------------------------------------------------------------
|
|
296
|
+
<root>hello world</root>
|
|
297
|
+
|
|
298
|
+
----
|
|
299
|
+
|
|
300
|
+
==== Show preprocessed inputs
|
|
301
|
+
|
|
302
|
+
Display the content after preprocessing (c14n, normalize, format, etc.).
|
|
303
|
+
This shows what the comparison actually compared, useful for understanding
|
|
304
|
+
how preprocessing affects your content.
|
|
305
|
+
|
|
306
|
+
**Ruby API:**
|
|
307
|
+
[source,ruby]
|
|
308
|
+
----
|
|
309
|
+
# Enable preprocessed input display in configuration
|
|
310
|
+
Canon::Config.configure do |config|
|
|
311
|
+
config.xml.diff.show_preprocessed_inputs = true
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# Or programmatically for a specific comparison
|
|
315
|
+
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
316
|
+
verbose: true,
|
|
317
|
+
show_preprocessed_inputs: true
|
|
318
|
+
)
|
|
319
|
+
----
|
|
320
|
+
|
|
321
|
+
**CLI usage:**
|
|
322
|
+
[source,bash]
|
|
323
|
+
----
|
|
324
|
+
# Show what was actually compared
|
|
325
|
+
$ canon diff file1.xml file2.xml --show-preprocessed-inputs
|
|
326
|
+
|
|
327
|
+
# Preprocess with normalization and show what was compared
|
|
328
|
+
$ canon diff file1.xml file2.xml --preprocessing normalize --show-preprocessed-inputs
|
|
329
|
+
----
|
|
330
|
+
|
|
331
|
+
**Environment variables:**
|
|
332
|
+
[source,bash]
|
|
333
|
+
----
|
|
334
|
+
# Global (all formats)
|
|
335
|
+
export CANON_SHOW_PROCESSED_INPUTS=true
|
|
336
|
+
|
|
337
|
+
# Format-specific
|
|
338
|
+
export CANON_XML_SHOW_PROCESSED_INPUTS=true
|
|
339
|
+
export CANON_HTML_SHOW_PROCESSED_INPUTS=true
|
|
340
|
+
export CANON_JSON_SHOW_PROCESSED_INPUTS=true
|
|
341
|
+
export CANON_YAML_SHOW_PROCESSED_INPUTS=true
|
|
342
|
+
----
|
|
343
|
+
|
|
344
|
+
**Output format:**
|
|
345
|
+
----
|
|
346
|
+
=== PREPROCESSED INPUTS (Compared) ===
|
|
347
|
+
Preprocessing: normalize
|
|
348
|
+
|
|
349
|
+
EXPECTED:
|
|
350
|
+
----------------------------------------------------------------------
|
|
351
|
+
<root> hello world </root>
|
|
352
|
+
|
|
353
|
+
RECEIVED:
|
|
354
|
+
----------------------------------------------------------------------
|
|
355
|
+
<root>hello world</root>
|
|
258
356
|
|
|
259
|
-
|
|
357
|
+
----
|
|
358
|
+
|
|
359
|
+
==== Show line-numbered inputs
|
|
360
|
+
|
|
361
|
+
Display raw inputs with line numbers (RSpec-style format). Useful for
|
|
362
|
+
pinpointing specific lines when debugging.
|
|
363
|
+
|
|
364
|
+
**Ruby API:**
|
|
365
|
+
[source,ruby]
|
|
366
|
+
----
|
|
367
|
+
# Enable line-numbered input display in configuration
|
|
368
|
+
Canon::Config.configure do |config|
|
|
369
|
+
config.xml.diff.show_line_numbered_inputs = true
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# Or programmatically for a specific comparison
|
|
373
|
+
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
374
|
+
verbose: true,
|
|
375
|
+
show_line_numbered_inputs: true
|
|
376
|
+
)
|
|
377
|
+
----
|
|
378
|
+
|
|
379
|
+
**CLI usage:**
|
|
380
|
+
[source,bash]
|
|
381
|
+
----
|
|
382
|
+
# Show raw inputs with line numbers (RSpec-style)
|
|
383
|
+
$ canon diff file1.xml file2.xml --show-line-numbered-inputs
|
|
384
|
+
----
|
|
385
|
+
|
|
386
|
+
**Environment variables:**
|
|
387
|
+
[source,bash]
|
|
388
|
+
----
|
|
389
|
+
# Global (all formats)
|
|
390
|
+
export CANON_SHOW_LINE_NUMBERED_INPUTS=true
|
|
391
|
+
|
|
392
|
+
# Format-specific
|
|
393
|
+
export CANON_XML_SHOW_LINE_NUMBERED_INPUTS=true
|
|
394
|
+
export CANON_HTML_SHOW_LINE_NUMBERED_INPUTS=true
|
|
395
|
+
export CANON_JSON_SHOW_LINE_NUMBERED_INPUTS=true
|
|
396
|
+
export CANON_YAML_SHOW_LINE_NUMBERED_INPUTS=true
|
|
397
|
+
----
|
|
398
|
+
|
|
399
|
+
**Output format:**
|
|
400
|
+
----
|
|
401
|
+
======================================================================
|
|
402
|
+
ORIGINAL INPUTS (with line numbers)
|
|
403
|
+
======================================================================
|
|
404
|
+
|
|
405
|
+
Expected:
|
|
260
406
|
1 | <root>
|
|
261
|
-
2 |
|
|
407
|
+
2 | hello
|
|
262
408
|
3 | </root>
|
|
263
409
|
|
|
264
|
-
|
|
410
|
+
Received:
|
|
411
|
+
1 | <root>hello world</root>
|
|
412
|
+
|
|
413
|
+
======================================================================
|
|
265
414
|
----
|
|
266
415
|
|
|
267
|
-
|
|
416
|
+
==== Verbose diff (all input displays)
|
|
268
417
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
418
|
+
The `verbose_diff` option is a convenience flag that enables all three input
|
|
419
|
+
display options at once. This is useful for maximum debugging output.
|
|
420
|
+
|
|
421
|
+
**Ruby API:**
|
|
422
|
+
[source,ruby]
|
|
423
|
+
----
|
|
424
|
+
# Enable all input displays in configuration
|
|
425
|
+
Canon::Config.configure do |config|
|
|
426
|
+
config.xml.diff.verbose_diff = true
|
|
427
|
+
end
|
|
273
428
|
|
|
274
|
-
|
|
429
|
+
# Or programmatically for a specific comparison
|
|
430
|
+
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
431
|
+
verbose: true,
|
|
432
|
+
verbose_diff: true
|
|
433
|
+
)
|
|
434
|
+
----
|
|
435
|
+
|
|
436
|
+
**CLI usage:**
|
|
437
|
+
[source,bash]
|
|
438
|
+
----
|
|
439
|
+
# Show all three input displays
|
|
440
|
+
$ canon diff file1.xml file2.xml --verbose
|
|
441
|
+
----
|
|
442
|
+
|
|
443
|
+
**Environment variables:**
|
|
275
444
|
[source,bash]
|
|
276
445
|
----
|
|
446
|
+
# Format-specific
|
|
277
447
|
export CANON_XML_DIFF_VERBOSE_DIFF=true
|
|
278
448
|
export CANON_HTML_DIFF_VERBOSE_DIFF=true
|
|
279
449
|
export CANON_JSON_DIFF_VERBOSE_DIFF=true
|
|
280
450
|
export CANON_YAML_DIFF_VERBOSE_DIFF=true
|
|
281
451
|
----
|
|
282
452
|
|
|
453
|
+
==== When to use each option
|
|
454
|
+
|
|
455
|
+
`show_raw_inputs`::
|
|
456
|
+
** You want to copy the expected output to paste into your test specs
|
|
457
|
+
** You need to see the exact formatting/structure of your input files
|
|
458
|
+
** You're debugging file reading/parsing issues
|
|
459
|
+
|
|
460
|
+
`show_preprocessed_inputs`::
|
|
461
|
+
** You want to understand what the comparison actually compared
|
|
462
|
+
** You're debugging why two documents are considered equivalent (or not)
|
|
463
|
+
** You need to trace the effect of preprocessing (c14n, normalize, format)
|
|
464
|
+
|
|
465
|
+
`show_line_numbered_inputs`::
|
|
466
|
+
** You need line numbers for pinpointing specific lines
|
|
467
|
+
** You prefer the RSpec-style format
|
|
468
|
+
** You're collaborating on debugging with others
|
|
469
|
+
|
|
470
|
+
`verbose_diff`::
|
|
471
|
+
** You want maximum debugging output (all three displays at once)
|
|
472
|
+
** You're doing initial investigation of a complex comparison issue
|
|
473
|
+
|
|
283
474
|
=== Algorithm choice
|
|
284
475
|
|
|
285
476
|
Canon provides two diff algorithms:
|
|
286
477
|
|
|
287
|
-
|
|
288
|
-
|
|
478
|
+
DOM diff (default):: Stable, position-based comparison for traditional
|
|
479
|
+
line-by-line output
|
|
480
|
+
|
|
481
|
+
Semantic tree diff (experimental):: Advanced operation detection (INSERT,
|
|
482
|
+
DELETE, UPDATE, MOVE, MERGE, SPLIT, UPGRADE, DOWNGRADE)
|
|
289
483
|
|
|
290
484
|
[source,ruby]
|
|
291
485
|
----
|
|
@@ -457,59 +457,110 @@ The whitespace difference is informative because `structural_whitespace: :ignore
|
|
|
457
457
|
|
|
458
458
|
== Color Control
|
|
459
459
|
|
|
460
|
+
=== Automatic Color Detection
|
|
461
|
+
|
|
462
|
+
Canon automatically detects whether the terminal supports color output:
|
|
463
|
+
|
|
464
|
+
* **TTY detection**: Colors are only enabled when output is to a terminal (not when piped to a file)
|
|
465
|
+
* **NO_COLOR support**: If the `NO_COLOR` environment variable is set (per https://no-color.org/), colors are disabled
|
|
466
|
+
* **Terminal capability detection**: Checks environment variables like `TERM` and `COLORTERM`
|
|
467
|
+
* **CI environment awareness**: Detects and adapts to CI systems (GitHub Actions, Travis CI, etc.)
|
|
468
|
+
|
|
469
|
+
This means colors work automatically in most scenarios without manual configuration.
|
|
470
|
+
|
|
460
471
|
=== Enabling/Disabling Colors
|
|
461
472
|
|
|
462
|
-
Colors
|
|
473
|
+
Colors can be explicitly controlled using the `use_color` option:
|
|
474
|
+
|
|
475
|
+
.Using automatic detection (default)
|
|
476
|
+
[example]
|
|
477
|
+
====
|
|
478
|
+
[source,bash]
|
|
479
|
+
----
|
|
480
|
+
# Auto-detects color support (default)
|
|
481
|
+
canon diff file1.xml file2.xml
|
|
482
|
+
----
|
|
483
|
+
====
|
|
463
484
|
|
|
464
|
-
.
|
|
485
|
+
.Explicit control
|
|
465
486
|
[example]
|
|
466
487
|
====
|
|
467
488
|
[source,bash]
|
|
468
489
|
----
|
|
469
|
-
#
|
|
490
|
+
# Force enable colors
|
|
470
491
|
canon diff file1.xml file2.xml --color
|
|
471
492
|
|
|
472
|
-
#
|
|
493
|
+
# Force disable colors
|
|
473
494
|
canon diff file1.xml file2.xml --no-color
|
|
474
495
|
----
|
|
475
496
|
====
|
|
476
497
|
|
|
477
498
|
.Ruby API
|
|
478
|
-
[example]
|
|
479
|
-
====
|
|
480
499
|
[source,ruby]
|
|
481
500
|
----
|
|
482
|
-
#
|
|
483
|
-
Canon.compare(file1, file2, format: :xml
|
|
501
|
+
# Auto-detect (default)
|
|
502
|
+
Canon.compare(file1, file2, format: :xml)
|
|
484
503
|
|
|
485
|
-
#
|
|
486
|
-
Canon.compare(file1, file2, format: :xml,
|
|
504
|
+
# Explicit control
|
|
505
|
+
Canon.compare(file1, file2, format: :xml, use_color: false)
|
|
487
506
|
----
|
|
488
507
|
====
|
|
489
508
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
509
|
+
=== NO_COLOR Environment Variable
|
|
510
|
+
|
|
511
|
+
Per the https://no-color.org/[NO_COLOR standard], setting the `NO_COLOR`
|
|
512
|
+
environment variable will disable colors:
|
|
513
|
+
|
|
514
|
+
[source,bash]
|
|
494
515
|
----
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
516
|
+
# Disable colors (respected by Canon and other NO_COLOR-aware tools)
|
|
517
|
+
export NO_COLOR=1
|
|
518
|
+
|
|
519
|
+
# Run canon - colors will be disabled
|
|
520
|
+
canon diff file1.xml file2.xml
|
|
499
521
|
----
|
|
500
|
-
====
|
|
501
522
|
|
|
502
|
-
|
|
523
|
+
The `NO_COLOR` variable always takes precedence over other color settings.
|
|
524
|
+
|
|
525
|
+
=== Environment Variables
|
|
526
|
+
|
|
527
|
+
In addition to `NO_COLOR`, Canon supports these environment variables:
|
|
503
528
|
|
|
504
529
|
[source,bash]
|
|
505
530
|
----
|
|
506
|
-
# Disable colors globally
|
|
531
|
+
# Disable colors globally (CANON_USE_COLOR)
|
|
507
532
|
export CANON_USE_COLOR=false
|
|
508
533
|
|
|
509
|
-
# Enable colors globally
|
|
534
|
+
# Enable colors globally (CANON_USE_COLOR)
|
|
510
535
|
export CANON_USE_COLOR=true
|
|
536
|
+
|
|
537
|
+
# Format-specific color control
|
|
538
|
+
export CANON_XML_DIFF_USE_COLOR=false
|
|
539
|
+
export CANON_HTML_DIFF_USE_COLOR=false
|
|
540
|
+
export CANON_JSON_DIFF_USE_COLOR=false
|
|
541
|
+
export CANON_YAML_DIFF_USE_COLOR=false
|
|
511
542
|
----
|
|
512
543
|
|
|
544
|
+
=== Terminal Detection
|
|
545
|
+
|
|
546
|
+
Canon detects terminal capabilities through these environment variables:
|
|
547
|
+
|
|
548
|
+
`COLORTERM`::
|
|
549
|
+
Set to `24bit`, `truecolor`, or `true` indicates True Color support
|
|
550
|
+
|
|
551
|
+
`TERM`:: Terminal type:
|
|
552
|
+
|
|
553
|
+
256-color support::: `xterm-256color`, `screen-256color`
|
|
554
|
+
Direct color support::: `xterm-direct`
|
|
555
|
+
No color support::: `dumb`, `emacs`
|
|
556
|
+
Assume basic ANSI color support::: Most other values
|
|
557
|
+
|
|
558
|
+
`CI`:: CI environment detection
|
|
559
|
+
(plus CI-specific variables)
|
|
560
|
+
|
|
561
|
+
If no terminal information is available, Canon assumes color support for modern
|
|
562
|
+
terminals.
|
|
563
|
+
|
|
513
564
|
|
|
514
565
|
== Diff Type Display Options
|
|
515
566
|
|
data/lib/canon/cli.rb
CHANGED
|
@@ -126,6 +126,24 @@ module Canon
|
|
|
126
126
|
|
|
127
127
|
# Disable color output
|
|
128
128
|
$ canon diff file1.xml file2.xml --no-color
|
|
129
|
+
|
|
130
|
+
# Show raw file contents (for copying to specs)
|
|
131
|
+
$ canon diff file1.xml file2.xml --show-raw-inputs
|
|
132
|
+
|
|
133
|
+
# Show preprocessed contents (what was actually compared)
|
|
134
|
+
$ canon diff file1.xml file2.xml --show-preprocessed-inputs
|
|
135
|
+
|
|
136
|
+
# Show both raw and preprocessed (full trace)
|
|
137
|
+
$ canon diff file1.xml file2.xml --show-raw-inputs --show-preprocessed-inputs
|
|
138
|
+
|
|
139
|
+
# Preprocess with normalization and show what was compared
|
|
140
|
+
$ canon diff file1.xml file2.xml --preprocessing normalize --show-preprocessed-inputs
|
|
141
|
+
|
|
142
|
+
# Show raw inputs with line numbers (RSpec-style)
|
|
143
|
+
$ canon diff file1.xml file2.xml --show-line-numbered-inputs
|
|
144
|
+
|
|
145
|
+
# Verbose mode (shows all three input displays)
|
|
146
|
+
$ canon diff file1.xml file2.xml --verbose
|
|
129
147
|
DESC
|
|
130
148
|
method_option :format,
|
|
131
149
|
aliases: "-f",
|
|
@@ -142,8 +160,7 @@ module Canon
|
|
|
142
160
|
desc: "Format type for second file"
|
|
143
161
|
method_option :color,
|
|
144
162
|
type: :boolean,
|
|
145
|
-
|
|
146
|
-
desc: "Colorize diff output"
|
|
163
|
+
desc: "Colorize diff output (auto-detected by default)"
|
|
147
164
|
method_option :verbose,
|
|
148
165
|
aliases: "-v",
|
|
149
166
|
type: :boolean,
|
|
@@ -213,6 +230,18 @@ module Canon
|
|
|
213
230
|
method_option :diff_grouping_lines,
|
|
214
231
|
type: :numeric,
|
|
215
232
|
desc: "Group diffs within N lines into context blocks (default: no grouping)"
|
|
233
|
+
method_option :show_raw_inputs,
|
|
234
|
+
type: :boolean,
|
|
235
|
+
default: false,
|
|
236
|
+
desc: "Show raw/original file contents before diff"
|
|
237
|
+
method_option :show_preprocessed_inputs,
|
|
238
|
+
type: :boolean,
|
|
239
|
+
default: false,
|
|
240
|
+
desc: "Show preprocessed contents (what was actually compared)"
|
|
241
|
+
method_option :show_line_numbered_inputs,
|
|
242
|
+
type: :boolean,
|
|
243
|
+
default: false,
|
|
244
|
+
desc: "Show raw inputs with line numbers (RSpec-style)"
|
|
216
245
|
def diff(file1, file2)
|
|
217
246
|
Commands::DiffCommand.new(options).run(file1, file2)
|
|
218
247
|
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Canon
|
|
4
|
+
# Detects whether the current terminal supports color output.
|
|
5
|
+
#
|
|
6
|
+
# This class provides cross-platform detection of terminal color capabilities
|
|
7
|
+
# by checking environment variables and, on Unix-like systems, optionally
|
|
8
|
+
# querying the terminfo database.
|
|
9
|
+
#
|
|
10
|
+
# == Detection Logic
|
|
11
|
+
#
|
|
12
|
+
# The detection follows this priority order:
|
|
13
|
+
#
|
|
14
|
+
# 1. **NO_COLOR**: If set (regardless of value), colors are disabled
|
|
15
|
+
# (per https://no-color.org/)
|
|
16
|
+
# 2. **Explicit user choice**: If explicitly set, honor that choice
|
|
17
|
+
# 3. **Terminal capability detection**:
|
|
18
|
+
# - COLORTERM=24bit or truecolor → True color support
|
|
19
|
+
# - TERM ending with 256 or 256color → 256-color support
|
|
20
|
+
# - TERM=dumb, TERM containing "emacs" → No color support
|
|
21
|
+
# - CI environment → Check specific CI variables
|
|
22
|
+
# - TTY detection → Only enable colors if output is to a TTY
|
|
23
|
+
#
|
|
24
|
+
# == Usage
|
|
25
|
+
#
|
|
26
|
+
# # Auto-detect
|
|
27
|
+
# ColorDetector.supports_color? # => true or false
|
|
28
|
+
#
|
|
29
|
+
# # Explicit choice (bypass detection)
|
|
30
|
+
# ColorDetector.supports_color?(explicit: true) # => true
|
|
31
|
+
# ColorDetector.supports_color?(explicit: false) # => false
|
|
32
|
+
#
|
|
33
|
+
# # With output stream check
|
|
34
|
+
# ColorDetector.supports_color?(output: $stdout)
|
|
35
|
+
#
|
|
36
|
+
class ColorDetector
|
|
37
|
+
# Environment variables that indicate color support
|
|
38
|
+
COLOR_TERM_VALUES = %w[24bit truecolor true].freeze
|
|
39
|
+
COLOR_TERM_SUFFIXES = %w[256 256color direct].freeze
|
|
40
|
+
NO_COLOR_TERMS = %w[dumb emacs].freeze
|
|
41
|
+
CI_ENV_VARS = %w[CI GITHUB_ACTIONS TRAVIS GITLAB_CI JENKINS_HOME].freeze
|
|
42
|
+
|
|
43
|
+
class << self
|
|
44
|
+
# Detect whether the current environment supports color output.
|
|
45
|
+
#
|
|
46
|
+
# @param explicit [Boolean, nil] Explicit user choice to bypass detection
|
|
47
|
+
# @param output [IO, nil] Output stream to check (default: $stdout)
|
|
48
|
+
# @return [Boolean] true if colors are supported, false otherwise
|
|
49
|
+
def supports_color?(explicit: nil, output: $stdout)
|
|
50
|
+
# 1. NO_COLOR always wins (per https://no-color.org/)
|
|
51
|
+
return false if ENV.key?("NO_COLOR")
|
|
52
|
+
|
|
53
|
+
# 2. Explicit user choice bypasses detection
|
|
54
|
+
return explicit unless explicit.nil?
|
|
55
|
+
|
|
56
|
+
# 3. Check if output is a TTY (don't use colors for piped/file output)
|
|
57
|
+
return false unless tty?(output)
|
|
58
|
+
|
|
59
|
+
# 4. Check terminal capability indicators
|
|
60
|
+
detect_from_env
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
# Check if output stream is a TTY
|
|
66
|
+
#
|
|
67
|
+
# @param io [IO] Output stream
|
|
68
|
+
# @return [Boolean] true if the stream is a TTY
|
|
69
|
+
def tty?(io)
|
|
70
|
+
return false unless io.respond_to?(:tty?)
|
|
71
|
+
return false unless io.respond_to?(:isatty)
|
|
72
|
+
|
|
73
|
+
# Ruby 2.5+ uses tty?, older uses isatty
|
|
74
|
+
io.tty? || io.isatty
|
|
75
|
+
rescue ArgumentError, IOError
|
|
76
|
+
# Stream might be closed or invalid
|
|
77
|
+
false
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Detect color support from environment variables
|
|
81
|
+
#
|
|
82
|
+
# @return [Boolean] true if colors appear to be supported
|
|
83
|
+
def detect_from_env
|
|
84
|
+
# Check for known color-capable terminals
|
|
85
|
+
colorterm = ENV["COLORTERM"]
|
|
86
|
+
return true if COLOR_TERM_VALUES.include?(colorterm)
|
|
87
|
+
|
|
88
|
+
# Check TERM variable
|
|
89
|
+
term = ENV["TERM"]
|
|
90
|
+
if term
|
|
91
|
+
# Known no-color terminals
|
|
92
|
+
return false if NO_COLOR_TERMS.any? { |t| term.include?(t) }
|
|
93
|
+
# Known color-capable terminals
|
|
94
|
+
return true if COLOR_TERM_SUFFIXES.any? { |s| term.end_with?(s) }
|
|
95
|
+
# Most modern terminals support basic ANSI colors
|
|
96
|
+
return true unless term.empty? || term == "unknown"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Check CI environments
|
|
100
|
+
# Some CI systems support colors, others don't
|
|
101
|
+
return detect_ci_colors if ci_environment?
|
|
102
|
+
|
|
103
|
+
# Default: assume colors are supported on modern terminals
|
|
104
|
+
# This is a safe default for most use cases
|
|
105
|
+
true
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Detect if we're in a CI environment
|
|
109
|
+
#
|
|
110
|
+
# @return [Boolean] true if in a CI environment
|
|
111
|
+
def ci_environment?
|
|
112
|
+
CI_ENV_VARS.any? { |var| ENV.key?(var) }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Detect color support in CI environments
|
|
116
|
+
#
|
|
117
|
+
# Different CI systems have different color support:
|
|
118
|
+
# - GitHub Actions: supports colors (explicit CI env vars)
|
|
119
|
+
# - Travis CI: supports colors
|
|
120
|
+
# - GitLab CI: supports colors
|
|
121
|
+
# - Jenkins: supports colors
|
|
122
|
+
# - Generic CI: check for specific TeamCity/Terminal variables
|
|
123
|
+
#
|
|
124
|
+
# @return [Boolean] true if CI environment likely supports colors
|
|
125
|
+
def detect_ci_colors
|
|
126
|
+
# GitHub Actions explicitly supports colors
|
|
127
|
+
return true if ENV["GITHUB_ACTIONS"]
|
|
128
|
+
|
|
129
|
+
# TeamCity supports colors with specific env var
|
|
130
|
+
return true if ENV["TEAMCITY_VERSION"]
|
|
131
|
+
|
|
132
|
+
# Most modern CI systems support ANSI colors
|
|
133
|
+
# Only disable for explicitly known non-color CI
|
|
134
|
+
return false if ENV["TERM"] == "dumb"
|
|
135
|
+
|
|
136
|
+
# Default to supporting colors in CI
|
|
137
|
+
true
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "../comparison"
|
|
4
4
|
require_relative "../diff_formatter"
|
|
5
|
+
require_relative "../color_detector"
|
|
5
6
|
require "json"
|
|
6
7
|
require "yaml"
|
|
7
8
|
|
|
@@ -48,11 +49,14 @@ module Canon
|
|
|
48
49
|
|
|
49
50
|
# Format and output results
|
|
50
51
|
formatter = Canon::DiffFormatter.new(
|
|
51
|
-
use_color:
|
|
52
|
+
use_color: resolve_color_option,
|
|
52
53
|
mode: mode,
|
|
53
54
|
context_lines: @options.fetch(:context_lines, 3),
|
|
54
55
|
diff_grouping_lines: @options[:diff_grouping_lines],
|
|
55
56
|
show_diffs: @options[:show_diffs]&.to_sym || :all,
|
|
57
|
+
show_raw_inputs: @options[:show_raw_inputs] || false,
|
|
58
|
+
show_preprocessed_inputs: @options[:show_preprocessed_inputs] || false,
|
|
59
|
+
show_line_numbered_inputs: @options[:show_line_numbered_inputs] || false,
|
|
56
60
|
)
|
|
57
61
|
|
|
58
62
|
# Show configuration in verbose mode using shared DebugOutput
|
|
@@ -61,7 +65,7 @@ module Canon
|
|
|
61
65
|
config_output = Canon::DiffFormatter::DebugOutput.verbose_tables_only(
|
|
62
66
|
result,
|
|
63
67
|
{
|
|
64
|
-
use_color:
|
|
68
|
+
use_color: resolve_color_option,
|
|
65
69
|
mode: mode,
|
|
66
70
|
context_lines: @options.fetch(:context_lines, 3),
|
|
67
71
|
diff_grouping_lines: @options[:diff_grouping_lines],
|
|
@@ -275,6 +279,19 @@ module Canon
|
|
|
275
279
|
5_242_880 # Default 5MB
|
|
276
280
|
end
|
|
277
281
|
end
|
|
282
|
+
|
|
283
|
+
# Resolve color option with auto-detection
|
|
284
|
+
#
|
|
285
|
+
# Returns the user's explicit choice if provided, otherwise
|
|
286
|
+
# auto-detects terminal color support.
|
|
287
|
+
#
|
|
288
|
+
# @return [Boolean] true if colors should be used
|
|
289
|
+
def resolve_color_option
|
|
290
|
+
return @options[:color] unless @options[:color].nil?
|
|
291
|
+
|
|
292
|
+
# Auto-detect when no explicit choice was made
|
|
293
|
+
ColorDetector.supports_color?
|
|
294
|
+
end
|
|
278
295
|
end
|
|
279
296
|
end
|
|
280
297
|
end
|
|
@@ -14,6 +14,9 @@ module Canon
|
|
|
14
14
|
show_diffs: :symbol,
|
|
15
15
|
verbose_diff: :boolean,
|
|
16
16
|
algorithm: :symbol,
|
|
17
|
+
show_raw_inputs: :boolean,
|
|
18
|
+
show_preprocessed_inputs: :boolean,
|
|
19
|
+
show_line_numbered_inputs: :boolean,
|
|
17
20
|
|
|
18
21
|
# MatchConfig attributes
|
|
19
22
|
profile: :symbol,
|
|
@@ -42,7 +45,8 @@ module Canon
|
|
|
42
45
|
|
|
43
46
|
def all_diff_attributes
|
|
44
47
|
%i[mode use_color context_lines grouping_lines show_diffs
|
|
45
|
-
verbose_diff algorithm
|
|
48
|
+
verbose_diff algorithm show_raw_inputs show_preprocessed_inputs
|
|
49
|
+
show_line_numbered_inputs max_file_size max_node_count max_diff_lines]
|
|
46
50
|
end
|
|
47
51
|
|
|
48
52
|
def all_match_attributes
|
data/lib/canon/config.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "config/env_provider"
|
|
4
4
|
require_relative "config/override_resolver"
|
|
5
|
+
require_relative "color_detector"
|
|
5
6
|
|
|
6
7
|
module Canon
|
|
7
8
|
# Global configuration for Canon
|
|
@@ -221,6 +222,30 @@ module Canon
|
|
|
221
222
|
@resolver.set_programmatic(:verbose_diff, value)
|
|
222
223
|
end
|
|
223
224
|
|
|
225
|
+
def show_raw_inputs
|
|
226
|
+
@resolver.resolve(:show_raw_inputs)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def show_raw_inputs=(value)
|
|
230
|
+
@resolver.set_programmatic(:show_raw_inputs, value)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def show_preprocessed_inputs
|
|
234
|
+
@resolver.resolve(:show_preprocessed_inputs)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def show_preprocessed_inputs=(value)
|
|
238
|
+
@resolver.set_programmatic(:show_preprocessed_inputs, value)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def show_line_numbered_inputs
|
|
242
|
+
@resolver.resolve(:show_line_numbered_inputs)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def show_line_numbered_inputs=(value)
|
|
246
|
+
@resolver.set_programmatic(:show_line_numbered_inputs, value)
|
|
247
|
+
end
|
|
248
|
+
|
|
224
249
|
def algorithm
|
|
225
250
|
@resolver.resolve(:algorithm)
|
|
226
251
|
end
|
|
@@ -266,6 +291,9 @@ module Canon
|
|
|
266
291
|
show_diffs: show_diffs,
|
|
267
292
|
verbose_diff: verbose_diff,
|
|
268
293
|
diff_algorithm: algorithm,
|
|
294
|
+
show_raw_inputs: show_raw_inputs,
|
|
295
|
+
show_preprocessed_inputs: show_preprocessed_inputs,
|
|
296
|
+
show_line_numbered_inputs: show_line_numbered_inputs,
|
|
269
297
|
max_file_size: max_file_size,
|
|
270
298
|
max_node_count: max_node_count,
|
|
271
299
|
max_diff_lines: max_diff_lines,
|
|
@@ -277,12 +305,15 @@ module Canon
|
|
|
277
305
|
def build_resolver(format)
|
|
278
306
|
defaults = {
|
|
279
307
|
mode: :by_line,
|
|
280
|
-
use_color:
|
|
308
|
+
use_color: ColorDetector.supports_color?,
|
|
281
309
|
context_lines: 3,
|
|
282
310
|
grouping_lines: 10,
|
|
283
311
|
show_diffs: :all,
|
|
284
312
|
verbose_diff: false,
|
|
285
313
|
algorithm: :dom,
|
|
314
|
+
show_raw_inputs: false,
|
|
315
|
+
show_preprocessed_inputs: false,
|
|
316
|
+
show_line_numbered_inputs: false,
|
|
286
317
|
max_file_size: 5_242_880, # 5MB in bytes
|
|
287
318
|
max_node_count: 10_000, # Maximum nodes in tree
|
|
288
319
|
max_diff_lines: 10_000, # Maximum diff output lines
|
data/lib/canon/diff_formatter.rb
CHANGED
|
@@ -162,16 +162,23 @@ module Canon
|
|
|
162
162
|
Comparison::UNEQUAL_PRIMITIVES => "Unequal primitive values",
|
|
163
163
|
}.freeze
|
|
164
164
|
|
|
165
|
+
# rubocop:disable Metrics/ParameterLists
|
|
165
166
|
def initialize(use_color: true, mode: :by_object, context_lines: 3,
|
|
166
167
|
diff_grouping_lines: nil, visualization_map: nil,
|
|
167
168
|
character_map_file: nil, character_definitions: nil,
|
|
168
|
-
show_diffs: :all, verbose_diff: false
|
|
169
|
+
show_diffs: :all, verbose_diff: false,
|
|
170
|
+
show_raw_inputs: false, show_preprocessed_inputs: false,
|
|
171
|
+
show_line_numbered_inputs: false)
|
|
172
|
+
# rubocop:enable Metrics/ParameterLists
|
|
169
173
|
@use_color = use_color
|
|
170
174
|
@mode = mode
|
|
171
175
|
@context_lines = context_lines
|
|
172
176
|
@diff_grouping_lines = diff_grouping_lines
|
|
173
177
|
@show_diffs = show_diffs
|
|
174
178
|
@verbose_diff = verbose_diff
|
|
179
|
+
@show_raw_inputs = show_raw_inputs
|
|
180
|
+
@show_preprocessed_inputs = show_preprocessed_inputs
|
|
181
|
+
@show_line_numbered_inputs = show_line_numbered_inputs
|
|
175
182
|
@visualization_map = build_visualization_map(
|
|
176
183
|
visualization_map: visualization_map,
|
|
177
184
|
character_map_file: character_map_file,
|
|
@@ -329,15 +336,39 @@ module Canon
|
|
|
329
336
|
)
|
|
330
337
|
end
|
|
331
338
|
|
|
332
|
-
#
|
|
333
|
-
|
|
339
|
+
# verbose_diff enables all three input displays as a convenience
|
|
340
|
+
verbose = @verbose_diff || @show_raw_inputs
|
|
341
|
+
show_prep = @verbose_diff || @show_preprocessed_inputs
|
|
342
|
+
show_line = @verbose_diff || @show_line_numbered_inputs
|
|
343
|
+
|
|
344
|
+
# 3. Raw/Original Input Display (when show_raw_inputs is enabled)
|
|
345
|
+
if verbose && comparison_result.is_a?(Canon::Comparison::ComparisonResult)
|
|
346
|
+
original1, original2 = comparison_result.original_strings
|
|
347
|
+
if original1 && original2
|
|
348
|
+
output << format_raw_inputs(original1, original2)
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# 4. Preprocessed Input Display (when show_preprocessed_inputs is enabled)
|
|
353
|
+
if show_prep && comparison_result.is_a?(Canon::Comparison::ComparisonResult)
|
|
354
|
+
preprocessed1, preprocessed2 = comparison_result.preprocessed_strings
|
|
355
|
+
if preprocessed1 && preprocessed2
|
|
356
|
+
preprocessing_info = comparison_result.match_options&.dig(:match,
|
|
357
|
+
:preprocessing)
|
|
358
|
+
output << format_preprocessed_inputs(preprocessed1, preprocessed2,
|
|
359
|
+
preprocessing_info)
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
# 5. Line-Numbered Input Display (when show_line_numbered_inputs is enabled)
|
|
364
|
+
if show_line && comparison_result.is_a?(Canon::Comparison::ComparisonResult)
|
|
334
365
|
original1, original2 = comparison_result.original_strings
|
|
335
366
|
if original1 && original2
|
|
336
|
-
output <<
|
|
367
|
+
output << format_line_numbered_inputs(original1, original2)
|
|
337
368
|
end
|
|
338
369
|
end
|
|
339
370
|
|
|
340
|
-
#
|
|
371
|
+
# 6. Main diff output (by-line or by-object) - ALWAYS
|
|
341
372
|
|
|
342
373
|
# Check if comparison result is a ComparisonResult object
|
|
343
374
|
if comparison_result.is_a?(Canon::Comparison::ComparisonResult)
|
|
@@ -428,24 +459,24 @@ module Canon
|
|
|
428
459
|
html.to_s
|
|
429
460
|
end
|
|
430
461
|
|
|
431
|
-
# Format original input strings
|
|
432
|
-
# Shows the actual strings that were passed in
|
|
462
|
+
# Format original input strings with line numbers (RSpec-style)
|
|
463
|
+
# Shows the actual strings that were passed in with line numbers for reference
|
|
433
464
|
#
|
|
434
465
|
# @param original1 [String] First original input string
|
|
435
466
|
# @param original2 [String] Second original input string
|
|
436
|
-
# @return [String] Formatted display
|
|
437
|
-
def
|
|
467
|
+
# @return [String] Formatted display with line numbers
|
|
468
|
+
def format_line_numbered_inputs(original1, original2)
|
|
438
469
|
return "" if original1.nil? || original2.nil?
|
|
439
470
|
|
|
440
471
|
output = []
|
|
441
472
|
output << ""
|
|
442
473
|
output << colorize("=" * 70, :cyan, :bold)
|
|
443
|
-
output << colorize(" ORIGINAL
|
|
474
|
+
output << colorize(" ORIGINAL INPUTS (with line numbers)", :cyan, :bold)
|
|
444
475
|
output << colorize("=" * 70, :cyan, :bold)
|
|
445
476
|
output << ""
|
|
446
477
|
|
|
447
478
|
# Format expected
|
|
448
|
-
output << colorize("Expected
|
|
479
|
+
output << colorize("Expected:", :yellow, :bold)
|
|
449
480
|
original1.each_line.with_index do |line, idx|
|
|
450
481
|
output << " #{colorize(sprintf('%4d', idx + 1),
|
|
451
482
|
:blue)} | #{line.chomp}"
|
|
@@ -453,7 +484,7 @@ module Canon
|
|
|
453
484
|
output << ""
|
|
454
485
|
|
|
455
486
|
# Format actual
|
|
456
|
-
output << colorize("
|
|
487
|
+
output << colorize("Received:", :yellow, :bold)
|
|
457
488
|
original2.each_line.with_index do |line, idx|
|
|
458
489
|
output << " #{colorize(sprintf('%4d', idx + 1),
|
|
459
490
|
:blue)} | #{line.chomp}"
|
|
@@ -465,6 +496,65 @@ module Canon
|
|
|
465
496
|
output.join("\n")
|
|
466
497
|
end
|
|
467
498
|
|
|
499
|
+
# Format raw/original inputs for display (user-friendly copyable format)
|
|
500
|
+
# Shows the raw file contents before any preprocessing
|
|
501
|
+
#
|
|
502
|
+
# @param raw1 [String] First raw input string
|
|
503
|
+
# @param raw2 [String] Second raw input string
|
|
504
|
+
# @return [String] Formatted display of raw inputs
|
|
505
|
+
def format_raw_inputs(raw1, raw2)
|
|
506
|
+
return "" if raw1.nil? || raw2.nil?
|
|
507
|
+
|
|
508
|
+
output = []
|
|
509
|
+
output << ""
|
|
510
|
+
output << colorize("=== ORIGINAL INPUTS (Raw) ===", :cyan, :bold)
|
|
511
|
+
output << ""
|
|
512
|
+
output << colorize("EXPECTED:", :yellow, :bold)
|
|
513
|
+
output << "-" * 70
|
|
514
|
+
output << raw1
|
|
515
|
+
output << ""
|
|
516
|
+
output << colorize("RECEIVED:", :yellow, :bold)
|
|
517
|
+
output << "-" * 70
|
|
518
|
+
output << raw2
|
|
519
|
+
output << ""
|
|
520
|
+
output << ""
|
|
521
|
+
|
|
522
|
+
output.join("\n")
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
# Format preprocessed inputs for display (what was actually compared)
|
|
526
|
+
# Shows the content after preprocessing (c14n, normalize, format, etc.)
|
|
527
|
+
#
|
|
528
|
+
# @param preprocessed1 [String] First preprocessed string
|
|
529
|
+
# @param preprocessed2 [String] Second preprocessed string
|
|
530
|
+
# @param preprocessing_info [Symbol, nil] Preprocessing mode (:c14n, :normalize, :format, etc.)
|
|
531
|
+
# @return [String] Formatted display of preprocessed inputs
|
|
532
|
+
def format_preprocessed_inputs(preprocessed1, preprocessed2,
|
|
533
|
+
preprocessing_info = nil)
|
|
534
|
+
return "" if preprocessed1.nil? || preprocessed2.nil?
|
|
535
|
+
|
|
536
|
+
output = []
|
|
537
|
+
output << ""
|
|
538
|
+
output << colorize("=== PREPROCESSED INPUTS (Compared) ===", :cyan, :bold)
|
|
539
|
+
|
|
540
|
+
# Show preprocessing mode if available
|
|
541
|
+
if preprocessing_info
|
|
542
|
+
output << "Preprocessing: #{preprocessing_info}"
|
|
543
|
+
end
|
|
544
|
+
output << ""
|
|
545
|
+
output << colorize("EXPECTED:", :yellow, :bold)
|
|
546
|
+
output << "-" * 70
|
|
547
|
+
output << preprocessed1
|
|
548
|
+
output << ""
|
|
549
|
+
output << colorize("RECEIVED:", :yellow, :bold)
|
|
550
|
+
output << "-" * 70
|
|
551
|
+
output << preprocessed2
|
|
552
|
+
output << ""
|
|
553
|
+
output << ""
|
|
554
|
+
|
|
555
|
+
output.join("\n")
|
|
556
|
+
end
|
|
557
|
+
|
|
468
558
|
# Build the final visualization map from various customization options
|
|
469
559
|
#
|
|
470
560
|
# @param visualization_map [Hash, nil] Complete custom visualization map
|
data/lib/canon/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: canon
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -193,6 +193,7 @@ files:
|
|
|
193
193
|
- lib/canon.rb
|
|
194
194
|
- lib/canon/cache.rb
|
|
195
195
|
- lib/canon/cli.rb
|
|
196
|
+
- lib/canon/color_detector.rb
|
|
196
197
|
- lib/canon/commands/diff_command.rb
|
|
197
198
|
- lib/canon/commands/format_command.rb
|
|
198
199
|
- lib/canon/comparison.rb
|