When looking at a large diff for which many of the lines do not change,
it can be difficult to locate the lines which do. Text-oriented
diffs such as those you get from a conventional version control system
solve this problem by removing those unchanged lines from the diff
entirely. For instance, here is a section of the README with a line
removed. Notice that only the part of the file we care about, which is
around the line deleted, is displayed in the diff:
```
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 two 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_maximum` — This number controls what happens to
unchanged lines (i.e. lines that are neither "insert" lines nor
"delete" lines) that are in between changed lines. If a section of
unchanged lines is beyond this number, the gem will elide (a fancy
word for remove) the data structures within that section as much as
possible until the limit is reached or it cannot go further. Elided
lines are replaced with a `# ...` marker.
Here are a few examples:
\### Elision enabled
If you add this to your test helper:
``` ruby
SuperDiff.configure do |config|
config.diff_elision_enabled = true
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:
```
[
# ...
- "Albania",
+ "Algeria",
# ...
- "Argentina",
+ "Armenia",
"Aruba",
"Australia"
]
```
\### Elision enabled and maximum specified
Configuration:
``` ruby
SuperDiff.configure do |config|
config.diff_elision_enabled = true
config.diff_elision_maximum = 5
end
```
Test:
```
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)
```
Resulting diff:
```
[
"Afghanistan",
"Aland Islands",
- "Albania",
+ "Algeria",
"American Samoa",
"Andorra",
# ...
"Antarctica",
"Antigua And Barbuda",
- "Argentina",
+ "Armenia",
"Aruba",
"Australia"
]
```
\### Elision enabled and maximum specified, but indentation limits complete elision
Configuration:
``` ruby
SuperDiff.configure do |config|
config.diff_elision_enabled = true
end
```
Test:
``` 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)
```
Resulting diff:
```
{
foo: {
bar: [
# ...
- "three"
+ "tree"
],
# ...
}
}
```
Notice how we cannot fully elide all of the unchanged lines in this case
because otherwise the diff would look like this and it wouldn't make
sense:
```
# ...
- "three"
+ "tree"
# ...
```