Skip to content

Commit f8c35ae

Browse files
committed
Add a way to elide diffs
When looking at a large diff for which many of the lines are unchanged it can be difficult to locate the lines which are changed. Text-oriented diffs such as those you get from a conventional version control system solve this problem by collapsing parts of the diff to show you only the most important lines (and also including some unimportant lines, aka context, so that you know where they fit within the bigger picture): ``` diff --git a/README.md b/README.md index 56b046c..b38f4ca 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,6 @@ SuperDiff.configure do |config| config.add_extra_differ_class(YourDiffer) config.add_extra_operation_tree_builder_class(YourOperationTreeBuilder) config.add_extra_operation_tree_class(YourOperationTree) - config.add_extra_diff_formatter_class(YourDiffFormatter) end ``` This commit implements a similar feature for data-oriented diffs. It adds three new configuration options to allow you to control the elision logic: * `diff_elision_enabled` — The elision logic is disabled by default so as not to surprise people, so setting this to `true` will turn it on. * `diff_elision_threshold` — This controls the maximum number of unchanged lines in between changed lines that you want to keep. The gem will collapse the data structures in this space as much as possible until the limit is reached. * `diff_elision_padding` — This is the option that's similar to the "context" in text-based diffs and controls how many unchanged lines you want to keep around before and after changed lines. The gem will guarantee that no lines in this padding will ever be collapsed. Here is a simple example. If you add this to your test helper: ``` ruby SuperDiff.configure do |config| config.diff_elision_enabled = true config.diff_elision_threshold = 5 end ``` And you have this test: ``` ruby expected = [ "Afghanistan", "Aland Islands", "Albania", "American Samoa", "Andorra", "Angola", "Anguilla", "Antarctica", "Antigua And Barbuda", "Argentina", "Aruba", "Australia" ] actual = [ "Afghanistan", "Aland Islands", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antarctica", "Antigua And Barbuda", "Armenia", "Aruba", "Australia" ] expect(actual).to eq(expected) ``` Then you will get a diff that looks like: ``` [ "Afghanistan", "Aland Islands", - "Albania", + "Algeria", "American Samoa", "Andorra", # ... "Antarctica", "Antigua And Barbuda", - "Argentina", + "Armenia", "Aruba", "Australia" ] ``` Now let's consider this example: ``` ruby expected = { foo: { bar: [ "one", "two", "three" ], baz: "qux", fizz: "buzz", zing: "bing" } } actual = [ foo: { bar: [ "one", "two", "tree" ], baz: "qux", fizz: "buzz", zing: "bing" } ] expect(actual).to eq(expected) ``` With the following configuration: ``` ruby SuperDiff.configure do |config| config.diff_elision_enabled = true config.diff_elision_threshold = 0 end ``` you would get: ``` { foo: { bar: [ # ... - "three" + "tree" ], # ... } } ``` whereas with a configuration of: ``` ruby SuperDiff.configure do |config| config.diff_elision_enabled = true config.diff_elision_threshold = 0 config.diff_elision_padding = 2 end ``` you would get: ``` { foo: { bar: [ "one", "two", - "three" + "tree" ], baz: "qux", # ... } } ```
1 parent dcdf05e commit f8c35ae

File tree

170 files changed

+11089
-2545
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

170 files changed

+11089
-2545
lines changed

