myers

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 24, 2025 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package myers implements the Myers' diff algorithm.

The Myers algorithm is an efficient method for computing the shortest edit script between two sequences (typically lines of text). This implementation provides both string-based and string slice-based diff functions with configuration options.

For large inputs, a linear space variant of Myers algorithm is used to reduce memory consumption. A fallback to a simpler LCS-based algorithm is also employed for large inputs (default > 10000 lines) or when recursion depth limits (default 30) are reached.

Basic Usage

To compare two strings using the default settings:

differ := myers.NewDiffer()
diff, err := differ.Diff("hello\nworld", "hello\nthere\nworld")

To compare slices of strings directly:

differ := myers.NewDiffer()
diff, err := differ.DiffStrings([]string{"hello", "world"}, []string{"hello", "there", "world"})

You can also use the Diff or DiffStrings functions directly:

diff, err := myers.Diff("hello\nworld", "hello\nthere\nworld")
diff, err := myers.DiffStrings([]string{"hello", "world"}, []string{"hello", "there", "world"})

Output Format

The output is a formatted string showing the differences between inputs with line numbers and change indicators:

  • Lines prefixed with spaces are unchanged (present in both inputs)
  • Lines prefixed with "+" were added (present only in the second input)
  • Lines prefixed with "-" were deleted (present only in the first input)

By default, line numbers from both inputs are shown in the output. The output format defaults to a context diff, which includes surrounding lines to provide context for the changes. The specific formatting is handled by a `Formatter` interface.

Configuration

Options can be used to customize the diff output and algorithm behavior. Key among these is the ability to select a `Formatter` to control the output style:

  • `WithContextFormatter`: Selects the context diff format (default).
  • `WithUnifiedFormatter`: Selects the unified diff format.
  • `WithFormatter`: Allows specifying a custom `Formatter` implementation.

Other options include:

Create a custom differ with 5 context lines surrounding changes:

differ := myers.NewCustomDiffer(myers.WithContextLines(5))

Create a custom differ that hides line numbers:

differ := myers.NewCustomDiffer(myers.WithShowLineNumbers(false))

Create a custom differ that produces a unified diff output:

differ := myers.NewCustomDiffer(myers.WithUnifiedFormatter())

Create a custom differ with a maximum edit distance (for performance on large inputs):

differ := myers.NewCustomDiffer(myers.WithMaxEditDistance(100))

Create a custom differ that uses the linear space algorithm variant:

differ := myers.NewCustomDiffer(myers.WithLinearSpace(true))

Combine options:

differ := myers.NewCustomDiffer(
     myers.WithContextLines(3),
     myers.WithShowLineNumbers(false))

Create a custom formatter:

customFormatter := &MyCustomFormatter{}  // Replace with your custom implementation
differ := myers.NewCustomDiffer(myers.WithFormatter(customFormatter))

You can also use the Diff or DiffStrings functions directly with options:

// With strings:
diff, err := myers.Diff("hello\nworld", "hello\nthere\nworld",
	myers.WithContextLines(3), myers.WithShowLineNumbers(false))
if err != nil {
	fmt.Println(err)
} else {
	fmt.Println(diff)
}

// With string slices:
diff, err = myers.DiffStrings([]string{"hello", "world"}, []string{"hello", "there", "world"},
	myers.WithContextLines(3), myers.WithShowLineNumbers(false))
if err != nil {
	fmt.Println(err)
} else {
	fmt.Println(diff)
}

Algorithm Details

This implementation uses the following strategies:

  • Myers' greedy algorithm for finding the shortest edit script.
  • A linear space variant of Myers' algorithm (Hirschberg's algorithm principle) to reduce memory usage for large inputs.
  • A fallback to a simpler LCS-based algorithm (implemented in the internal/diffcore package) for large edit distances, large inputs, or when linear space recursion depth limits are reached.
  • Context-aware output formatting.

The time complexity is typically O(ND) where N is the sum of input lengths and D is the size of the minimum edit script, but the fallback to the LCS-based algorithm results in O(N*M) time complexity in certain cases.

Space complexity varies depending on the chosen algorithm variant:

  • O(N) for the linear space algorithm.
  • O(V) for the standard Myers algorithm (V is the length of the `v` vector).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Diff

func Diff(a, b string, opts ...Option) (string, error)

Diff computes differences between two values using the Myers diff algorithm. Returns an error if option validation fails.

func DiffStrings

func DiffStrings(a, b []string, opts ...Option) (string, error)

DiffStrings computes differences between string slices using the Myers diff algorithm. Returns an error if option validation fails.

func NewCustomDiffer

func NewCustomDiffer(opts ...Option) diff.Differ

NewCustomDiffer creates a new CustomMyersDiffer instance

func NewDiffer

func NewDiffer() diff.Differ

NewMyersDiffer creates a new MyersDiffer instance

Types

type Option

type Option func(*options)

func WithContextFormatter

func WithContextFormatter() Option

WithContextFormatter uses the context formatter for diff output

func WithContextLines

func WithContextLines(n int) Option

WithContextLines sets the number of context lines

func WithFormatter

func WithFormatter(f diff.Formatter) Option

Option to set the formatter directly

func WithLargeInputThreshold

func WithLargeInputThreshold(size int) Option

WithLargeInputThreshold sets the maximum size of input for which the simple diff algorithm is used.

func WithLinearRecursionMaxDepth

func WithLinearRecursionMaxDepth(depth int) Option

WithLinearRecursionMaxDepth sets the maximum depth of recursion for the linear space algorithm

func WithLinearSpace

func WithLinearSpace(linear bool) Option

WithLinearSpace sets whether to use linear space algorithm

func WithMaxEditDistance

func WithMaxEditDistance(n int) Option

WithMaxEditDistance sets the maximum edit distance

func WithOutputFormat

func WithOutputFormat(format diff.OutputFormat) Option

WithOutputFormat sets the output format

func WithShowLineNumbers

func WithShowLineNumbers(show bool) Option

WithShowLineNumbers sets whether to show line numbers

func WithSmallInputThreshold

func WithSmallInputThreshold(size int) Option

WithSmallInputThreshold sets the size of input (in number of lines/string slice elements) below which the Myers algorithm is used.

func WithUnifiedFormatter

func WithUnifiedFormatter() Option

WithUnifiedFormatter uses the unified formatter for diff output

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL