differ v0.1.1 Differ View Source
Module that computes diff
for terms
Using with structs
It is possible to use Differ
with structs, you need to derive default implementation
for Differ.Diffable
and Differ.Patchable
protocols:
defmodule User do
@derive [Differ.Diffable, Differ.Patchable]
defstruct name: "", age: 21
end
And now you can call Differ.diff/2
with your structs:
iex> Differ.diff(%User{name: "John"}, %User{name: "John Smith"})
[{:name, :diff, [eq: "John", ins: " Smith"]}, {:age, :eq, 21}]
You can skip some fields aswell (e.g. timestamps, id), by using skip
option, when deriving default implementation
@derive [{Differ.Diffable, skip: [:updated_at, :diffs]}, Differ.Patchable]
schema "posts" do
field :content, :string
field :tags, {:array, :string}
field :title, :string
field :diffs, {:array, Diff}, default: []
timestamps()
end
Link to this section Summary
Functions
Returns diff between 2 terms that implement Differ.Diffable
protocol
Allows to visualize diff
Optimizes diff size
Applies diff and returns patched value
Same as Differ.patch/2
, but returns value and throws on error
Reverts diff and returns patched value
Same as Differ.revert/2
, but returns value and throws on error
Link to this section Functions
diff(old, new)
View Sourcediff(Differ.Diffable.t(), Differ.Diffable.t()) :: Differ.Diffable.diff()
Returns diff between 2 terms that implement Differ.Diffable
protocol
Diff here is edit script, that should be compatible with List.myers_difference/3
Examples
iex> Differ.diff(%{key: "value"}, %{key: "value"})
[eq: %{key: "value"}]
iex> Differ.diff("Hello!", "Hey!")
[eq: "He", del: "llo", ins: "y", eq: "!"]
explain(term, diff, cb, opts \\ [])
View Source (since 0.1.1)explain( Differ.Patchable.t(), Differ.Diffable.diff(), (Differ.Diffable.operation() -> String.t()), [{:revert, true}] ) :: String.t()
Allows to visualize diff
Applies diff to a term
and calls cb
on each operation,
result of cb
will be used to construct new value for term
Options
revert
- reverts term with given diff, before apply (defaulttrue
)
Examples
iex> Differ.explain("qwerty", [eq: "qwer", del: "123", ins: "ty"],
...> fn {op, val} ->
...> case op do
...> :del -> "--" <> val
...> :ins -> "++" <> val
...> _ -> val
...> end
...> end)
"qwer--123++ty"
optimize(diff, level \\ 1)
View Sourceoptimize(Differ.Diffable.diff(), Differ.Diffable.level()) :: Differ.Diffable.diff()
Optimizes diff size
Optimizes size by removing data that is not relevant for change. There is 3 levels of optimization:
- Safe - can have conflicts, can be reverted
- Safe-ish - you lose ability to get conflicts, but still can be reverted
- Un-safe - no conflicts and no reverting
Examples
iex> regular_diff = Differ.diff(%{"same" => "same"}, %{"same" => "same", "new" => "val"})
[{"same", :eq, "same"}, {"new", :ins, "val"}]
iex> Differ.optimize(regular_diff)
[{"new", :ins, "val"}]
iex> diff = Differ.diff("Somewhat long string with a litle change athere", "Somewhat long string with a litle change here")
[eq: "Somewhat long string with a litle change ", del: "at", eq: "here"]
iex> Differ.optimize(diff, 2)
[skip: 41, del: "at", skip: 4]
iex> Differ.optimize(diff, 3)
[skip: 41, remove: 2, skip: 4]
patch(obj, diff)
View Sourcepatch(Differ.Patchable.t(), Differ.Diffable.diff()) :: {:ok, Differ.Patchable.t()} | {:error, String.t()}
Applies diff and returns patched value
Examples
iex> old_list = ["22", "1"]
iex> diff = Differ.diff(old_list, ["2", "1", "3"])
iex> Differ.patch(old_list, diff)
{:ok, ["2", "1", "3"]}
patch!(obj, diff)
View Sourcepatch!(Differ.Patchable.t(), Differ.Diffable.diff()) :: Differ.Patchable.t()
Same as Differ.patch/2
, but returns value and throws on error
revert(obj, diff)
View Sourcerevert(Differ.Patchable.t(), Differ.Diffable.diff()) :: {:ok, Differ.Patchable.t()} | {:error, String.t()}
Reverts diff and returns patched value
Examples
iex> old_list = ["22", "1"]
iex> new_list = ["2", "1", "3"]
iex> diff = Differ.diff(old_list, new_list)
iex> Differ.revert(new_list, diff)
{:ok, ["22", "1"]}
revert!(obj, diff)
View Sourcerevert!(Differ.Patchable.t(), Differ.Diffable.diff()) :: Differ.Patchable.t()
Same as Differ.revert/2
, but returns value and throws on error