# patience

[![CI](https://github.com/peter-evans/patience/actions/workflows/ci.yml/badge.svg)](https://github.com/peter-evans/patience/actions/workflows/ci.yml)
[![GoReportCard](https://goreportcard.com/badge/github.com/peter-evans/patience)](https://goreportcard.com/report/github.com/peter-evans/patience)
[![GoDoc](https://godoc.org/github.com/peter-evans/patience?status.svg)](https://godoc.org/github.com/peter-evans/patience)

Go implementation of the Patience Diff algorithm.

This library generates line-oriented diffs between source and destination inputs, using the Patience Diff algorithm.

## Features

Supports both plain format and [Unified format](https://en.wikipedia.org/wiki/Diff#Unified_format) (unidiff).

Plain format:
```diff
 the
 quick
 brown
-chicken
+fox
 jumps
 over
 the
+lazy
 dog
```

Unified format (unidiff):

```diff
--- a.txt
+++ b.txt
@@ -3,3 +3,3 @@
 brown
-chicken
+fox
 jumps
@@ -7,2 +7,3 @@
 the
+lazy
 dog
```

## Installation

```sh
go get github.com/peter-evans/patience
```

## Usage

```go
a := strings.Split(textA, "\n")
b := strings.Split(textB, "\n")

diffs := patience.Diff(a, b)

// Combined diff
diff := patience.DiffText(diffs)

// Split diffs
diffA := patience.DiffTextA(diffs)
diffB := patience.DiffTextB(diffs)

// Unified diff
unidiff := patience.UnifiedDiffText(diffs)

// Unified diff with options
unidiffopts := patience.UnifiedDiffTextWithOptions(
     diffs,
     UnifiedDiffOptions{
          Precontext: 2, 
          Postcontext: 2,
          SrcHeader:   "a.txt",
          DstHeader:   "b.txt",
     },
)
```

## About

Patience Diff is an algorithm credited to [Bram Cohen](https://bramcohen.livejournal.com/73318.html) that produces diffs tending to be more human-readable than the common diff algorithm.

The common diff algorithm is based on the [longest common subsequence](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem) problem.
It is credited to [Eugene Myers](http://www.xmailserver.org/diff2.pdf) and is the default diff algorithm in Git.
While the diffs generated by this algorithm are efficient, in many cases they tend not to correspond to what humans would naturally identify.

Patience Diff, while also relying on computing the longest common subsequence, takes a different approach. It only computes the longest common subsequence of the *unique*, *common* elements of both texts. This means that lines that are frequently non-unique, such as those containing a single brace or new line character, are ignored. The result is that distinctive lines, such as function declarations, become the anchor points of commonality between the two texts.

This is an example comparing Patience Diff to the common diff algorithm (Myers).

Patience Diff
```diff
 #include <stdio.h>
 
+int fib(int n)
+{
+    if(n > 2)
+    {
+        return fib(n-1) + fib(n-2);
+    }
+    return 1;
+}
+
 // Frobs foo heartily
 int frobnitz(int foo)
 {
     int i;
     for(i = 0; i < 10; i++)
     {
-        printf("Your answer is: ");
         printf("%d\n", foo);
     }
 }
 
-int fact(int n)
-{
-    if(n > 1)
-    {
-        return fact(n-1) * n;
-    }
-    return 1;
-}
- 
 int main(int argc, char **argv)
 {
-    frobnitz(fact(10));
+    frobnitz(fib(10));
 }
```

Common diff (Myers)
```diff
 #include <stdio.h>
 
-// Frobs foo heartily
-int frobnitz(int foo)
+int fib(int n)
 {
-    int i;
-    for(i = 0; i < 10; i++)
+    if(n > 2)
     {
-        printf("Your answer is: ");
-        printf("%d\n", foo);
+        return fib(n-1) + fib(n-2);
     }
+    return 1;
 }
 
-int fact(int n)
+// Frobs foo heartily
+int frobnitz(int foo)
 {
-    if(n > 1)
+    int i;
+    for(i = 0; i < 10; i++)
     {
-        return fact(n-1) * n;
+        printf("%d\n", foo);
     }
-    return 1;
 }
 
 int main(int argc, char **argv)
 {
-    frobnitz(fact(10));
+    frobnitz(fib(10));
 }
```

## References

- [Patience Diff Advantages](https://bramcohen.livejournal.com/73318.html) by Bram Cohen
- [Patience Diff, a brief summary](https://alfedenzo.livejournal.com/170301.html) by Alfedenzo