CHANGELOG.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,59 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Breaking changes
6+
7+
* Continuing with the previous release, diff formatters are now gone in favor of
8+
operation tree flatteners. If you have a custom diff formatter, you will want
9+
to inherit from SuperDiff::DiffFormatters::Base (or an appropriate subclass).
10+
Additionally, the `add_extra_diff_formatter_class` configuration option has
11+
disappeared; instead, operation tree classes are expected to have an
12+
`operation_tree_flattener_class` method.
13+
14+
### Features
15+
16+
* Add the ability to compress long diffs by eliding unimportant sections. This
17+
functionality is not enabled by default; rather, you will need to activate it
18+
and then configure it. At a minimum, you will want to add something like this
19+
to your spec helper:
20+
21+
``` ruby
22+
SuperDiff.configure do |config|
23+
config.diff_elision_enabled = true
24+
config.diff_elision_threshold = 10
25+
end
26+
```
27+
28+
Here, `diff_elision_threshold` controls the minimum number of lines that are
29+
changed that you want to see in between lines that are unchanged (everything
30+
else will be elided as much as possible in a way that makes sense). Here is
31+
another possible configuration:
32+
33+
``` ruby
34+
SuperDiff.configure do |config|
35+
config.diff_elision_enabled = true
36+
config.diff_elision_threshold = 10
37+
config.diff_elision_padding = 5
38+
end
39+
```
40+
41+
Here, `diff_elision_padding` controls the amount of context that you want to
42+
preserve around changed lines in the diff. This makes this functionality act
43+
closer to diffs you might see in a version control system.
44+
45+
### Features
46+
47+
* Update inspection of Doubles to include stubbed methods and their values.
48+
49+
### Improvements
50+
51+
* Change how objects are inspected on a single line so that instance variables
52+
are always sorted.
53+
* Make a tweak to how hashes are presented in diffs and inspections: a hash that
54+
has a mixture of symbols and strings will be presented as though all keys are
55+
strings (i.e. hashrocket syntax).
56+
357
## 0.5.1 - 2020-06-19
458

