From 3041443d1989b6196dc5b868f4f7a3f467c431b1 Mon Sep 17 00:00:00 2001 From: Brian Cavalier Date: Fri, 11 Jul 2014 12:15:01 -0400 Subject: [PATCH] Tweak patch context docs. Clean up jiff/lib/context, add jsdoc --- README.md | 11 ++++++----- lib/context.js | 31 ++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 132a3b6..38672f3 100644 --- a/README.md +++ b/README.md @@ -108,18 +108,19 @@ As of v0.2, `jiff.diff` and `jiff.patch` support [patch contexts](http://en.wiki Using patch contexts can greatly improve patch accuracy for arrays, at the cost of increasing the size of patches. -Patch contexts are supported via a pair of closely related functions: `makeContext` and `findContext`. +Patch contexts are entirely opt-in. To use them, you must provide a pair of closely related functions: `makeContext` and `findContext`. An API for creating default `makeContext` and `findContext` functions is provided in [`jiff/lib/context`](#jifflibcontext), or you can implement your own. -If you supply the optional `makeContext` function to `jiff.diff`, it will be used to generated a context for each change to an array. +When you supply the optional `makeContext` function to `jiff.diff`, it will be used to generated a context for each change to an array. -Likewise, if you supply the optional `findContext` function to `jiff.patch` (or `jiff.patchInPlace`), it will be used to find adjusted array indices where patches should actually be applied. +Likewise, when you supply the optional `findContext` function to `jiff.patch` (or `jiff.patchInPlace`), it will be used to find adjusted array indices where patches should actually be applied. -The context is opaque, and jiff will not attempt to inspect or use it: `jiff.diff` will simply add whatever is returned by `makeContext` to patch operations, and `jiff.patch` will simply hand it to `findContext` when it sees a context in a patch operation. +The context is opaque, and jiff itself will not attempt to inspect or interpret it: `jiff.diff` will simply add whatever is returned by `makeContext` to patch operations, and `jiff.patch` will simply hand it to `findContext` when it sees a context in a patch operation. -An API for creating default `makeContext` and `findContext` functions is provided in [`jiff/lib/context`](#jifflibcontext). ## Experimental APIs +These APIs are still considered experimental, signatures may change. + ### jiff/lib/context ```js diff --git a/lib/context.js b/lib/context.js index c71b0dd..7f34419 100644 --- a/lib/context.js +++ b/lib/context.js @@ -3,21 +3,39 @@ exports.matchContext = matchContext; exports.makeContextFinder = makeContextFinder; exports.makeContext = makeContext; +/** + * Creates a findContext function that expects a context + * { before: [...], after: [...] } containing some number of items before + * and after the change. Uses the provided equals function to compare + * array itesm and find the best fit position in the array to + * apply the patch. Uses a similar algorithm to GNU patch. + * @param {function(a:*, b:*):boolean} equals return truthy if a and b are equal + * @returns {Function} a findContext function that can be passed to jiff.patch + */ function makeContextFinder(equals) { return function(index, array, context) { return findPosition(equals, index, array, context); }; } +/** + * Creates a makeContext function that will generate patch contexts + * { before: [...], after: [...] } containing `size` number of items + * before and after the change. + * @param {number} size max number of items before/after the change to include + * @returns {Function} a makeContext function that can be passed to jiff.diff + */ function makeContext(size) { return function (index, array) { return { before: array.slice(Math.max(0, index - size), index), - after: array.slice(Math.min(array.length, index), index + size) + after: array.slice(Math.min(array.length, index + 1), index + size + 1) }; }; } +// TODO: Include removed items in the patch context when patch is a remove + function findPosition (equals, start, array, context) { var index; var before = context.before; @@ -27,9 +45,9 @@ function findPosition (equals, start, array, context) { var amax = after.length; while(amax > 0 || bmax < blen) { - index = findPositionWith(equals, array, + index = findPositionWith(equals, array, start, before.slice(bmax), - after.slice(0, amax), start); + after.slice(0, amax)); if(index >= 0) { return index; @@ -42,16 +60,15 @@ function findPosition (equals, start, array, context) { return start; } -function findPositionWith(equals, array, before, after, start) { +function findPositionWith(equals, array, start, before, after, patch) { var blen = before.length; var b = start-blen; - var bspan = blen; var found = false; var i = b; while(i >= 0 && !found) { - found = matchContext(equals, array, i, i+blen, before, after); + found = matchContext(equals, array, i, i+blen+1, before, after); if(found) { return i + blen; } @@ -61,7 +78,7 @@ function findPositionWith(equals, array, before, after, start) { i = start; while(i < array.length && !found) { - found = matchContext(equals, array, i-bspan, i, before, after); + found = matchContext(equals, array, i-blen, i+1, before, after); if(found) { return i; }