View Source TextDiff (TextDiff v0.1.0)

Formats the diff between two strings.

Examples

iex> code = """
...> defmodule Foo do
...>   @moduledoc   false
...>
...>   def foo, do:  :foo
...>
...>   def three_times(x) do
...>     {x,
...>      x,x}
...>   end
...>
...>   def bar(x) do
...>     {:bar, x}
...>   end
...> end\
...> """
...> formatted = code |> Code.format_string!() |> IO.iodata_to_binary()
...> code
...> |> TextDiff.format(formatted, color: false)
...> |> IO.iodata_to_binary()
"""
 1  1   |defmodule Foo do
 2    - |  @moduledoc   false
    2 + |  @moduledoc false
 3  3   |
 4    - |  def foo, do:  :foo
    4 + |  def foo, do: :foo
 5  5   |
 6  6   |  def three_times(x) do
 7    - |    {x,
 8    - |     x,x}
    7 + |    {x, x, x}
 9  8   |  end
10  9   |
     ...|
"""

Summary

Functions

@spec default_opts() :: keyword()
Link to this function

format(code, code, opts \\ default_opts())

View Source
@spec format(String.t(), String.t(), keyword()) :: iodata()

Formats the diff between two strings.

The returned iodata shows the lines with changes and 2 lines before and after the changed positions. The string contains also a gutter with line number and a - or + for removed and added lines. Multiple lines without changes are marked with ... in the gutter.

Options

  • :after - the count of lines printed after each change. Defaults to 2.
  • :before - the count of lines printed before each change. Defaults to 2.
  • :color - enables color in the output. Defaults to true.
  • :line_numbers - enables line numbers. Defaults to true.
  • :line - the line number of the first line. Defaults to 1.
  • :tokenizer - a function that splits a line of text into distinct tokens that should be compared when creating a colorized diff of a single line. The default tokenizer prioritizes highlighting entire words, so a line that updates two to three would appear as removing two and adding three, instead of keeping the t, removing wo, and adding hree. :tokenizer may be a function that accepts a single argument or an MFA tuple, where the line of text will be prepended to the given arguments.
  • :colorizer - a function that accepts a string and a color token (:red, :green, etc.) and returns iodata with that formatting applied. May be a function that accepts 2 arguments or an MFA tuple, where the string and color will be prepended to the given arguments. Defaults to a colorizer based on IO.ANSI.format/1.
  • :format - optional keyword list of formatting options. See "Formatting" below.

Formatting

Alternative formatting options can be passed to control the gutter, colors, and the separator between the gutter and line of text in the rendered diff. The separator is the same for all lines, but the gutter and colors differ depending on the operation: :eq, :del, :ins, :skip.

The options (and their defaults) are:

  • :separator - "|"
  • :gutter
    • :eq - " "
    • :del - " - "
    • :ins - " + "
    • :skip - "..."
  • :colors
    • :del - [text: :red, space: :red_background]
    • :ins - [text: :green, space: :green_background]
    • :skip - [text: :yellow]
    • :separator - [text: :yellow]

These top-level formatting options will be merged into passed options. For example, you could change only the :separator with:

format(string1, string2, format: [separator: "~ "])

See IO.ANSI for info on colors.

Examples

iex> code = """
...> defmodule Bar do
...>   @moduledoc false
...>
...>   bar(x, y) do
...>     z = x + y
...>     {x,y  , z}
...>   end
...>
...>   bar(x, y, z) do
...>     {x, y, z}
...>   end
...> end\
...> """
iex> formatted = code |> Code.format_string!() |> IO.iodata_to_binary()
iex> code
...> |> TextDiff.format(formatted, color: false)
...> |> IO.iodata_to_binary()
"""
     ...|
 4  4   |  bar(x, y) do
 5  5   |    z = x + y
 6    - |    {x,y  , z}
    6 + |    {x, y, z}
 7  7   |  end
 8  8   |
     ...|
"""
iex> code
...> |> TextDiff.format(formatted, color: false, after: 1, before: 1)
...> |> IO.iodata_to_binary()
"""
     ...|
 5  5   |    z = x + y
 6    - |    {x,y  , z}
    6 + |    {x, y, z}
 7  7   |  end
     ...|
"""
iex> code
...> |> TextDiff.format(formatted, color: false, line_numbers: false)
...> |> IO.iodata_to_binary()
"""
...|
   |  bar(x, y) do
   |    z = x + y
 - |    {x,y  , z}
 + |    {x, y, z}
   |  end
   |
...|
"""