559
### Bug fixes

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ SuperDiff.configure do |config|
169169
config.add_extra_differ_class(YourDiffer)
170170
config.add_extra_operation_tree_builder_class(YourOperationTreeBuilder)
171171
config.add_extra_operation_tree_class(YourOperationTree)
172-
config.add_extra_diff_formatter_class(YourDiffFormatter)
173172
end
174173
```
175174

config/zeus_plan.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,15 @@ class CustomZeusPlan < Zeus::Plan
1818
:confirm_started,
1919
)
2020

21-
def initialize(using_outside_of_zeus: false, color_enabled: false)
21+
def initialize(
22+
using_outside_of_zeus: false,
23+
color_enabled: false,
24+
configuration: {}
25+
)
2226
@test_plan = TestPlan.new(
2327
using_outside_of_zeus: using_outside_of_zeus,
2428
color_enabled: color_enabled,
29+
configuration: configuration,
2530
)
2631
end
2732
end

lib/super_diff.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module SuperDiff
77
:ColorizedDocumentExtensions,
88
"super_diff/colorized_document_extensions",
99
)
10+
autoload :OperationTreeFlatteners, "super_diff/operation_tree_flatteners"
1011
autoload :Configuration, "super_diff/configuration"
1112
autoload :Csi, "super_diff/csi"
1213
autoload :DiffFormatters, "super_diff/diff_formatters"
@@ -15,6 +16,10 @@ module SuperDiff
1516
autoload :Errors, "super_diff/errors"
1617
autoload :Helpers, "super_diff/helpers"
1718
autoload :ImplementationChecks, "super_diff/implementation_checks"
19+
autoload :Line, "super_diff/line"
20+
autoload :TieredLines, "super_diff/tiered_lines"
21+
autoload :TieredLinesElider, "super_diff/tiered_lines_elider"
22+
autoload :TieredLinesFormatter, "super_diff/tiered_lines_formatter"
1823
autoload :ObjectInspection, "super_diff/object_inspection"
1924
autoload :OperationTrees, "super_diff/operation_trees"
2025
autoload :OperationTreeBuilders, "super_diff/operation_tree_builders"
@@ -24,12 +29,14 @@ module SuperDiff
2429
COLORS = {
2530
alpha: :magenta,
2631
beta: :yellow,
32+
gamma: :cyan,
2733
border: :blue,
2834
header: :white,
2935
}.freeze
3036

3137
def self.configure
3238
yield configuration
39+
configuration.updated
3340
end
3441

3542
def self.configuration
@@ -42,4 +49,13 @@ def self.time_like?(value)
4249
(value.respond_to?(:acts_like_time?) && value.acts_like_time?) ||
4350
value.is_a?(Time)
4451
end
52+
53+
def self.primitive?(value)
54+
case value
55+
when true, false, nil, Symbol, Numeric, Regexp, Class
56+
true
57+
else
58+
false
59+
end
60+
end
4561
end

lib/super_diff/active_record.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
module SuperDiff
44
module ActiveRecord
5-
autoload :DiffFormatters, "super_diff/active_record/diff_formatters"
65
autoload :Differs, "super_diff/active_record/differs"
76
autoload(
87
:ObjectInspection,
@@ -16,6 +15,10 @@ module ActiveRecord
1615
:OperationTreeBuilders,
1716
"super_diff/active_record/operation_tree_builders",
1817
)
18+
autoload(
19+
:OperationTreeFlatteners,
20+
"super_diff/active_record/operation_tree_flatteners",
21+
)
1922

2023
SuperDiff.configure do |config|
2124
config.add_extra_differ_classes(
@@ -25,12 +28,9 @@ module ActiveRecord
2528
OperationTreeBuilders::ActiveRecordModel,
2629
OperationTreeBuilders::ActiveRecordRelation,
2730
)
28-
config.add_extra_diff_formatter_classes(
29-
DiffFormatters::ActiveRecordRelation,
30-
)
31-
config.add_extra_inspector_classes(
32-
ObjectInspection::Inspectors::ActiveRecordModel,
33-
ObjectInspection::Inspectors::ActiveRecordRelation,
31+
config.add_extra_inspection_tree_builder_classes(
32+
ObjectInspection::InspectionTreeBuilders::ActiveRecordModel,
33+
ObjectInspection::InspectionTreeBuilders::ActiveRecordRelation,
3434
)
3535
end
3636
end

lib/super_diff/active_record/diff_formatters.rb

Lines changed: 0 additions & 10 deletions
This file was deleted.

lib/super_diff/active_record/diff_formatters/active_record_relation.rb

Lines changed: 0 additions & 23 deletions
This file was deleted.

lib/super_diff/active_record/differs/active_record_relation.rb

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,10 @@ def self.applies_to?(expected, actual)
77
actual.is_a?(::ActiveRecord::Relation)
88
end
99

10-
def call
11-
DiffFormatters::ActiveRecordRelation.call(
12-
operation_tree,
13-
indent_level: indent_level,
14-
)
15-
end
16-
17-
private
10+
protected
1811

19-
def operation_tree
20-
OperationTreeBuilders::ActiveRecordRelation.call(
21-
expected: expected,
22-
actual: actual,
23-
)
12+
def operation_tree_builder_class
13+
OperationTreeBuilders::ActiveRecordRelation
2414
end
2515
end
2616
end

lib/super_diff/active_record/object_inspection.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@ module SuperDiff
22
module ActiveRecord
33
module ObjectInspection
44
autoload(
5-
:Inspectors,
6-
"super_diff/active_record/object_inspection/inspectors",
7-
)
8-
autoload(
9-
:MapExtension,
10-
"super_diff/active_record/object_inspection/map_extension",
5+
:InspectionTreeBuilders,
6+
"super_diff/active_record/object_inspection/inspection_tree_builders",
117
)
128
end
139
end
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module SuperDiff
2+
module ActiveRecord
3+
module ObjectInspection
4+
module InspectionTreeBuilders
5+
autoload(
6+
:ActiveRecordModel,
7+
"super_diff/active_record/object_inspection/inspection_tree_builders/active_record_model",
8+
)
9+
autoload(
10+
:ActiveRecordRelation,
11+
"super_diff/active_record/object_inspection/inspection_tree_builders/active_record_relation",
12+
)
13+
end
14+
end
15+
end
16+
end

0 commit comments

Comments
 (0)