View Source Diffie (Diffie v0.3.2)

Diffie is a module for making human-readable reports of the differences between two strings, or between two lists of objects (of whatever type).

NOT FOR DIFFIE-HELLMAN KEY EXCHANGE!

Summary

Functions

diff_report(old, new, opts \\ [])

Functions

diff_report(old, new, opts \\ [])

diff_report(old, new, opts \\ [])

diff_report returns a string containing a report (hence the name), similar to a simplified version of the diff command-line utility, of the differences between the two strings, or two lists.

Given two strings, by default it works line by line, and is case-sensitive, but you can change this with options, as follows:

  • :ignore_case - (boolean) be case-insensitive when comparing the strings. Does not get applied to strings within objects. If you want that, you will have to use a custom transformation function (see below). Also applicable to the version that takes two lists, if you pass it two lists of strings.

  • :omit_deletes - (boolean) omit deleted items, and old versions of changed items. Also applicable to the version that takes two lists. Causes the new version of a changed item to be marked with "Updated" rather than "Into".

  • :split_on - (string or regex) split strings on this, not \n.

  • :transform - (function reference) function to apply to items in the report. Also applicable to the version that takes two lists.

If you do not supply a transformation:

  • strings will be handled as-is,
  • items that implement the String.chars protocol will be sent to to_string,
  • and anything else will be sent to inspect.

If your list items do not implement String.chars and you wish to apply some transformation, that transformation must include turning them into something that does, such as piping through inspect.

Examples:

iex> Diffie.diff_report("foo\nbar", "foo\nbar\nbaz")
"Added:\n> baz"

iex> Diffie.diff_report("foo\nbar\nbaz", "foo\nbaz")
"Removed:\n< bar"

iex> Diffie.diff_report("foo\nbar\nbaz", "foo\nboo\nbaz")
"Changed:\n< bar\n\nInto:\n> boo"

iex> Diffie.diff_report("fooXXbarXXbaz", "fooXXbaz", split_on: "XX")
"Removed:\n< bar"

iex> Diffie.diff_report("bar", "baz", split_on: "")
"Changed:\n< r\n\nInto:\n> z"

iex> Diffie.diff_report("foo\nbar\nbaz", "foo\nboo\nbaz", omit_deletes: true)
"Updated:\n> boo"  # note removal of "Changed:\n< r\n\n" and different marker

iex> Diffie.diff_report("foo bar\nbaz quux", "fox bear\nbaz quix",
...>                    split_on: ~r{\s})
"Changed:\n< foo\n< bar\n\nInto:\n> fox\n> bear\n\nChanged:\n< quux\n\nInto:\n> quix"

iex> Diffie.diff_report("foo\nbar\nbaz", "foo\nbaz", transform: &String.upcase/1)
"Removed:\n< BAR"

iex> Diffie.diff_report("The quick brown fox jumps\nover the lazy dog.",
...>                    "That fox\njumps quickly over\nthe dig!",
...>                    split_on: ~r/\s/, transform: &String.upcase/1)
"Changed:\n< THE\n< QUICK\n< BROWN\n\nInto:\n> THAT\n\nAdded:\n> QUICKLY\n\nChanged:\n< LAZY\n< DOG.\n\nInto:\n> DIG!"

iex> Diffie.diff_report("The quick brown fox jumps over the lazy dog.",
...>                    "That fox jumps quickly over the dig!",
...>                    split_on: ~r/\s/, omit_deletes: true)
"Updated:\n> That\n\nAdded:\n> quickly\n\nUpdated:\n> dig!"

iex> Diffie.diff_report("The quick brown fox jumps over the lazy dog",
...>                    "That fox jumps quickly",
...>                    split_on: ~r/\s/, omit_deletes: true)
"Updated:\n> That\n\nUpdated:\n> quickly"

iex> Diffie.diff_report("The quick brown fox jumps over the lazy dog",
...>                    "That fox jumps quickly over",
...>                    split_on: ~r/\s/, omit_deletes: true)
"Updated:\n> That\n\nAdded:\n> quickly"

iex> Diffie.diff_report([1,2], [1,2,3])
"Added:\n> 3"

iex> Diffie.diff_report([1,2,3], [1,2])
"Removed:\n< 3"

iex> Diffie.diff_report([1,2,3,4,6], [1,2,5])
"Changed:\n< 3\n< 4\n< 6\n\nInto:\n> 5"

iex> Diffie.diff_report([1,2,3,4,6], [1,2,5,6,7], omit_deletes: true)
"Updated:\n> 5\n\nAdded:\n> 7"  # note removal of "Changed:\n< 3\n\n", and different marker

iex> Diffie.diff_report([1,2,3], [1,2], omit_deletes: true)
""

iex> Diffie.diff_report([1,2], [1,2,3], transform: fn x->x*2 end)
"Added:\n> 6"

iex> alice = %{name: "Alice", age: "29"}
iex> bob = %{name: "Bob", age: "52"}
iex> Diffie.diff_report([alice], [alice,bob])
"Added:\n> %{name: \"Bob\", age: \"52\"}"

iex> alice = %{name: "Alice", age: "29"}
iex> bob = %{name: "Bob", age: "52"}
iex> Diffie.diff_report([alice], [alice, bob],
...>                    transform: fn p -> Map.delete(p, :age) end)
** (Protocol.UndefinedError) protocol String.Chars not implemented for %{name: "Bob"} of type Map. This protocol is implemented for the following type(s): Atom, BitString, Date, DateTime, Float, Integer, List, NaiveDateTime, Time, URI, Version, Version.Requirement

iex> alice = %{name: "Alice", age: "29"}
iex> bob = %{name: "Bob", age: "52"}
iex> Diffie.diff_report([alice], [alice, bob],
...>                    transform: fn p -> Map.delete(p, :age) |> inspect end)
"Added:\n> %{name: \"Bob\"}"

iex> alice = %{name: "Alice", age: "29"}
iex> bob = %{name: "Bob", age: "52"}
iex> Diffie.diff_report([alice], [alice, bob],
...>                    transform: fn p -> p.name end)
"Added:\n> Bob"