unified_diff.pl --

Convert unified diff format patches to and from Prolog terms. unified_diff//2 can be used to parse and generate patches. This module intends to support only well-formed patches. It makes no attempt to handle arbitrary patches as they might occur in the wild.

Installation

Using SWI-Prolog 6.3 or later:

    $ swipl
    1 ?- pack_install(unified_diff).

Source code available and pull requests accepted on GitHub: https://github.com/mndrix/unified_diff

author
- Michael Hendricks <michael@ndrix.org>
license
- MIT
unified_diff(?Intro:codes, ?Files:list)// is semidet
Parse or generate a unified diff. Intro is arbitrary text that occurs before the first file header. Files is a list of terms: file(OldPath, NewPath, Hunks). OldPath is file's path before applying this patch. NewPath is the file's path after.

Hunks is a list of terms: hunk(OldLine, NewLine, Heading, Deltas). OldLine is the line number of the original file to which this hunk applies. NewLine is the line number of the new file. Heading is optional text on the same line as the hunk header (usually a function name). An empty list indicates a missing heading.

Deltas is a list of terms with three possible functors. The functor ' ' indicates a context line, - indicates a deletion and + indicates an insertion. All three functors have arity 1 and the first argument is a list of codes indicating the content.

For example, this patch in unified diff format:

Patch explanation
--- alphabet
+++ alphabet
@@ -1,3 +1,3 @@ function:
 alpha
-b
+beta
gamma

is equivalent to this term:

[ file(alphabet,
       alphabet,
       [ hunk(1,1,"function:",
              [ ' '("alpha")
              , -"b"
              , +"beta"
              , ' '("gamma")
              ])])]
unified_diff_ranges(+Deltas, -OldSize, -NewSize) is det
Calculate range sizes based on a list of deltas. Each hunk in a unified diff has a header something like this:
@@ -118,6 +118,10 @@ sub profile {

unified_diff_ranges/3 calculates the values OldSize and NewSize (6 and 10 in this example, respectively) based on Deltas.

Range sizes are automatically calculated when generating patches. They're automatically verified when parsing. Therefore, it's unlikely that consumers will need this predicate.