diff --git a/Makefile b/Makefile index f81f8cb..a67b0ac 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ dist/difflib-browser.js: lib/difflib.js util/build.coffee lib/difflib.js: src/difflib.coffee @coffee -c -o lib src -test: +test: lib/difflib.js dist/difflib-browser.js @NODE_ENV=test \ node_modules/.bin/mocha \ --ui qunit \ diff --git a/README.md b/README.md index 78e15c2..fff5174 100644 --- a/README.md +++ b/README.md @@ -440,7 +440,7 @@ If not specified, the strings default to blanks. ``` -### difflib.*getCloseMatches*(word, possibilities\[, n\]\[, cutoff\]) +### difflib.*getCloseMatches*(word, possibilities\[, n\]\[, cutoff\]\[, formatter\]) Return a list of the best “good enough” matches. *word* is a sequence for which close matches are desired @@ -454,12 +454,26 @@ Optional argument *cutoff* (default 0.6) is a float in the range [0, 1]. Possibilities that don’t score at least that similar to word are ignored. +Optional argument *formatter* is a function that is run on each element from +*possibilities* before matching is run. + + The best (no more than n) matches among the possibilities are returned in a list, sorted by similarity score, most similar first. ```js >>> difflib.getCloseMatches('appel', ['ape', 'apple', 'peach', 'puppy']) ['apple', 'ape'] + +>>> difflib.getCloseMatches('appel', [ + { id: 'a', fruit: 'apple' }, + { id: 'b', fruit: 'pineapple' }, + { id: 'c', fruit: 'cherry' }, + { id: 'd', fruit: 'mango' } + ], null, null, function (i) { + return i.fruit; + }) +[{ id: 'a', fruit: 'apple' }] ``` diff --git a/dist/difflib-browser.js b/dist/difflib-browser.js index 98c5c3c..6fd1e8e 100644 --- a/dist/difflib-browser.js +++ b/dist/difflib-browser.js @@ -2,4 +2,5 @@ * @fileoverview Text diff library ported from Python's difflib module. * https://github.com/qiao/difflib.js */ -var difflib=function(){var a=function(b,c){var d=a.resolve(b,c||"/"),e=a.modules[d];if(!e)throw new Error("Failed to resolve module "+b+", tried "+d);var f=e._cached?e._cached:e();return f};return a.paths=[],a.modules={},a.extensions=[".js",".coffee"],a._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0},a.resolve=function(){return function(b,c){function h(b){if(a.modules[b])return b;for(var c=0;c=0;e--){if(b[e]==="node_modules")continue;var f=b.slice(0,e+1).join("/")+"/node_modules";c.push(f)}return c}c||(c="/");if(a._core[b])return b;var d=a.modules.path();c=d.resolve("/",c);var e=c||"/";if(b.match(/^(?:\.\.?\/|\/)/)){var f=h(d.resolve(e,b))||i(d.resolve(e,b));if(f)return f}var g=j(b,e);if(g)return g;throw new Error("Cannot find module '"+b+"'")}}(),a.alias=function(b,c){var d=a.modules.path(),e=null;try{e=a.resolve(b+"/package.json","/")}catch(f){e=a.resolve(b,"/")}var g=d.dirname(e),h=(Object.keys||function(a){var b=[];for(var c in a)b.push(c);return b})(a.modules);for(var i=0;i0){var c=a.shift();c()}}},!0),function(c){b?(a.push(c),window.postMessage("browserify-tick","*")):setTimeout(c,0)}}()),process.title||(process.title="browser"),process.binding||(process.binding=function(b){if(b==="evals")return a("vm");throw new Error("No such module")}),process.cwd||(process.cwd=function(){return"."}),process.env||(process.env={}),process.argv||(process.argv=[]),a.define("path",function(a,b,c,d,e){function f(a,b){var c=[];for(var d=0;d=0;d--){var e=a[d];e=="."?a.splice(d,1):e===".."?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c--;c)a.unshift("..");return a}var h=/^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;c.resolve=function(){var a="",b=!1;for(var c=arguments.length;c>=-1&&!b;c--){var d=c>=0?arguments[c]:process.cwd();if(typeof d!="string"||!d)continue;a=d+"/"+a,b=d.charAt(0)==="/"}return a=g(f(a.split("/"),function(a){return!!a}),!b).join("/"),(b?"/":"")+a||"."},c.normalize=function(a){var b=a.charAt(0)==="/",c=a.slice(-1)==="/";return a=g(f(a.split("/"),function(a){return!!a}),!b).join("/"),!a&&!b&&(a="."),a&&c&&(a+="/"),(b?"/":"")+a},c.join=function(){var a=Array.prototype.slice.call(arguments,0);return c.normalize(f(a,function(a,b){return a&&typeof a=="string"}).join("/"))},c.dirname=function(a){var b=h.exec(a)[1]||"",c=!1;return b?b.length===1||c&&b.length<=3&&b.charAt(1)===":"?b:b.substring(0,b.length-1):"."},c.basename=function(a,b){var c=h.exec(a)[2]||"";return b&&c.substr(-1*b.length)===b&&(c=c.substr(0,c.length-b.length)),c},c.extname=function(a){return h.exec(a)[3]||""}}),a.define("/node_modules/heap/package.json",function(a,b,c,d,e){b.exports={main:"./index.js"}}),a.define("/node_modules/heap/index.js",function(a,b,c,d,e){b.exports=a("./lib/heap")}),a.define("/node_modules/heap/lib/heap.js",function(a,b,c,d,e){(function(){var a,c,d,e,f,g,h,i,j,k,l,m,n,o;d=Math.floor,k=Math.min,c=function(a,b){return ab?1:0},j=function(a,b,e,f,g){var h;e==null&&(e=0),g==null&&(g=c);if(e<0)throw new Error("lo must be non-negative");f==null&&(f=a.length);while(g(e,f)<0)h=d((e+f)/2),g(b,a[h])<0?f=h:e=h+1;return[].splice.apply(a,[e,e-e].concat(b)),b},g=function(a,b,d){return d==null&&(d=c),a.push(b),n(a,0,a.length-1,d)},f=function(a,b){var d,e;return b==null&&(b=c),d=a.pop(),a.length?(e=a[0],a[0]=d,o(a,0,b)):e=d,e},i=function(a,b,d){var e;return d==null&&(d=c),e=a[0],a[0]=b,o(a,0,d),e},h=function(a,b,d){var e;return d==null&&(d=c),a.length&&d(a[0],b)<0&&(e=[a[0],b],b=e[0],a[0]=e[1],o(a,0,d)),b},e=function(a,b){var e,f,g,h,i,j,k,l;b==null&&(b=c),j=function(){l=[];for(var b=0,c=d(a.length/2);0<=c?bc;0<=c?b++:b--)l.push(b);return l}.apply(this).reverse(),k=[];for(f=0,h=j.length;fq;h=0<=q?++n:--n)r.push(f(a,d));return r},n=function(a,b,d,e){var f,g,h;e==null&&(e=c),f=a[d];while(d>b){h=d-1>>1,g=a[h];if(e(f,g)<0){a[d]=g,d=h;continue}break}return a[d]=f},o=function(a,b,d){var e,f,g,h,i;d==null&&(d=c),f=a.length,i=b,g=a[b],e=2*b+1;while(e=0;f--)if(c[f]!=d[f])return!1;for(f=c.length-1;f>=0;f--){e=c[f];if(!n(a[e],b[e]))return!1}return!0}function r(a,b){return!a||!b?!1:b instanceof RegExp?b.test(a):a instanceof b?!0:b.call({},a)===!0?!0:!1}function s(a,b,c,d){var e;typeof c=="string"&&(d=c,c=null);try{b()}catch(f){e=f}d=(c&&c.name?" ("+c.name+").":".")+(d?" "+d:"."),a&&!e&&l("Missing expected exception"+d),!a&&r(e,c)&&l("Got unwanted exception"+d);if(a&&e&&c&&!r(e,c)||!a&&e)throw e}var f=a("util"),g=a("buffer").Buffer,h=Array.prototype.slice,i=b.exports=m;i.AssertionError=function(b){this.name="AssertionError",this.message=b.message,this.actual=b.actual,this.expected=b.expected,this.operator=b.operator;var c=b.stackStartFunction||l;Error.captureStackTrace&&Error.captureStackTrace(this,c)},f.inherits(i.AssertionError,Error),i.AssertionError.prototype.toString=function(){return this.message?[this.name+":",this.message].join(" "):[this.name+":",k(JSON.stringify(this.actual,j),128),this.operator,k(JSON.stringify(this.expected,j),128)].join(" ")},i.AssertionError.__proto__=Error.prototype,i.fail=l,i.ok=m,i.equal=function(b,c,d){b!=c&&l(b,c,d,"==",i.equal)},i.notEqual=function(b,c,d){b==c&&l(b,c,d,"!=",i.notEqual)},i.deepEqual=function(b,c,d){n(b,c)||l(b,c,d,"deepEqual",i.deepEqual)},i.notDeepEqual=function(b,c,d){n(b,c)&&l(b,c,d,"notDeepEqual",i.notDeepEqual)},i.strictEqual=function(b,c,d){b!==c&&l(b,c,d,"===",i.strictEqual)},i.notStrictEqual=function(b,c,d){b===c&&l(b,c,d,"!==",i.notStrictEqual)},i.throws=function(a,b,c){s.apply(this,[!0].concat(h.call(arguments)))},i.doesNotThrow=function(a,b,c){s.apply(this,[!1].concat(h.call(arguments)))},i.ifError=function(a){if(a)throw a}}),a.define("util",function(a,b,c,d,e){function g(a){return a instanceof Array||Array.isArray(a)||a&&a!==Object.prototype&&g(a.__proto__)}function h(a){return a instanceof RegExp||typeof a=="object"&&Object.prototype.toString.call(a)==="[object RegExp]"}function i(a){if(a instanceof Date)return!0;if(typeof a!="object")return!1;var b=Date.prototype&&n(Date.prototype),c=a.__proto__&&n(a.__proto__);return JSON.stringify(c)===JSON.stringify(b)}function j(a){return a<10?"0"+a.toString(10):a.toString(10)}function l(){var a=new Date,b=[j(a.getHours()),j(a.getMinutes()),j(a.getSeconds())].join(":");return[a.getDate(),k[a.getMonth()],b].join(" ")}var f=a("events");c.print=function(){},c.puts=function(){},c.debug=function(){},c.inspect=function(a,b,d,e){function k(a,d){if(a&&typeof a.inspect=="function"&&a!==c&&(!a.constructor||a.constructor.prototype!==a))return a.inspect(d);switch(typeof a){case"undefined":return j("undefined","undefined");case"string":var e="'"+JSON.stringify(a).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return j(e,"string");case"number":return j(""+a,"number");case"boolean":return j(""+a,"boolean")}if(a===null)return j("null","null");var l=m(a),o=b?n(a):l;if(typeof a=="function"&&o.length===0){if(h(a))return j(""+a,"regexp");var p=a.name?": "+a.name:"";return j("[Function"+p+"]","special")}if(i(a)&&o.length===0)return j(a.toUTCString(),"date");var q,r,s;g(a)?(r="Array",s=["[","]"]):(r="Object",s=["{","}"]);if(typeof a=="function"){var t=a.name?": "+a.name:"";q=h(a)?" "+a:" [Function"+t+"]"}else q="";i(a)&&(q=" "+a.toUTCString());if(o.length===0)return s[0]+q+s[1];if(d<0)return h(a)?j(""+a,"regexp"):j("[Object]","special");f.push(a);var u=o.map(function(b){var c,e;a.__lookupGetter__&&(a.__lookupGetter__(b)?a.__lookupSetter__(b)?e=j("[Getter/Setter]","special"):e=j("[Getter]","special"):a.__lookupSetter__(b)&&(e=j("[Setter]","special"))),l.indexOf(b)<0&&(c="["+b+"]"),e||(f.indexOf(a[b])<0?(d===null?e=k(a[b]):e=k(a[b],d-1),e.indexOf("\n")>-1&&(g(a)?e=e.split("\n").map(function(a){return" "+a}).join("\n").substr(2):e="\n"+e.split("\n").map(function(a){return" "+a}).join("\n"))):e=j("[Circular]","special"));if(typeof c=="undefined"){if(r==="Array"&&b.match(/^\d+$/))return e;c=JSON.stringify(""+b),c.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(c=c.substr(1,c.length-2),c=j(c,"name")):(c=c.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),c=j(c,"string"))}return c+": "+e});f.pop();var v=0,w=u.reduce(function(a,b){return v++,b.indexOf("\n")>=0&&v++,a+b.length+1},0);return w>50?u=s[0]+(q===""?"":q+"\n ")+" "+u.join(",\n ")+" "+s[1]:u=s[0]+q+" "+u.join(", ")+" "+s[1],u}var f=[],j=function(a,b){var c={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},d={special:"cyan",number:"blue","boolean":"yellow","undefined":"grey","null":"bold",string:"green",date:"magenta",regexp:"red"}[b];return d?"["+c[d][0]+"m"+a+"["+c[d][1]+"m":a};return e||(j=function(a,b){return a}),k(a,typeof d=="undefined"?2:d)};var k=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];c.log=function(a){},c.pump=null;var m=Object.keys||function(a){var b=[];for(var c in a)b.push(c);return b},n=Object.getOwnPropertyNames||function(a){var b=[];for(var c in a)Object.hasOwnProperty.call(a,c)&&b.push(c);return b},o=Object.create||function(a,b){var c;if(a===null)c={__proto__:null};else{if(typeof a!="object")throw new TypeError("typeof prototype["+typeof a+"] != 'object'");var d=function(){};d.prototype=a,c=new d,c.__proto__=a}return typeof b!="undefined"&&Object.defineProperties&&Object.defineProperties(c,b),c};c.inherits=function(a,b){a.super_=b,a.prototype=o(b.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}})}}),a.define("events",function(a,b,c,d,e){process.EventEmitter||(process.EventEmitter=function(){});var f=c.EventEmitter=process.EventEmitter,g=typeof Array.isArray=="function"?Array.isArray:function(a){return Object.prototype.toString.call(a)==="[object Array]"},h=10;f.prototype.setMaxListeners=function(a){this._events||(this._events={}),this._events.maxListeners=a},f.prototype.emit=function(a){if(a==="error")if(!this._events||!this._events.error||g(this._events.error)&&!this._events.error.length)throw arguments[1]instanceof Error?arguments[1]:new Error("Uncaught, unspecified 'error' event.");if(!this._events)return!1;var b=this._events[a];if(!b)return!1;if(typeof b=="function"){switch(arguments.length){case 1:b.call(this);break;case 2:b.call(this,arguments[1]);break;case 3:b.call(this,arguments[1],arguments[2]);break;default:var c=Array.prototype.slice.call(arguments,1);b.apply(this,c)}return!0}if(g(b)){var c=Array.prototype.slice.call(arguments,1),d=b.slice();for(var e=0,f=d.length;e0&&this._events[a].length>c&&(this._events[a].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[a].length),console.trace())}this._events[a].push(b)}else this._events[a]=[this._events[a],b];return this},f.prototype.on=f.prototype.addListener,f.prototype.once=function(a,b){var c=this;return c.on(a,function d(){c.removeListener(a,d),b.apply(this,arguments)}),this},f.prototype.removeListener=function(a,b){if("function"!=typeof b)throw new Error("removeListener only takes instances of Function");if(!this._events||!this._events[a])return this;var c=this._events[a];if(g(c)){var d=c.indexOf(b);if(d<0)return this;c.splice(d,1),c.length==0&&delete this._events[a]}else this._events[a]===b&&delete this._events[a];return this},f.prototype.removeAllListeners=function(a){return a&&this._events&&this._events[a]&&(this._events[a]=null),this},f.prototype.listeners=function(a){return this._events||(this._events={}),this._events[a]||(this._events[a]=[]),g(this._events[a])||(this._events[a]=[this._events[a]]),this._events[a]}}),a.define("buffer",function(a,b,c,d,e){function f(a){this.length=a}function h(a){return a<16?"0"+a.toString(16):a.toString(16)}function i(a){return a=~~Math.ceil(+a),a<0?0:a}function j(a,b,c){if(!(this instanceof j))return new j(a,b,c);var d;if(typeof c=="number")this.length=i(b),this.parent=a,this.offset=c;else{switch(d=typeof a){case"number":this.length=i(a);break;case"string":this.length=j.byteLength(a,b);break;case"object":this.length=i(a.length);break;default:throw new Error("First argument needs to be a number, array or string.")}this.length>j.poolSize?(this.parent=new f(this.length),this.offset=0):((!l||l.length-l.used>>0):(e=a[b+2]<<16,e|=a[b+1]<<8,e|=a[b],e+=a[b+3]<<24>>>0),e}function p(a,b,c,d){var e,f;return d||(g.ok(typeof c=="boolean","missing or invalid endian"),g.ok(b!==undefined&&b!==null,"missing offset"),g.ok(b+1=0,"specified a negative value for writing an unsigned value"),g.ok(a<=b,"value is larger than maximum value for type"),g.ok(Math.floor(a)===a,"value has a fractional component")}function u(a,b,c,d,e){e||(g.ok(b!==undefined&&b!==null,"missing value"),g.ok(typeof d=="boolean","missing or invalid endian"),g.ok(c!==undefined&&c!==null,"missing offset"),g.ok(c+1>>8,a[c+1]=b&255):(a[c+1]=(b&65280)>>>8,a[c]=b&255)}function v(a,b,c,d,e){e||(g.ok(b!==undefined&&b!==null,"missing value"),g.ok(typeof d=="boolean","missing or invalid endian"),g.ok(c!==undefined&&c!==null,"missing offset"),g.ok(c+3>>24&255,a[c+1]=b>>>16&255,a[c+2]=b>>>8&255,a[c+3]=b&255):(a[c+3]=b>>>24&255,a[c+2]=b>>>16&255,a[c+1]=b>>>8&255,a[c]=b&255)}function w(a,b,c){g.ok(typeof a=="number","cannot write a non-number as a number"),g.ok(a<=b,"value larger than maximum allowed value"),g.ok(a>=c,"value smaller than minimum allowed value"),g.ok(Math.floor(a)===a,"value has a fractional component")}function x(a,b,c){g.ok(typeof a=="number","cannot write a non-number as a number"),g.ok(a<=b,"value larger than maximum allowed value"),g.ok(a>=c,"value smaller than minimum allowed value")}function y(a,b,c,d,e){e||(g.ok(b!==undefined&&b!==null,"missing value"),g.ok(typeof d=="boolean","missing or invalid endian"),g.ok(c!==undefined&&c!==null,"missing offset"),g.ok(c+1=0?u(a,b,c,d,e):u(a,65535+b+1,c,d,e)}function z(a,b,c,d,e){e||(g.ok(b!==undefined&&b!==null,"missing value"),g.ok(typeof d=="boolean","missing or invalid endian"),g.ok(c!==undefined&&c!==null,"missing offset"),g.ok(c+3=0?v(a,b,c,d,e):v(a,4294967295+b+1,c,d,e)}function A(b,c,d,e,f){f||(g.ok(c!==undefined&&c!==null,"missing value"),g.ok(typeof e=="boolean","missing or invalid endian"),g.ok(d!==undefined&&d!==null,"missing offset"),g.ok(d+3"},f.prototype.hexSlice=function(a,b){var c=this.length;if(!a||a<0)a=0;if(!b||b<0||b>c)b=c;var d="";for(var e=a;ed&&(c=d)):c=d;var e=a.length;if(e%2)throw new Error("Invalid hex string");c>e/2&&(c=e/2);for(var g=0;gf&&(c=f)):c=f,d=String(d||"utf8").toLowerCase();switch(d){case"hex":return this.hexWrite(a,b,c);case"utf8":case"utf-8":return this.utf8Write(a,b,c);case"ascii":return this.asciiWrite(a,b,c);case"binary":return this.binaryWrite(a,b,c);case"base64":return this.base64Write(a,b,c);case"ucs2":case"ucs-2":return this.ucs2Write(a,b,c);default:throw new Error("Unknown encoding")}},f.prototype.slice=function(a,b){b===undefined&&(b=this.length);if(b>this.length)throw new Error("oob");if(a>b)throw new Error("oob");return new j(this,b-a,+a)},c.SlowBuffer=f,c.Buffer=j,j.poolSize=8192;var l;j.isBuffer=function(b){return b instanceof j||b instanceof f},j.prototype.inspect=function(){var b=[],d=this.length;for(var e=0;e"},j.prototype.get=function(b){if(b<0||b>=this.length)throw new Error("oob");return this.parent[this.offset+b]},j.prototype.set=function(b,c){if(b<0||b>=this.length)throw new Error("oob");return this.parent[this.offset+b]=c},j.prototype.write=function(a,b,c,d){if(isFinite(b))isFinite(c)||(d=c,c=undefined);else{var e=d;d=b,b=c,c=e}b=+b||0;var g=this.length-b;c?(c=+c,c>g&&(c=g)):c=g,d=String(d||"utf8").toLowerCase();var h;switch(d){case"hex":h=this.parent.hexWrite(a,this.offset+b,c);break;case"utf8":case"utf-8":h=this.parent.utf8Write(a,this.offset+b,c);break;case"ascii":h=this.parent.asciiWrite(a,this.offset+b,c);break;case"binary":h=this.parent.binaryWrite(a,this.offset+b,c);break;case"base64":h=this.parent.base64Write(a,this.offset+b,c);break;case"ucs2":case"ucs-2":h=this.parent.ucs2Write(a,this.offset+b,c);break;default:throw new Error("Unknown encoding")}return j._charsWritten=f._charsWritten,h},j.prototype.toString=function(a,b,c){a=String(a||"utf8").toLowerCase(),typeof b=="undefined"||b<0?b=0:b>this.length&&(b=this.length),typeof c=="undefined"||c>this.length?c=this.length:c<0&&(c=0),b+=this.offset,c+=this.offset;switch(a){case"hex":return this.parent.hexSlice(b,c);case"utf8":case"utf-8":return this.parent.utf8Slice(b,c);case"ascii":return this.parent.asciiSlice(b,c);case"binary":return this.parent.binarySlice(b,c);case"base64":return this.parent.base64Slice(b,c);case"ucs2":case"ucs-2":return this.parent.ucs2Slice(b,c);default:throw new Error("Unknown encoding")}},j.byteLength=f.byteLength,j.prototype.fill=function(b,c,d){b||(b=0),c||(c=0),d||(d=this.length),typeof b=="string"&&(b=b.charCodeAt(0));if(typeof b!="number"||isNaN(b))throw new Error("value is not a number");if(d=this.length)throw new Error("start out of bounds");if(d<0||d>this.length)throw new Error("end out of bounds");return this.parent.fill(b,c+this.offset,d+this.offset)},j.prototype.copy=function(a,b,c,d){var e=this;c||(c=0),d||(d=this.length),b||(b=0);if(d=a.length)throw new Error("targetStart out of bounds");if(c<0||c>=e.length)throw new Error("sourceStart out of bounds");if(d<0||d>e.length)throw new Error("sourceEnd out of bounds");return d>this.length&&(d=this.length),a.length-bthis.length)throw new Error("oob");if(a>b)throw new Error("oob");return new j(this.parent,b-a,+a+this.offset)},j.prototype.utf8Slice=function(a,b){return this.toString("utf8",a,b)},j.prototype.binarySlice=function(a,b){return this.toString("binary",a,b)},j.prototype.asciiSlice=function(a,b){return this.toString("ascii",a,b)},j.prototype.utf8Write=function(a,b){return this.write(a,b,"utf8")},j.prototype.binaryWrite=function(a,b){return this.write(a,b,"binary")},j.prototype.asciiWrite=function(a,b){return this.write(a,b,"ascii")},j.prototype.readUInt8=function(a,b){var c=this;return b||(g.ok(a!==undefined&&a!==null,"missing offset"),g.ok(a=0?d.writeUInt8(a,b,c):d.writeUInt8(255+a+1,b,c)},j.prototype.writeInt16LE=function(a,b,c){y(this,a,b,!1,c)},j.prototype.writeInt16BE=function(a,b,c){y(this,a,b,!0,c)},j.prototype.writeInt32LE=function(a,b,c){z(this,a,b,!1,c)},j.prototype.writeInt32BE=function(a,b,c){z(this,a,b,!0,c)},j.prototype.writeFloatLE=function(a,b,c){A(this,a,b,!1,c)},j.prototype.writeFloatBE=function(a,b,c){A(this,a,b,!0,c)},j.prototype.writeDoubleLE=function(a,b,c){B(this,a,b,!1,c)},j.prototype.writeDoubleBE=function(a,b,c){B(this,a,b,!0,c)},f.prototype.readUInt8=j.prototype.readUInt8,f.prototype.readUInt16LE=j.prototype.readUInt16LE,f.prototype.readUInt16BE=j.prototype.readUInt16BE,f.prototype.readUInt32LE=j.prototype.readUInt32LE,f.prototype.readUInt32BE=j.prototype.readUInt32BE,f.prototype.readInt8=j.prototype.readInt8,f.prototype.readInt16LE=j.prototype.readInt16LE,f.prototype.readInt16BE=j.prototype.readInt16BE,f.prototype.readInt32LE=j.prototype.readInt32LE,f.prototype.readInt32BE=j.prototype.readInt32BE,f.prototype.readFloatLE=j.prototype.readFloatLE,f.prototype.readFloatBE=j.prototype.readFloatBE,f.prototype.readDoubleLE=j.prototype.readDoubleLE,f.prototype.readDoubleBE=j.prototype.readDoubleBE,f.prototype.writeUInt8=j.prototype.writeUInt8,f.prototype.writeUInt16LE=j.prototype.writeUInt16LE,f.prototype.writeUInt16BE=j.prototype.writeUInt16BE,f.prototype.writeUInt32LE=j.prototype.writeUInt32LE,f.prototype.writeUInt32BE=j.prototype.writeUInt32BE,f.prototype.writeInt8=j.prototype.writeInt8,f.prototype.writeInt16LE=j.prototype.writeInt16LE,f.prototype.writeInt16BE=j.prototype.writeInt16BE,f.prototype.writeInt32LE=j.prototype.writeInt32LE,f.prototype.writeInt32BE=j.prototype.writeInt32BE,f.prototype.writeFloatLE=j.prototype.writeFloatLE,f.prototype.writeFloatBE=j.prototype.writeFloatBE,f.prototype.writeDoubleLE=j.prototype.writeDoubleLE,f.prototype.writeDoubleBE=j.prototype.writeDoubleBE}),a.define("buffer_ieee754",function(a,b,c,d,e){c.readIEEE754=function(a,b,c,d,e){var f,g,h=e*8-d-1,i=(1<>1,k=-7,l=c?0:e-1,m=c?1:-1,n=a[b+l];l+=m,f=n&(1<<-k)-1,n>>=-k,k+=h;for(;k>0;f=f*256+a[b+l],l+=m,k-=8);g=f&(1<<-k)-1,f>>=-k,k+=d;for(;k>0;g=g*256+a[b+l],l+=m,k-=8);if(f===0)f=1-j;else{if(f===i)return g?NaN:(n?-1:1)*Infinity;g+=Math.pow(2,d),f-=j}return(n?-1:1)*g*Math.pow(2,f-d)},c.writeIEEE754=function(a,b,c,d,e,f){var g,h,i,j=f*8-e-1,k=(1<>1,m=e===23?Math.pow(2,-24)-Math.pow(2,-77):0,n=d?f-1:0,o=d?-1:1,p=b<0||b===0&&1/b<0?1:0;b=Math.abs(b),isNaN(b)||b===Infinity?(h=isNaN(b)?1:0,g=k):(g=Math.floor(Math.log(b)/Math.LN2),b*(i=Math.pow(2,-g))<1&&(g--,i*=2),g+l>=1?b+=m/i:b+=m*Math.pow(2,1-l),b*i>=2&&(g++,i/=2),g+l>=k?(h=0,g=k):g+l>=1?(h=(b*i-1)*Math.pow(2,e),g+=l):(h=b*Math.pow(2,l-1)*Math.pow(2,e),g=0));for(;e>=8;a[c+n]=h&255,n+=o,h/=256,e-=8);g=g<0;a[c+n]=g&255,n+=o,g/=256,j-=8);a[c+n-o]|=p*128}}),a.define("/difflib.js",function(a,b,c,d,e){(function(){var b,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x=[].indexOf||function(a){for(var b=0,c=this.length;bh;c=0<=h?++f:--f){if(a[c]b[c])return 1}return d-e},w=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)},q=function(a){var b,c,d;for(c=0,d=a.length;c=200){k=j(i/100)+1;for(c in b)e=b[c],e.length>k&&(l[c]=!0,delete b[c])}return this.isbjunk=function(a){return w(h,a)},this.isbpopular=function(a){return w(l,a)}},a.prototype.findLongestMatch=function(a,b,c,d){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,x,y,z;t=[this.a,this.b,this.b2j,this.isbjunk],e=t[0],f=t[1],g=t[2],l=t[3],u=[a,c,0],h=u[0],i=u[1],j=u[2],n={};for(k=q=a;a<=b?qb;k=a<=b?++q:--q){p={},v=w(g,e[k])?g[e[k]]:[];for(r=0,s=v.length;r=d)break;o=p[m]=(n[m-1]||0)+1,o>j&&(x=[k-o+1,m-o+1,o],h=x[0],i=x[1],j=x[2])}n=p}while(h>a&&i>c&&!l(f[i-1])&&e[h-1]===f[i-1])y=[h-1,i-1,j+1],h=y[0],i=y[1],j=y[2];while(h+ja&&i>c&&l(f[i-1])&&e[h-1]===f[i-1])z=[h-1,i-1,j+1],h=z[0],i=z[1],j=z[2];while(h+ji&&(c.push([j,e,m(f,e+a),g,m(h,g+a)]),d.push(c),c=[],r=[l(e,f-a),l(g,h-a)],e=r[0],g=r[1]),c.push([j,e,f,g,h]);return c.length&&(c.length!==1||c[0][0]!=="equal")&&d.push(c),d},a.prototype.ratio=function(){var a,b,c,d,e;b=0,e=this.getMatchingBlocks();for(c=0,d=e.length;c0&&d++;return s(d,this.a.length+this.b.length)},a.prototype.realQuickRatio=function(){var a,b,c;return c=[this.a.length,this.b.length],a=c[0],b=c[1],s(m(a,b),a+b)},a}(),k=function(a,b,c,e){var f,h,i,j,k,l,m,n,o,p;c==null&&(c=3),e==null&&(e=.6);if(c>0){if(0<=e&&e<=1){f=[],h=new g,h.setSeq2(a);for(k=0,m=b.length;k=e&&h.quickRatio()>=e&&h.ratio()>=e&&f.push([h.ratio(),j]);f=d.nlargest(f,c,r),p=[];for(l=0,n=f.length;l 0: ("+c+")")},t=function(a,b){var c,d,e;e=[0,a.length],c=e[0],d=e[1];while(cd;e=c<=d?++f:--f)g.push(""+a+" "+b[e]);return g},a.prototype._plainReplace=function(a,b,c,d,e,f){var g,i,j,k,l,m,n,o,p,q;h(bf;z=e<=f?++F:--F){q=d[z],u.setSeq2(q);for(y=G=b;b<=c?Gc;y=b<=c?++G:--G){i=a[y];if(i===q){w===null&&(W=[y,z],w=W[0],x=W[1]);continue}u.setSeq1(i),u.realQuickRatio()>n&&u.quickRatio()>n&&u.ratio()>n&&(X=[u.ratio(),y,z],n=X[0],o=X[1],p=X[2])}}if(n=0},v=function(a,b){var c,d;return c=a+1,d=b-a,d===1?""+c:(d||c--,""+c+","+d)},p=function(a,b,c){var d,e,f,h,i,j,k,l,m,n,o,p,q,r,s,t,u,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q;K=c!=null?c:{},i=K.fromfile,y=K.tofile,j=K.fromfiledate,z=K.tofiledate,t=K.n,s=K.lineterm,i==null&&(i=""),y==null&&(y=""),j==null&&(j=""),z==null&&(z=""),t==null&&(t=3),s==null&&(s="\n"),r=[],u=!1,L=(new g(null,a,b)).getGroupedOpcodes();for(A=0,E=L.length;A=0)&&d.push(c.slice(2));return d},c._arrayCmp=r,c.SequenceMatcher=g,c.getCloseMatches=k,c._countLeading=t,c.Differ=b,c.IS_LINE_JUNK=f,c.IS_CHARACTER_JUNK=e,c._formatRangeUnified=v,c.unifiedDiff=p,c._formatRangeContext=u,c.contextDiff=i,c.ndiff=n,c.restore=o}).call(this)}),a("/difflib.js"),a("/difflib")}() \ No newline at end of file +var difflib=function(){var t=function(e,n){var r=t.resolve(e,n||"/"),o=t.modules[r];if(!o)throw new Error("Failed to resolve module "+e+", tried "+r);var i=o._cached?o._cached:o();return i};return t.paths=[],t.modules={},t.extensions=[".js",".coffee"],t._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0},t.resolve=function(){return function(e,n){function r(e){if(t.modules[e])return e;for(var n=0;n=0;r--)if("node_modules"!==e[r]){var o=e.slice(0,r+1).join("/")+"/node_modules";n.push(o)}return n}if(n||(n="/"),t._core[e])return e;var u=t.modules.path();n=u.resolve("/",n);var a=n||"/";if(e.match(/^(?:\.\.?\/|\/)/)){var f=r(u.resolve(a,e))||o(u.resolve(a,e));if(f)return f}var l=i(e,a);if(l)return l;throw new Error("Cannot find module '"+e+"'")}}(),t.alias=function(e,n){var r=t.modules.path(),o=null;try{o=t.resolve(e+"/package.json","/")}catch(n){o=t.resolve(e,"/")}for(var i=r.dirname(o),s=(Object.keys||function(t){var e=[];for(var n in t)e.push(n);return e})(t.modules),u=0;u0)){var n=t.shift();n()}},!0),function(n){e?(t.push(n),window.postMessage("browserify-tick","*")):setTimeout(n,0)}}()),process.title||(process.title="browser"),process.binding||(process.binding=function(e){if("evals"===e)return t("vm");throw new Error("No such module")}),process.cwd||(process.cwd=function(){return"."}),process.env||(process.env={}),process.argv||(process.argv=[]),t.define("path",function(t,e,n,r,o){function i(t,e){for(var n=[],r=0;r=0;r--){var o=t[r];"."==o?t.splice(r,1):".."===o?(t.splice(r,1),n++):n&&(t.splice(r,1),n--)}if(e)for(;n--;n)t.unshift("..");return t}var u=/^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;n.resolve=function(){for(var t="",e=!1,n=arguments.length;n>=-1&&!e;n--){var r=n>=0?arguments[n]:process.cwd();"string"==typeof r&&r&&(t=r+"/"+t,e="/"===r.charAt(0))}return t=s(i(t.split("/"),function(t){return!!t}),!e).join("/"),(e?"/":"")+t||"."},n.normalize=function(t){var e="/"===t.charAt(0),n="/"===t.slice(-1);return t=s(i(t.split("/"),function(t){return!!t}),!e).join("/"),t||e||(t="."),t&&n&&(t+="/"),(e?"/":"")+t},n.join=function(){var t=Array.prototype.slice.call(arguments,0);return n.normalize(i(t,function(t,e){return t&&"string"==typeof t}).join("/"))},n.dirname=function(t){var e=u.exec(t)[1]||"",n=!1;return e?1===e.length||n&&e.length<=3&&":"===e.charAt(1)?e:e.substring(0,e.length-1):"."},n.basename=function(t,e){var n=u.exec(t)[2]||"";return e&&n.substr(-1*e.length)===e&&(n=n.substr(0,n.length-e.length)),n},n.extname=function(t){return u.exec(t)[3]||""}}),t.define("/node_modules/heap/package.json",function(t,e,n,r,o){e.exports={main:"./index.js"}}),t.define("/node_modules/heap/index.js",function(t,e,n,r,o){e.exports=t("./lib/heap")}),t.define("/node_modules/heap/lib/heap.js",function(t,e,n,r,o){(function(){var t,r,o,i,s,u,a,f,l,p,h,c,d,g,y;o=Math.floor,p=Math.min,r=function(t,e){return te?1:0},l=function(t,e,n,i,s){var u;if(null==n&&(n=0),null==s&&(s=r),n<0)throw new Error("lo must be non-negative");for(null==i&&(i=t.length);nn;0<=n?e++:e--)f.push(e);return f}.apply(this).reverse(),a=[],i=0,s=u.length;iy;u=0<=y?++c:--c)v.push(s(t,n));return v},g=function(t,e,n,o){var i,s,u;for(null==o&&(o=r),i=t[n];n>e&&(u=n-1>>1,s=t[u],o(i,s)<0);)t[n]=s,n=u;return t[n]=i},y=function(t,e,n){var o,i,s,u,a;for(null==n&&(n=r),i=t.length,a=e,s=t[e],o=2*e+1;o=0;r--)if(o[r]!=i[r])return!1;for(r=o.length-1;r>=0;r--)if(n=o[r],!f(t[n],e[n]))return!1;return!0}function c(t,e){return!(!t||!e)&&(e instanceof RegExp?e.test(t):t instanceof e||e.call({},t)===!0)}function d(t,e,n,r){var o;"string"==typeof n&&(r=n,n=null);try{e()}catch(t){o=t}if(r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),t&&!o&&u("Missing expected exception"+r),!t&&c(o,n)&&u("Got unwanted exception"+r),t&&o&&n&&!c(o,n)||!t&&o)throw o}var g=t("util"),y=t("buffer").Buffer,v=Array.prototype.slice,b=e.exports=a;b.AssertionError=function(t){this.name="AssertionError",this.message=t.message,this.actual=t.actual,this.expected=t.expected,this.operator=t.operator;var e=t.stackStartFunction||u;Error.captureStackTrace&&Error.captureStackTrace(this,e)},g.inherits(b.AssertionError,Error),b.AssertionError.prototype.toString=function(){return this.message?[this.name+":",this.message].join(" "):[this.name+":",s(JSON.stringify(this.actual,i),128),this.operator,s(JSON.stringify(this.expected,i),128)].join(" ")},b.AssertionError.__proto__=Error.prototype,b.fail=u,b.ok=a,b.equal=function(t,e,n){t!=e&&u(t,e,n,"==",b.equal)},b.notEqual=function(t,e,n){t==e&&u(t,e,n,"!=",b.notEqual)},b.deepEqual=function(t,e,n){f(t,e)||u(t,e,n,"deepEqual",b.deepEqual)},b.notDeepEqual=function(t,e,n){f(t,e)&&u(t,e,n,"notDeepEqual",b.notDeepEqual)},b.strictEqual=function(t,e,n){t!==e&&u(t,e,n,"===",b.strictEqual)},b.notStrictEqual=function(t,e,n){t===e&&u(t,e,n,"!==",b.notStrictEqual)},b.throws=function(t,e,n){d.apply(this,[!0].concat(v.call(arguments)))},b.doesNotThrow=function(t,e,n){d.apply(this,[!1].concat(v.call(arguments)))},b.ifError=function(t){if(t)throw t}}),t.define("util",function(t,e,n,r,o){function i(t){return t instanceof Array||Array.isArray(t)||t&&t!==Object.prototype&&i(t.__proto__)}function s(t){return t instanceof RegExp||"object"==typeof t&&"[object RegExp]"===Object.prototype.toString.call(t)}function u(t){if(t instanceof Date)return!0;if("object"!=typeof t)return!1;var e=Date.prototype&&f(Date.prototype),n=t.__proto__&&f(t.__proto__);return JSON.stringify(n)===JSON.stringify(e)}t("events");n.print=function(){},n.puts=function(){},n.debug=function(){},n.inspect=function(t,e,r,o){function l(t,r){if(t&&"function"==typeof t.inspect&&t!==n&&(!t.constructor||t.constructor.prototype!==t))return t.inspect(r);switch(typeof t){case"undefined":return h("undefined","undefined");case"string":var o="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return h(o,"string");case"number":return h(""+t,"number");case"boolean":return h(""+t,"boolean")}if(null===t)return h("null","null");var c=a(t),d=e?f(t):c;if("function"==typeof t&&0===d.length){if(s(t))return h(""+t,"regexp");var g=t.name?": "+t.name:"";return h("[Function"+g+"]","special")}if(u(t)&&0===d.length)return h(t.toUTCString(),"date");var y,v,b;if(i(t)?(v="Array",b=["[","]"]):(v="Object",b=["{","}"]),"function"==typeof t){var w=t.name?": "+t.name:"";y=s(t)?" "+t:" [Function"+w+"]"}else y="";if(u(t)&&(y=" "+t.toUTCString()),0===d.length)return b[0]+y+b[1];if(r<0)return s(t)?h(""+t,"regexp"):h("[Object]","special");p.push(t);var m=d.map(function(e){var n,o;if(t.__lookupGetter__&&(t.__lookupGetter__(e)?o=t.__lookupSetter__(e)?h("[Getter/Setter]","special"):h("[Getter]","special"):t.__lookupSetter__(e)&&(o=h("[Setter]","special"))),c.indexOf(e)<0&&(n="["+e+"]"),o||(p.indexOf(t[e])<0?(o=null===r?l(t[e]):l(t[e],r-1),o.indexOf("\n")>-1&&(o=i(t)?o.split("\n").map(function(t){return" "+t}).join("\n").substr(2):"\n"+o.split("\n").map(function(t){return" "+t}).join("\n"))):o=h("[Circular]","special")),"undefined"==typeof n){if("Array"===v&&e.match(/^\d+$/))return o;n=JSON.stringify(""+e),n.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(n=n.substr(1,n.length-2),n=h(n,"name")):(n=n.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),n=h(n,"string"))}return n+": "+o});p.pop();var E=0,k=m.reduce(function(t,e){return E++,e.indexOf("\n")>=0&&E++,t+e.length+1},0);return m=k>50?b[0]+(""===y?"":y+"\n ")+" "+m.join(",\n ")+" "+b[1]:b[0]+y+" "+m.join(", ")+" "+b[1]}var p=[],h=function(t,e){var n={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},r={special:"cyan",number:"blue",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"}[e];return r?"["+n[r][0]+"m"+t+"["+n[r][1]+"m":t};return o||(h=function(t,e){return t}),l(t,"undefined"==typeof r?2:r)};n.log=function(t){},n.pump=null;var a=Object.keys||function(t){var e=[];for(var n in t)e.push(n);return e},f=Object.getOwnPropertyNames||function(t){var e=[];for(var n in t)Object.hasOwnProperty.call(t,n)&&e.push(n);return e},l=Object.create||function(t,e){var n;if(null===t)n={__proto__:null};else{if("object"!=typeof t)throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var r=function(){};r.prototype=t,n=new r,n.__proto__=t}return"undefined"!=typeof e&&Object.defineProperties&&Object.defineProperties(n,e),n};n.inherits=function(t,e){t.super_=e,t.prototype=l(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}}),t.define("events",function(t,e,n,r,o){process.EventEmitter||(process.EventEmitter=function(){});var i=n.EventEmitter=process.EventEmitter,s="function"==typeof Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},u=10;i.prototype.setMaxListeners=function(t){this._events||(this._events={}),this._events.maxListeners=t},i.prototype.emit=function(t){if("error"===t&&(!this._events||!this._events.error||s(this._events.error)&&!this._events.error.length))throw arguments[1]instanceof Error?arguments[1]:new Error("Uncaught, unspecified 'error' event.");if(!this._events)return!1;var e=this._events[t];if(!e)return!1;if("function"==typeof e){switch(arguments.length){case 1:e.call(this);break;case 2:e.call(this,arguments[1]);break;case 3:e.call(this,arguments[1],arguments[2]);break;default:var n=Array.prototype.slice.call(arguments,1);e.apply(this,n)}return!0}if(s(e)){for(var n=Array.prototype.slice.call(arguments,1),r=e.slice(),o=0,i=r.length;o0&&this._events[t].length>n&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),console.trace())}this._events[t].push(e)}else this._events[t]=[this._events[t],e];else this._events[t]=e;return this},i.prototype.on=i.prototype.addListener,i.prototype.once=function(t,e){var n=this;return n.on(t,function r(){n.removeListener(t,r),e.apply(this,arguments)}),this},i.prototype.removeListener=function(t,e){if("function"!=typeof e)throw new Error("removeListener only takes instances of Function");if(!this._events||!this._events[t])return this;var n=this._events[t];if(s(n)){var r=n.indexOf(e);if(r<0)return this;n.splice(r,1),0==n.length&&delete this._events[t]}else this._events[t]===e&&delete this._events[t];return this},i.prototype.removeAllListeners=function(t){return t&&this._events&&this._events[t]&&(this._events[t]=null),this},i.prototype.listeners=function(t){return this._events||(this._events={}),this._events[t]||(this._events[t]=[]),s(this._events[t])||(this._events[t]=[this._events[t]]),this._events[t]}}),t.define("buffer",function(t,e,n,r,o){function i(t){this.length=t}function s(t){return t<16?"0"+t.toString(16):t.toString(16)}function u(t){return t=~~Math.ceil(+t),t<0?0:t}function a(t,e,n){if(!(this instanceof a))return new a(t,e,n);var r;if("number"==typeof n)this.length=u(e),this.parent=t,this.offset=n;else{switch(r=typeof t){case"number":this.length=u(t);break;case"string":this.length=a.byteLength(t,e);break;case"object":this.length=u(t.length);break;default:throw new Error("First argument needs to be a number, array or string.")}if(this.length>a.poolSize?(this.parent=new i(this.length),this.offset=0):((!x||x.length-x.used>>0):(o=t[e+2]<<16,o|=t[e+1]<<8,o|=t[e],o+=t[e+3]<<24>>>0),o}function c(t,e,n,r){var o,i;return r||(j.ok("boolean"==typeof n,"missing or invalid endian"),j.ok(void 0!==e&&null!==e,"missing offset"),j.ok(e+1=0,"specified a negative value for writing an unsigned value"),j.ok(t<=e,"value is larger than maximum value for type"),j.ok(Math.floor(t)===t,"value has a fractional component")}function b(t,e,n,r,o){o||(j.ok(void 0!==e&&null!==e,"missing value"),j.ok("boolean"==typeof r,"missing or invalid endian"),j.ok(void 0!==n&&null!==n,"missing offset"),j.ok(n+1>>8,t[n+1]=255&e):(t[n+1]=(65280&e)>>>8,t[n]=255&e)}function w(t,e,n,r,o){o||(j.ok(void 0!==e&&null!==e,"missing value"),j.ok("boolean"==typeof r,"missing or invalid endian"),j.ok(void 0!==n&&null!==n,"missing offset"),j.ok(n+3>>24&255,t[n+1]=e>>>16&255,t[n+2]=e>>>8&255,t[n+3]=255&e):(t[n+3]=e>>>24&255,t[n+2]=e>>>16&255,t[n+1]=e>>>8&255,t[n]=255&e)}function m(t,e,n){j.ok("number"==typeof t,"cannot write a non-number as a number"),j.ok(t<=e,"value larger than maximum allowed value"),j.ok(t>=n,"value smaller than minimum allowed value"),j.ok(Math.floor(t)===t,"value has a fractional component")}function E(t,e,n){j.ok("number"==typeof t,"cannot write a non-number as a number"),j.ok(t<=e,"value larger than maximum allowed value"),j.ok(t>=n,"value smaller than minimum allowed value")}function k(t,e,n,r,o){o||(j.ok(void 0!==e&&null!==e,"missing value"),j.ok("boolean"==typeof r,"missing or invalid endian"),j.ok(void 0!==n&&null!==n,"missing offset"),j.ok(n+1=0?b(t,e,n,r,o):b(t,65535+e+1,n,r,o)}function _(t,e,n,r,o){o||(j.ok(void 0!==e&&null!==e,"missing value"),j.ok("boolean"==typeof r,"missing or invalid endian"),j.ok(void 0!==n&&null!==n,"missing offset"),j.ok(n+3=0?w(t,e,n,r,o):w(t,4294967295+e+1,n,r,o)}function I(e,n,r,o,i){i||(j.ok(void 0!==n&&null!==n,"missing value"),j.ok("boolean"==typeof o,"missing or invalid endian"),j.ok(void 0!==r&&null!==r,"missing offset"),j.ok(r+3"},i.prototype.hexSlice=function(t,e){var n=this.length;(!t||t<0)&&(t=0),(!e||e<0||e>n)&&(e=n);for(var r="",o=t;or&&(n=r)):n=r;var o=t.length;if(o%2)throw new Error("Invalid hex string");n>o/2&&(n=o/2);for(var s=0;si&&(n=i)):n=i,r=String(r||"utf8").toLowerCase()){case"hex":return this.hexWrite(t,e,n);case"utf8":case"utf-8":return this.utf8Write(t,e,n);case"ascii":return this.asciiWrite(t,e,n);case"binary":return this.binaryWrite(t,e,n);case"base64":return this.base64Write(t,e,n);case"ucs2":case"ucs-2":return this.ucs2Write(t,e,n);default:throw new Error("Unknown encoding")}},i.prototype.slice=function(t,e){if(void 0===e&&(e=this.length),e>this.length)throw new Error("oob");if(t>e)throw new Error("oob");return new a(this,e-t,+t)},n.SlowBuffer=i,n.Buffer=a,a.poolSize=8192;var x;a.isBuffer=function(t){return t instanceof a||t instanceof i},a.prototype.inspect=function(){for(var t=[],e=this.length,r=0;r"},a.prototype.get=function(t){if(t<0||t>=this.length)throw new Error("oob");return this.parent[this.offset+t]},a.prototype.set=function(t,e){if(t<0||t>=this.length)throw new Error("oob");return this.parent[this.offset+t]=e},a.prototype.write=function(t,e,n,r){if(isFinite(e))isFinite(n)||(r=n,n=void 0);else{var o=r;r=e,e=n,n=o}e=+e||0;var s=this.length-e;n?(n=+n,n>s&&(n=s)):n=s,r=String(r||"utf8").toLowerCase();var u;switch(r){case"hex":u=this.parent.hexWrite(t,this.offset+e,n);break;case"utf8":case"utf-8":u=this.parent.utf8Write(t,this.offset+e,n);break;case"ascii":u=this.parent.asciiWrite(t,this.offset+e,n);break;case"binary":u=this.parent.binaryWrite(t,this.offset+e,n);break;case"base64":u=this.parent.base64Write(t,this.offset+e,n);break;case"ucs2":case"ucs-2":u=this.parent.ucs2Write(t,this.offset+e,n);break;default:throw new Error("Unknown encoding")}return a._charsWritten=i._charsWritten,u},a.prototype.toString=function(t,e,n){switch(t=String(t||"utf8").toLowerCase(),"undefined"==typeof e||e<0?e=0:e>this.length&&(e=this.length),"undefined"==typeof n||n>this.length?n=this.length:n<0&&(n=0),e+=this.offset,n+=this.offset,t){case"hex":return this.parent.hexSlice(e,n);case"utf8":case"utf-8":return this.parent.utf8Slice(e,n);case"ascii":return this.parent.asciiSlice(e,n);case"binary":return this.parent.binarySlice(e,n);case"base64":return this.parent.base64Slice(e,n);case"ucs2":case"ucs-2":return this.parent.ucs2Slice(e,n);default:throw new Error("Unknown encoding")}},a.byteLength=i.byteLength,a.prototype.fill=function(t,e,n){if(t||(t=0),e||(e=0),n||(n=this.length),"string"==typeof t&&(t=t.charCodeAt(0)),"number"!=typeof t||isNaN(t))throw new Error("value is not a number");if(n=this.length)throw new Error("start out of bounds");if(n<0||n>this.length)throw new Error("end out of bounds");return this.parent.fill(t,e+this.offset,n+this.offset)},a.prototype.copy=function(t,e,n,r){var o=this;if(n||(n=0),r||(r=this.length),e||(e=0),r=t.length)throw new Error("targetStart out of bounds");if(n<0||n>=o.length)throw new Error("sourceStart out of bounds");if(r<0||r>o.length)throw new Error("sourceEnd out of bounds");return r>this.length&&(r=this.length),t.length-ethis.length)throw new Error("oob");if(t>e)throw new Error("oob");return new a(this.parent,e-t,+t+this.offset)},a.prototype.utf8Slice=function(t,e){return this.toString("utf8",t,e)},a.prototype.binarySlice=function(t,e){return this.toString("binary",t,e)},a.prototype.asciiSlice=function(t,e){return this.toString("ascii",t,e)},a.prototype.utf8Write=function(t,e){return this.write(t,e,"utf8")},a.prototype.binaryWrite=function(t,e){return this.write(t,e,"binary")},a.prototype.asciiWrite=function(t,e){return this.write(t,e,"ascii")},a.prototype.readUInt8=function(t,e){var n=this;return e||(j.ok(void 0!==t&&null!==t,"missing offset"),j.ok(t=0?r.writeUInt8(t,e,n):r.writeUInt8(255+t+1,e,n)},a.prototype.writeInt16LE=function(t,e,n){k(this,t,e,!1,n)},a.prototype.writeInt16BE=function(t,e,n){k(this,t,e,!0,n)},a.prototype.writeInt32LE=function(t,e,n){_(this,t,e,!1,n)},a.prototype.writeInt32BE=function(t,e,n){_(this,t,e,!0,n)},a.prototype.writeFloatLE=function(t,e,n){I(this,t,e,!1,n)},a.prototype.writeFloatBE=function(t,e,n){I(this,t,e,!0,n)},a.prototype.writeDoubleLE=function(t,e,n){S(this,t,e,!1,n)},a.prototype.writeDoubleBE=function(t,e,n){S(this,t,e,!0,n)},i.prototype.readUInt8=a.prototype.readUInt8,i.prototype.readUInt16LE=a.prototype.readUInt16LE,i.prototype.readUInt16BE=a.prototype.readUInt16BE,i.prototype.readUInt32LE=a.prototype.readUInt32LE,i.prototype.readUInt32BE=a.prototype.readUInt32BE,i.prototype.readInt8=a.prototype.readInt8,i.prototype.readInt16LE=a.prototype.readInt16LE,i.prototype.readInt16BE=a.prototype.readInt16BE,i.prototype.readInt32LE=a.prototype.readInt32LE,i.prototype.readInt32BE=a.prototype.readInt32BE,i.prototype.readFloatLE=a.prototype.readFloatLE,i.prototype.readFloatBE=a.prototype.readFloatBE,i.prototype.readDoubleLE=a.prototype.readDoubleLE,i.prototype.readDoubleBE=a.prototype.readDoubleBE,i.prototype.writeUInt8=a.prototype.writeUInt8,i.prototype.writeUInt16LE=a.prototype.writeUInt16LE,i.prototype.writeUInt16BE=a.prototype.writeUInt16BE,i.prototype.writeUInt32LE=a.prototype.writeUInt32LE,i.prototype.writeUInt32BE=a.prototype.writeUInt32BE,i.prototype.writeInt8=a.prototype.writeInt8,i.prototype.writeInt16LE=a.prototype.writeInt16LE,i.prototype.writeInt16BE=a.prototype.writeInt16BE,i.prototype.writeInt32LE=a.prototype.writeInt32LE,i.prototype.writeInt32BE=a.prototype.writeInt32BE,i.prototype.writeFloatLE=a.prototype.writeFloatLE,i.prototype.writeFloatBE=a.prototype.writeFloatBE,i.prototype.writeDoubleLE=a.prototype.writeDoubleLE,i.prototype.writeDoubleBE=a.prototype.writeDoubleBE}),t.define("buffer_ieee754",function(t,e,n,r,o){n.readIEEE754=function(t,e,n,r,o){var i,s,u=8*o-r-1,a=(1<>1,l=-7,p=n?0:o-1,h=n?1:-1,c=t[e+p];for(p+=h,i=c&(1<<-l)-1,c>>=-l,l+=u;l>0;i=256*i+t[e+p],p+=h,l-=8);for(s=i&(1<<-l)-1,i>>=-l,l+=r;l>0;s=256*s+t[e+p],p+=h,l-=8);if(0===i)i=1-f;else{if(i===a)return s?NaN:(c?-1:1)*(1/0);s+=Math.pow(2,r),i-=f}return(c?-1:1)*s*Math.pow(2,i-r)},n.writeIEEE754=function(t,e,n,r,o,i){var s,u,a,f=8*i-o-1,l=(1<>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,c=r?i-1:0,d=r?-1:1,g=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(u=isNaN(e)?1:0,s=l):(s=Math.floor(Math.log(e)/Math.LN2),e*(a=Math.pow(2,-s))<1&&(s--,a*=2),e+=s+p>=1?h/a:h*Math.pow(2,1-p),e*a>=2&&(s++,a/=2),s+p>=l?(u=0,s=l):s+p>=1?(u=(e*a-1)*Math.pow(2,o),s+=p):(u=e*Math.pow(2,p-1)*Math.pow(2,o),s=0));o>=8;t[n+c]=255&u,c+=d,u/=256,o-=8);for(s=s<0;t[n+c]=255&s,c+=d,s/=256,f-=8);t[n+c-d]|=128*g}}),t.define("/difflib.js",function(t,e,n,r,o){(function(){var e,r,o,i,s,u,a,f,l,p,h,c,d,g,y,v,b,w,m,E,k,_=[].indexOf||function(t){for(var e=0,n=this.length;eu;n=0<=u?++i:--i){if(t[n]e[n])return 1}return r-o},k=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},y=function(t){var e,n,r;for(n=0,r=t.length;n=200){l=f(a/100)+1;for(n in e)o=e[n],o.length>l&&(p[n]=!0,delete e[n])}return this.isbjunk=function(t){return k(u,t)},this.isbpopular=function(t){return k(p,t)}},t.prototype.findLongestMatch=function(t,e,n,r){var o,i,s,u,a,f,l,p,h,c,d,g,y,v,b,w,m,E,_,I,S;for(w=[this.a,this.b,this.b2j,this.isbjunk],o=w[0],i=w[1],s=w[2],p=w[3],m=[t,n,0],u=m[0],a=m[1],f=m[2],c={},l=y=t;t<=e?ye;l=t<=e?++y:--y){for(g={},E=k(s,o[l])?s[o[l]]:[],v=0,b=E.length;v=r)break;d=g[h]=(c[h-1]||0)+1,d>f&&(_=[l-d+1,h-d+1,d],u=_[0],a=_[1],f=_[2])}c=g}for(;u>t&&a>n&&!p(i[a-1])&&o[u-1]===i[a-1];)I=[u-1,a-1,f+1],u=I[0],a=I[1],f=I[2];for(;u+ft&&a>n&&p(i[a-1])&&o[u-1]===i[a-1];)S=[u-1,a-1,f+1],u=S[0],a=S[1],f=S[2];for(;u+fa&&(n.push([f,o,h(i,o+t),s,h(u,s+t)]),r.push(n),n=[],v=[p(o,i-t),p(s,u-t)],o=v[0],s=v[1]),n.push([f,o,i,s,u]);return!n.length||1===n.length&&"equal"===n[0][0]||r.push(n),r},t.prototype.ratio=function(){var t,e,n,r,o;for(e=0,o=this.getMatchingBlocks(),n=0,r=o.length;n0&&r++;return b(r,this.a.length+this.b.length)},t.prototype.realQuickRatio=function(){var t,e,n;return n=[this.a.length,this.b.length],t=n[0],e=n[1],b(h(t,e),t+e)},t}(),l=function(t,e,n,o,i){var u,a,f,l,p,h,c,d,g,y,b;if(null==n&&(n=3),null==o&&(o=.6),!(n>0))throw new Error("n must be > 0: ("+n+")");if(!(0<=o&&o<=1))throw new Error("cutoff must be in [0.0, 1.0]: ("+o+")");for(a=[],f=new s,f.setSeq2(t),h=0,d=e.length;h=o&&f.quickRatio()>=o&&f.ratio()>=o&&a.push([f.ratio(),u]);for(a=r.nlargest(a,n,v),b=[],c=0,g=a.length;cr;o=n<=r?++i:--i)s.push(""+t+" "+e[o]);return s},t.prototype._plainReplace=function(t,e,n,r,o,i){var s,a,f,l,p,h,c,d,g,y;for(u(ei;S=o<=i?++U:--U)for(y=r[S],m.setSeq2(y),I=q=e;e<=n?qn;I=e<=n?++q:--q)a=t[I],a!==y?(m.setSeq1(a),m.realQuickRatio()>c&&m.quickRatio()>c&&m.ratio()>c&&(X=[m.ratio(),I,S],c=X[0],d=X[1],g=X[2])):null===k&&(Q=[I,S],k=Q[0],_=Q[1]);if(c=0},E=function(t,e){var n,r;return n=t+1,r=e-t,1===r?""+n:(r||n--,""+n+","+r)},g=function(t,e,n){var r,o,i,u,a,f,l,p,h,c,d,g,y,v,b,w,m,k,_,I,S,j,x,L,B,A,U,q,O,M,T,N,F,D,R,W,C,$;for(N=null!=n?n:{},a=N.fromfile,I=N.tofile,f=N.fromfiledate,S=N.tofiledate,w=N.n,b=N.lineterm,null==a&&(a=""),null==I&&(I=""),null==f&&(f=""),null==S&&(S=""),null==w&&(w=3),null==b&&(b="\n"),v=[],m=!1,F=new s(null,t,e).getGroupedOpcodes(),j=0,A=F.length;j=0&&r.push(n.slice(2));return r},n._arrayCmp=v,n.SequenceMatcher=s,n.getCloseMatches=l,n._countLeading=w,n.Differ=e,n.IS_LINE_JUNK=i,n.IS_CHARACTER_JUNK=o,n._formatRangeUnified=E,n.unifiedDiff=g,n._formatRangeContext=m,n.contextDiff=a,n.ndiff=c,n.restore=d}).call(this)}),t("/difflib.js"),t("/difflib")}(); \ No newline at end of file diff --git a/lib/difflib.js b/lib/difflib.js index 80d250e..7598e99 100644 --- a/lib/difflib.js +++ b/lib/difflib.js @@ -1,4 +1,4 @@ -// Generated by CoffeeScript 1.3.1 +// Generated by CoffeeScript 1.7.1 /* Module difflib -- helpers for computing deltas between objects. @@ -23,8 +23,7 @@ Class SequenceMatcher: Class Differ: For producing human-readable deltas from sequences of lines of text. -*/ - + */ (function() { var Differ, Heap, IS_CHARACTER_JUNK, IS_LINE_JUNK, SequenceMatcher, assert, contextDiff, floor, getCloseMatches, max, min, ndiff, restore, unifiedDiff, _any, _arrayCmp, _calculateRatio, _countLeading, _formatRangeContext, _formatRangeUnified, _has, @@ -75,114 +74,110 @@ Class Differ: SequenceMatcher = (function() { - SequenceMatcher.name = 'SequenceMatcher'; - /* - SequenceMatcher is a flexible class for comparing pairs of sequences of - any type, so long as the sequence elements are hashable. The basic - algorithm predates, and is a little fancier than, an algorithm - published in the late 1980's by Ratcliff and Obershelp under the - hyperbolic name "gestalt pattern matching". The basic idea is to find - the longest contiguous matching subsequence that contains no "junk" - elements (R-O doesn't address junk). The same idea is then applied - recursively to the pieces of the sequences to the left and to the right - of the matching subsequence. This does not yield minimal edit - sequences, but does tend to yield matches that "look right" to people. + SequenceMatcher is a flexible class for comparing pairs of sequences of + any type, so long as the sequence elements are hashable. The basic + algorithm predates, and is a little fancier than, an algorithm + published in the late 1980's by Ratcliff and Obershelp under the + hyperbolic name "gestalt pattern matching". The basic idea is to find + the longest contiguous matching subsequence that contains no "junk" + elements (R-O doesn't address junk). The same idea is then applied + recursively to the pieces of the sequences to the left and to the right + of the matching subsequence. This does not yield minimal edit + sequences, but does tend to yield matches that "look right" to people. - SequenceMatcher tries to compute a "human-friendly diff" between two - sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the - longest *contiguous* & junk-free matching subsequence. That's what - catches peoples' eyes. The Windows(tm) windiff has another interesting - notion, pairing up elements that appear uniquely in each sequence. - That, and the method here, appear to yield more intuitive difference - reports than does diff. This method appears to be the least vulnerable - to synching up on blocks of "junk lines", though (like blank lines in - ordinary text files, or maybe "

" lines in HTML files). That may be - because this is the only method of the 3 that has a *concept* of - "junk" . + SequenceMatcher tries to compute a "human-friendly diff" between two + sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the + longest *contiguous* & junk-free matching subsequence. That's what + catches peoples' eyes. The Windows(tm) windiff has another interesting + notion, pairing up elements that appear uniquely in each sequence. + That, and the method here, appear to yield more intuitive difference + reports than does diff. This method appears to be the least vulnerable + to synching up on blocks of "junk lines", though (like blank lines in + ordinary text files, or maybe "

" lines in HTML files). That may be + because this is the only method of the 3 that has a *concept* of + "junk" . - Example, comparing two strings, and considering blanks to be "junk": + Example, comparing two strings, and considering blanks to be "junk": - >>> isjunk = (c) -> c is ' ' - >>> s = new SequenceMatcher(isjunk, - 'private Thread currentThread;', - 'private volatile Thread currentThread;') + >>> isjunk = (c) -> c is ' ' + >>> s = new SequenceMatcher(isjunk, + 'private Thread currentThread;', + 'private volatile Thread currentThread;') - .ratio() returns a float in [0, 1], measuring the "similarity" of the - sequences. As a rule of thumb, a .ratio() value over 0.6 means the - sequences are close matches: + .ratio() returns a float in [0, 1], measuring the "similarity" of the + sequences. As a rule of thumb, a .ratio() value over 0.6 means the + sequences are close matches: - >>> s.ratio().toPrecision(3) - '0.866' + >>> s.ratio().toPrecision(3) + '0.866' - If you're only interested in where the sequences match, - .getMatchingBlocks() is handy: + If you're only interested in where the sequences match, + .getMatchingBlocks() is handy: - >>> for [a, b, size] in s.getMatchingBlocks() - ... console.log("a[#{a}] and b[#{b}] match for #{size} elements"); - a[0] and b[0] match for 8 elements - a[8] and b[17] match for 21 elements - a[29] and b[38] match for 0 elements + >>> for [a, b, size] in s.getMatchingBlocks() + ... console.log("a[#{a}] and b[#{b}] match for #{size} elements"); + a[0] and b[0] match for 8 elements + a[8] and b[17] match for 21 elements + a[29] and b[38] match for 0 elements - Note that the last tuple returned by .get_matching_blocks() is always a - dummy, (len(a), len(b), 0), and this is the only case in which the last - tuple element (number of elements matched) is 0. + Note that the last tuple returned by .get_matching_blocks() is always a + dummy, (len(a), len(b), 0), and this is the only case in which the last + tuple element (number of elements matched) is 0. - If you want to know how to change the first sequence into the second, - use .get_opcodes(): + If you want to know how to change the first sequence into the second, + use .get_opcodes(): - >>> for [op, a1, a2, b1, b2] in s.getOpcodes() - ... console.log "#{op} a[#{a1}:#{a2}] b[#{b1}:#{b2}]" - equal a[0:8] b[0:8] - insert a[8:8] b[8:17] - equal a[8:29] b[17:38] + >>> for [op, a1, a2, b1, b2] in s.getOpcodes() + ... console.log "#{op} a[#{a1}:#{a2}] b[#{b1}:#{b2}]" + equal a[0:8] b[0:8] + insert a[8:8] b[8:17] + equal a[8:29] b[17:38] - See the Differ class for a fancy human-friendly file differencer, which - uses SequenceMatcher both to compare sequences of lines, and to compare - sequences of characters within similar (near-matching) lines. + See the Differ class for a fancy human-friendly file differencer, which + uses SequenceMatcher both to compare sequences of lines, and to compare + sequences of characters within similar (near-matching) lines. - See also function getCloseMatches() in this module, which shows how - simple code building on SequenceMatcher can be used to do useful work. + See also function getCloseMatches() in this module, which shows how + simple code building on SequenceMatcher can be used to do useful work. - Timing: Basic R-O is cubic time worst case and quadratic time expected - case. SequenceMatcher is quadratic time for the worst case and has - expected-case behavior dependent in a complicated way on how many - elements the sequences have in common; best case time is linear. + Timing: Basic R-O is cubic time worst case and quadratic time expected + case. SequenceMatcher is quadratic time for the worst case and has + expected-case behavior dependent in a complicated way on how many + elements the sequences have in common; best case time is linear. - Methods: + Methods: - constructor(isjunk=null, a='', b='') - Construct a SequenceMatcher. + constructor(isjunk=null, a='', b='') + Construct a SequenceMatcher. - setSeqs(a, b) - Set the two sequences to be compared. + setSeqs(a, b) + Set the two sequences to be compared. - setSeq1(a) - Set the first sequence to be compared. + setSeq1(a) + Set the first sequence to be compared. - setSeq2(b) - Set the second sequence to be compared. + setSeq2(b) + Set the second sequence to be compared. - findLongestMatch(alo, ahi, blo, bhi) - Find longest matching block in a[alo:ahi] and b[blo:bhi]. + findLongestMatch(alo, ahi, blo, bhi) + Find longest matching block in a[alo:ahi] and b[blo:bhi]. - getMatchingBlocks() - Return list of triples describing matching subsequences. + getMatchingBlocks() + Return list of triples describing matching subsequences. - getOpcodes() - Return list of 5-tuples describing how to turn a into b. + getOpcodes() + Return list of 5-tuples describing how to turn a into b. - ratio() - Return a measure of the sequences' similarity (float in [0,1]). + ratio() + Return a measure of the sequences' similarity (float in [0,1]). - quickRatio() - Return an upper bound on .ratio() relatively quickly. + quickRatio() + Return an upper bound on .ratio() relatively quickly. - realQuickRatio() - Return an upper bound on ratio() very quickly. - */ - - + realQuickRatio() + Return an upper bound on ratio() very quickly. + */ function SequenceMatcher(isjunk, a, b, autojunk) { this.isjunk = isjunk; if (a == null) { @@ -192,35 +187,36 @@ Class Differ: b = ''; } this.autojunk = autojunk != null ? autojunk : true; + /* - Construct a SequenceMatcher. + Construct a SequenceMatcher. - Optional arg isjunk is null (the default), or a one-argument - function that takes a sequence element and returns true iff the - element is junk. Null is equivalent to passing "(x) -> 0", i.e. - no elements are considered to be junk. For example, pass - (x) -> x in ' \t' - if you're comparing lines as sequences of characters, and don't - want to synch up on blanks or hard tabs. + Optional arg isjunk is null (the default), or a one-argument + function that takes a sequence element and returns true iff the + element is junk. Null is equivalent to passing "(x) -> 0", i.e. + no elements are considered to be junk. For example, pass + (x) -> x in ' \t' + if you're comparing lines as sequences of characters, and don't + want to synch up on blanks or hard tabs. - Optional arg a is the first of two sequences to be compared. By - default, an empty string. The elements of a must be hashable. See - also .setSeqs() and .setSeq1(). + Optional arg a is the first of two sequences to be compared. By + default, an empty string. The elements of a must be hashable. See + also .setSeqs() and .setSeq1(). - Optional arg b is the second of two sequences to be compared. By - default, an empty string. The elements of b must be hashable. See - also .setSeqs() and .setSeq2(). + Optional arg b is the second of two sequences to be compared. By + default, an empty string. The elements of b must be hashable. See + also .setSeqs() and .setSeq2(). - Optional arg autojunk should be set to false to disable the - "automatic junk heuristic" that treats popular elements as junk - (see module documentation for more information). - */ - + Optional arg autojunk should be set to false to disable the + "automatic junk heuristic" that treats popular elements as junk + (see module documentation for more information). + */ this.a = this.b = null; this.setSeqs(a, b); } SequenceMatcher.prototype.setSeqs = function(a, b) { + /* Set the two sequences to be compared. @@ -228,12 +224,13 @@ Class Differ: >>> s.setSeqs('abcd', 'bcde') >>> s.ratio() 0.75 - */ + */ this.setSeq1(a); return this.setSeq2(b); }; SequenceMatcher.prototype.setSeq1 = function(a) { + /* Set the first sequence to be compared. @@ -252,7 +249,7 @@ Class Differ: repeatedly for each of the other sequences. See also setSeqs() and setSeq2(). - */ + */ if (a === this.a) { return; } @@ -261,25 +258,26 @@ Class Differ: }; SequenceMatcher.prototype.setSeq2 = function(b) { + /* - Set the second sequence to be compared. + Set the second sequence to be compared. - The first sequence to be compared is not changed. + The first sequence to be compared is not changed. - >>> s = new SequenceMatcher(null, 'abcd', 'bcde') - >>> s.ratio() - 0.75 - >>> s.setSeq2('abcd') - >>> s.ratio() - 1.0 + >>> s = new SequenceMatcher(null, 'abcd', 'bcde') + >>> s.ratio() + 0.75 + >>> s.setSeq2('abcd') + >>> s.ratio() + 1.0 - SequenceMatcher computes and caches detailed information about the - second sequence, so if you want to compare one sequence S against - many sequences, use .setSeq2(S) once and call .setSeq1(x) - repeatedly for each of the other sequences. + SequenceMatcher computes and caches detailed information about the + second sequence, so if you want to compare one sequence S against + many sequences, use .setSeq2(S) once and call .setSeq1(x) + repeatedly for each of the other sequences. - See also setSeqs() and setSeq1(). - */ + See also setSeqs() and setSeq1(). + */ if (b === this.b) { return; } @@ -331,6 +329,7 @@ Class Differ: }; SequenceMatcher.prototype.findLongestMatch = function(alo, ahi, blo, bhi) { + /* Find longest matching block in a[alo...ahi] and b[blo...bhi]. @@ -356,8 +355,7 @@ Class Differ: >>> s = new SequenceMatcher(null, 'ab', 'c') >>> s.findLongestMatch(0, 2, 0, 1) [0, 0, 0] - */ - + */ var a, b, b2j, besti, bestj, bestsize, i, isbjunk, j, j2len, k, newj2len, _i, _j, _len, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; _ref = [this.a, this.b, this.b2j, this.isbjunk], a = _ref[0], b = _ref[1], b2j = _ref[2], isbjunk = _ref[3]; _ref1 = [alo, blo, 0], besti = _ref1[0], bestj = _ref1[1], bestsize = _ref1[2]; @@ -396,25 +394,25 @@ Class Differ: }; SequenceMatcher.prototype.getMatchingBlocks = function() { + /* - Return list of triples describing matching subsequences. + Return list of triples describing matching subsequences. - Each triple is of the form [i, j, n], and means that - a[i...i+n] == b[j...j+n]. The triples are monotonically increasing in - i and in j. it's also guaranteed that if - [i, j, n] and [i', j', n'] are adjacent triples in the list, and - the second is not the last triple in the list, then i+n != i' or - j+n != j'. IOW, adjacent triples never describe adjacent equal - blocks. + Each triple is of the form [i, j, n], and means that + a[i...i+n] == b[j...j+n]. The triples are monotonically increasing in + i and in j. it's also guaranteed that if + [i, j, n] and [i', j', n'] are adjacent triples in the list, and + the second is not the last triple in the list, then i+n != i' or + j+n != j'. IOW, adjacent triples never describe adjacent equal + blocks. - The last triple is a dummy, [a.length, b.length, 0], and is the only - triple with n==0. + The last triple is a dummy, [a.length, b.length, 0], and is the only + triple with n==0. - >>> s = new SequenceMatcher(null, 'abxcd', 'abcd') - >>> s.getMatchingBlocks() - [[0, 0, 2], [3, 2, 2], [5, 4, 0]] - */ - + >>> s = new SequenceMatcher(null, 'abxcd', 'abcd') + >>> s.getMatchingBlocks() + [[0, 0, 2], [3, 2, 2], [5, 4, 0]] + */ var ahi, alo, bhi, blo, i, i1, i2, j, j1, j2, k, k1, k2, la, lb, matchingBlocks, nonAdjacent, queue, x, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4; if (this.matchingBlocks) { return this.matchingBlocks; @@ -457,6 +455,7 @@ Class Differ: }; SequenceMatcher.prototype.getOpcodes = function() { + /* Return list of 5-tuples describing how to turn a into b. @@ -480,8 +479,7 @@ Class Differ: [ 'replace' , 3 , 4 , 2 , 3 ] , [ 'equal' , 4 , 6 , 3 , 5 ] , [ 'insert' , 6 , 6 , 5 , 6 ] ] - */ - + */ var ai, answer, bj, i, j, size, tag, _i, _len, _ref, _ref1, _ref2; if (this.opcodes) { return this.opcodes; @@ -515,6 +513,7 @@ Class Differ: if (n == null) { n = 3; } + /* Isolate change clusters by eliminating ranges with no changes. @@ -540,8 +539,7 @@ Class Differ: [ [ 'equal' , 31 , 34 , 27 , 30 ], [ 'replace' , 34 , 35 , 30 , 31 ], [ 'equal' , 35 , 38 , 31 , 34 ] ] ] - */ - + */ codes = this.getOpcodes(); if (!codes.length) { codes = [['equal', 0, 1, 0, 1]]; @@ -574,28 +572,28 @@ Class Differ: }; SequenceMatcher.prototype.ratio = function() { + /* - Return a measure of the sequences' similarity (float in [0,1]). + Return a measure of the sequences' similarity (float in [0,1]). - Where T is the total number of elements in both sequences, and - M is the number of matches, this is 2.0*M / T. - Note that this is 1 if the sequences are identical, and 0 if - they have nothing in common. + Where T is the total number of elements in both sequences, and + M is the number of matches, this is 2.0*M / T. + Note that this is 1 if the sequences are identical, and 0 if + they have nothing in common. - .ratio() is expensive to compute if you haven't already computed - .getMatchingBlocks() or .getOpcodes(), in which case you may - want to try .quickRatio() or .realQuickRatio() first to get an - upper bound. - - >>> s = new SequenceMatcher(null, 'abcd', 'bcde') - >>> s.ratio() - 0.75 - >>> s.quickRatio() - 0.75 - >>> s.realQuickRatio() - 1.0 - */ - + .ratio() is expensive to compute if you haven't already computed + .getMatchingBlocks() or .getOpcodes(), in which case you may + want to try .quickRatio() or .realQuickRatio() first to get an + upper bound. + + >>> s = new SequenceMatcher(null, 'abcd', 'bcde') + >>> s.ratio() + 0.75 + >>> s.quickRatio() + 0.75 + >>> s.realQuickRatio() + 1.0 + */ var match, matches, _i, _len, _ref; matches = 0; _ref = this.getMatchingBlocks(); @@ -607,13 +605,13 @@ Class Differ: }; SequenceMatcher.prototype.quickRatio = function() { + /* - Return an upper bound on ratio() relatively quickly. + Return an upper bound on ratio() relatively quickly. - This isn't defined beyond that it is an upper bound on .ratio(), and - is faster to compute. - */ - + This isn't defined beyond that it is an upper bound on .ratio(), and + is faster to compute. + */ var avail, elt, fullbcount, matches, numb, _i, _j, _len, _len1, _ref, _ref1; if (!this.fullbcount) { this.fullbcount = fullbcount = {}; @@ -643,13 +641,13 @@ Class Differ: }; SequenceMatcher.prototype.realQuickRatio = function() { + /* - Return an upper bound on ratio() very quickly. + Return an upper bound on ratio() very quickly. - This isn't defined beyond that it is an upper bound on .ratio(), and - is faster to compute than either .ratio() or .quickRatio(). - */ - + This isn't defined beyond that it is an upper bound on .ratio(), and + is faster to compute than either .ratio() or .quickRatio(). + */ var la, lb, _ref; _ref = [this.a.length, this.b.length], la = _ref[0], lb = _ref[1]; return _calculateRatio(min(la, lb), la + lb); @@ -659,41 +657,44 @@ Class Differ: })(); - getCloseMatches = function(word, possibilities, n, cutoff) { - var result, s, score, x, _i, _j, _len, _len1, _ref, _results; + getCloseMatches = function(word, possibilities, n, cutoff, formatter) { + var o, result, s, score, x, _i, _j, _len, _len1, _ref, _results; if (n == null) { n = 3; } if (cutoff == null) { cutoff = 0.6; } + /* - Use SequenceMatcher to return list of the best "good enough" matches. + Use SequenceMatcher to return list of the best "good enough" matches. - word is a sequence for which close matches are desired (typically a - string). + word is a sequence for which close matches are desired (typically a + string). - possibilities is a list of sequences against which to match word - (typically a list of strings). + possibilities is a list of sequences against which to match word + (typically a list of strings). - Optional arg n (default 3) is the maximum number of close matches to - return. n must be > 0. + Optional arg n (default 3) is the maximum number of close matches to + return. n must be > 0. - Optional arg cutoff (default 0.6) is a float in [0, 1]. Possibilities - that don't score at least that similar to word are ignored. + Optional arg cutoff (default 0.6) is a float in [0, 1]. Possibilities + that don't score at least that similar to word are ignored. - The best (no more than n) matches among the possibilities are returned - in a list, sorted by similarity score, most similar first. + Optional arg formatter is a function that is run on each element from possibilities + before matching is run. - >>> getCloseMatches('appel', ['ape', 'apple', 'peach', 'puppy']) - ['apple', 'ape'] - >>> KEYWORDS = require('coffee-script').RESERVED - >>> getCloseMatches('wheel', KEYWORDS) - ['when', 'while'] - >>> getCloseMatches('accost', KEYWORDS) - ['const'] - */ - + The best (no more than n) matches among the possibilities are returned + in a list, sorted by similarity score, most similar first. + + >>> getCloseMatches('appel', ['ape', 'apple', 'peach', 'puppy']) + ['apple', 'ape'] + >>> KEYWORDS = require('coffee-script').RESERVED + >>> getCloseMatches('wheel', KEYWORDS) + ['when', 'while'] + >>> getCloseMatches('accost', KEYWORDS) + ['const'] + */ if (!(n > 0)) { throw new Error("n must be > 0: (" + n + ")"); } @@ -705,9 +706,13 @@ Class Differ: s.setSeq2(word); for (_i = 0, _len = possibilities.length; _i < _len; _i++) { x = possibilities[_i]; + o = x; + if (formatter) { + x = formatter(x); + } s.setSeq1(x); if (s.realQuickRatio() >= cutoff && s.quickRatio() >= cutoff && s.ratio() >= cutoff) { - result.push([s.ratio(), x]); + result.push([s.ratio(), o]); } } result = Heap.nlargest(result, n, _arrayCmp); @@ -720,13 +725,13 @@ Class Differ: }; _countLeading = function(line, ch) { + /* - Return number of `ch` characters at the start of `line`. + Return number of `ch` characters at the start of `line`. - >>> _countLeading(' abc', ' ') - 3 - */ - + >>> _countLeading(' abc', ' ') + 3 + */ var i, n, _ref; _ref = [0, line.length], i = _ref[0], n = _ref[1]; while (i < n && line[i] === ch) { @@ -737,122 +742,118 @@ Class Differ: Differ = (function() { - Differ.name = 'Differ'; - /* - Differ is a class for comparing sequences of lines of text, and - producing human-readable differences or deltas. Differ uses - SequenceMatcher both to compare sequences of lines, and to compare - sequences of characters within similar (near-matching) lines. - - Each line of a Differ delta begins with a two-letter code: - - '- ' line unique to sequence 1 - '+ ' line unique to sequence 2 - ' ' line common to both sequences - '? ' line not present in either input sequence - - Lines beginning with '? ' attempt to guide the eye to intraline - differences, and were not present in either input sequence. These lines - can be confusing if the sequences contain tab characters. - - Note that Differ makes no claim to produce a *minimal* diff. To the - contrary, minimal diffs are often counter-intuitive, because they synch - up anywhere possible, sometimes accidental matches 100 pages apart. - Restricting synch points to contiguous matches preserves some notion of - locality, at the occasional cost of producing a longer diff. - - Example: Comparing two texts. - - >>> text1 = ['1. Beautiful is better than ugly.\n', - ... '2. Explicit is better than implicit.\n', - ... '3. Simple is better than complex.\n', - ... '4. Complex is better than complicated.\n'] - >>> text1.length - 4 - >>> text2 = ['1. Beautiful is better than ugly.\n', - ... '3. Simple is better than complex.\n', - ... '4. Complicated is better than complex.\n', - ... '5. Flat is better than nested.\n'] - - Next we instantiate a Differ object: - - >>> d = new Differ() - - Note that when instantiating a Differ object we may pass functions to - filter out line and character 'junk'. - - Finally, we compare the two: - - >>> result = d.compare(text1, text2) - [ ' 1. Beautiful is better than ugly.\n', - '- 2. Explicit is better than implicit.\n', - '- 3. Simple is better than complex.\n', - '+ 3. Simple is better than complex.\n', - '? ++\n', - '- 4. Complex is better than complicated.\n', - '? ^ ---- ^\n', - '+ 4. Complicated is better than complex.\n', - '? ++++ ^ ^\n', - '+ 5. Flat is better than nested.\n' ] - - Methods: - - constructor(linejunk=null, charjunk=null) - Construct a text differencer, with optional filters. - compare(a, b) - Compare two sequences of lines; generate the resulting delta. - */ - - + Differ is a class for comparing sequences of lines of text, and + producing human-readable differences or deltas. Differ uses + SequenceMatcher both to compare sequences of lines, and to compare + sequences of characters within similar (near-matching) lines. + + Each line of a Differ delta begins with a two-letter code: + + '- ' line unique to sequence 1 + '+ ' line unique to sequence 2 + ' ' line common to both sequences + '? ' line not present in either input sequence + + Lines beginning with '? ' attempt to guide the eye to intraline + differences, and were not present in either input sequence. These lines + can be confusing if the sequences contain tab characters. + + Note that Differ makes no claim to produce a *minimal* diff. To the + contrary, minimal diffs are often counter-intuitive, because they synch + up anywhere possible, sometimes accidental matches 100 pages apart. + Restricting synch points to contiguous matches preserves some notion of + locality, at the occasional cost of producing a longer diff. + + Example: Comparing two texts. + + >>> text1 = ['1. Beautiful is better than ugly.\n', + ... '2. Explicit is better than implicit.\n', + ... '3. Simple is better than complex.\n', + ... '4. Complex is better than complicated.\n'] + >>> text1.length + 4 + >>> text2 = ['1. Beautiful is better than ugly.\n', + ... '3. Simple is better than complex.\n', + ... '4. Complicated is better than complex.\n', + ... '5. Flat is better than nested.\n'] + + Next we instantiate a Differ object: + + >>> d = new Differ() + + Note that when instantiating a Differ object we may pass functions to + filter out line and character 'junk'. + + Finally, we compare the two: + + >>> result = d.compare(text1, text2) + [ ' 1. Beautiful is better than ugly.\n', + '- 2. Explicit is better than implicit.\n', + '- 3. Simple is better than complex.\n', + '+ 3. Simple is better than complex.\n', + '? ++\n', + '- 4. Complex is better than complicated.\n', + '? ^ ---- ^\n', + '+ 4. Complicated is better than complex.\n', + '? ++++ ^ ^\n', + '+ 5. Flat is better than nested.\n' ] + + Methods: + + constructor(linejunk=null, charjunk=null) + Construct a text differencer, with optional filters. + compare(a, b) + Compare two sequences of lines; generate the resulting delta. + */ function Differ(linejunk, charjunk) { this.linejunk = linejunk; this.charjunk = charjunk; + /* - Construct a text differencer, with optional filters. + Construct a text differencer, with optional filters. - The two optional keyword parameters are for filter functions: + The two optional keyword parameters are for filter functions: - - `linejunk`: A function that should accept a single string argument, - and return true iff the string is junk. The module-level function - `IS_LINE_JUNK` may be used to filter out lines without visible - characters, except for at most one splat ('#'). It is recommended - to leave linejunk null. + - `linejunk`: A function that should accept a single string argument, + and return true iff the string is junk. The module-level function + `IS_LINE_JUNK` may be used to filter out lines without visible + characters, except for at most one splat ('#'). It is recommended + to leave linejunk null. - - `charjunk`: A function that should accept a string of length 1. The - module-level function `IS_CHARACTER_JUNK` may be used to filter out - whitespace characters (a blank or tab; **note**: bad idea to include - newline in this!). Use of IS_CHARACTER_JUNK is recommended. - */ - + - `charjunk`: A function that should accept a string of length 1. The + module-level function `IS_CHARACTER_JUNK` may be used to filter out + whitespace characters (a blank or tab; **note**: bad idea to include + newline in this!). Use of IS_CHARACTER_JUNK is recommended. + */ } Differ.prototype.compare = function(a, b) { + /* - Compare two sequences of lines; generate the resulting delta. + Compare two sequences of lines; generate the resulting delta. - Each sequence must contain individual single-line strings ending with - newlines. Such sequences can be obtained from the `readlines()` method - of file-like objects. The delta generated also consists of newline- - terminated strings, ready to be printed as-is via the writeline() - method of a file-like object. + Each sequence must contain individual single-line strings ending with + newlines. Such sequences can be obtained from the `readlines()` method + of file-like objects. The delta generated also consists of newline- + terminated strings, ready to be printed as-is via the writeline() + method of a file-like object. - Example: + Example: - >>> d = new Differ - >>> d.compare(['one\n', 'two\n', 'three\n'], - ... ['ore\n', 'tree\n', 'emu\n']) - [ '- one\n', - '? ^\n', - '+ ore\n', - '? ^\n', - '- two\n', - '- three\n', - '? -\n', - '+ tree\n', - '+ emu\n' ] - */ - + >>> d = new Differ + >>> d.compare(['one\n', 'two\n', 'three\n'], + ... ['ore\n', 'tree\n', 'emu\n']) + [ '- one\n', + '? ^\n', + '+ ore\n', + '? ^\n', + '- two\n', + '- three\n', + '? -\n', + '+ tree\n', + '+ emu\n' ] + */ var ahi, alo, bhi, blo, cruncher, g, line, lines, tag, _i, _j, _len, _len1, _ref, _ref1; cruncher = new SequenceMatcher(this.linejunk, a, b); lines = []; @@ -884,10 +885,10 @@ Class Differ: }; Differ.prototype._dump = function(tag, x, lo, hi) { - /* - Generate comparison results for a same-tagged range. - */ + /* + Generate comparison results for a same-tagged range. + */ var i, _i, _results; _results = []; for (i = _i = lo; lo <= hi ? _i < hi : _i > hi; i = lo <= hi ? ++_i : --_i) { @@ -919,22 +920,22 @@ Class Differ: }; Differ.prototype._fancyReplace = function(a, alo, ahi, b, blo, bhi) { + /* - When replacing one block of lines with another, search the blocks - for *similar* lines; the best-matching pair (if any) is used as a - synch point, and intraline difference marking is done on the - similar pair. Lots of work, but often worth it. + When replacing one block of lines with another, search the blocks + for *similar* lines; the best-matching pair (if any) is used as a + synch point, and intraline difference marking is done on the + similar pair. Lots of work, but often worth it. - Example: - >>> d = new Differ - >>> d._fancyReplace(['abcDefghiJkl\n'], 0, 1, - ... ['abcdefGhijkl\n'], 0, 1) - [ '- abcDefghiJkl\n', - '? ^ ^ ^\n', - '+ abcdefGhijkl\n', - '? ^ ^ ^\n' ] - */ - + Example: + >>> d = new Differ + >>> d._fancyReplace(['abcDefghiJkl\n'], 0, 1, + ... ['abcdefGhijkl\n'], 0, 1) + [ '- abcDefghiJkl\n', + '? ^ ^ ^\n', + '+ abcdefGhijkl\n', + '? ^ ^ ^\n' ] + */ var aelt, ai, ai1, ai2, atags, belt, bestRatio, besti, bestj, bj, bj1, bj2, btags, cruncher, cutoff, eqi, eqj, i, j, la, lb, line, lines, tag, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _n, _o, _ref, _ref1, _ref10, _ref11, _ref12, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; _ref = [0.74, 0.75], bestRatio = _ref[0], cutoff = _ref[1]; cruncher = new SequenceMatcher(this.charjunk); @@ -1034,19 +1035,19 @@ Class Differ: }; Differ.prototype._qformat = function(aline, bline, atags, btags) { + /* - Format "?" output and deal with leading tabs. + Format "?" output and deal with leading tabs. - Example: + Example: - >>> d = new Differ - >>> d._qformat('\tabcDefghiJkl\n', '\tabcdefGhijkl\n', - [ '- \tabcDefghiJkl\n', - '? \t ^ ^ ^\n', - '+ \tabcdefGhijkl\n', - '? \t ^ ^ ^\n' ] - */ - + >>> d = new Differ + >>> d._qformat('\tabcDefghiJkl\n', '\tabcdefGhijkl\n', + [ '- \tabcDefghiJkl\n', + '? \t ^ ^ ^\n', + '+ \tabcdefGhijkl\n', + '? \t ^ ^ ^\n' ] + */ var common, lines; lines = []; common = min(_countLeading(aline, '\t'), _countLeading(bline, '\t')); @@ -1073,19 +1074,19 @@ Class Differ: if (pat == null) { pat = /^\s*#?\s*$/; } - /* - Return 1 for ignorable line: iff `line` is blank or contains a single '#'. - - Examples: - - >>> IS_LINE_JUNK('\n') - true - >>> IS_LINE_JUNK(' # \n') - true - >>> IS_LINE_JUNK('hello\n') - false - */ + /* + Return 1 for ignorable line: iff `line` is blank or contains a single '#'. + + Examples: + + >>> IS_LINE_JUNK('\n') + true + >>> IS_LINE_JUNK(' # \n') + true + >>> IS_LINE_JUNK('hello\n') + false + */ return pat.test(line); }; @@ -1093,28 +1094,28 @@ Class Differ: if (ws == null) { ws = ' \t'; } - /* - Return 1 for ignorable character: iff `ch` is a space or tab. - - Examples: - >>> IS_CHARACTER_JUNK(' ').should.be.true - true - >>> IS_CHARACTER_JUNK('\t').should.be.true - true - >>> IS_CHARACTER_JUNK('\n').should.be.false - false - >>> IS_CHARACTER_JUNK('x').should.be.false - false - */ + /* + Return 1 for ignorable character: iff `ch` is a space or tab. + + Examples: + >>> IS_CHARACTER_JUNK(' ').should.be.true + true + >>> IS_CHARACTER_JUNK('\t').should.be.true + true + >>> IS_CHARACTER_JUNK('\n').should.be.false + false + >>> IS_CHARACTER_JUNK('x').should.be.false + false + */ return __indexOf.call(ws, ch) >= 0; }; _formatRangeUnified = function(start, stop) { - /* - Convert range to the "ed" format' - */ + /* + Convert range to the "ed" format' + */ var beginning, length; beginning = start + 1; length = stop - start; @@ -1130,45 +1131,45 @@ Class Differ: unifiedDiff = function(a, b, _arg) { var file1Range, file2Range, first, fromdate, fromfile, fromfiledate, group, i1, i2, j1, j2, last, line, lines, lineterm, n, started, tag, todate, tofile, tofiledate, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6; _ref = _arg != null ? _arg : {}, fromfile = _ref.fromfile, tofile = _ref.tofile, fromfiledate = _ref.fromfiledate, tofiledate = _ref.tofiledate, n = _ref.n, lineterm = _ref.lineterm; + /* - Compare two sequences of lines; generate the delta as a unified diff. + Compare two sequences of lines; generate the delta as a unified diff. - Unified diffs are a compact way of showing line changes and a few - lines of context. The number of context lines is set by 'n' which - defaults to three. + Unified diffs are a compact way of showing line changes and a few + lines of context. The number of context lines is set by 'n' which + defaults to three. - By default, the diff control lines (those with ---, +++, or @@) are - created with a trailing newline. + By default, the diff control lines (those with ---, +++, or @@) are + created with a trailing newline. - For inputs that do not have trailing newlines, set the lineterm - argument to "" so that the output will be uniformly newline free. + For inputs that do not have trailing newlines, set the lineterm + argument to "" so that the output will be uniformly newline free. - The unidiff format normally has a header for filenames and modification - times. Any or all of these may be specified using strings for - 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. - The modification times are normally expressed in the ISO 8601 format. + The unidiff format normally has a header for filenames and modification + times. Any or all of these may be specified using strings for + 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. + The modification times are normally expressed in the ISO 8601 format. - Example: + Example: - >>> unifiedDiff('one two three four'.split(' '), - ... 'zero one tree four'.split(' '), { - ... fromfile: 'Original' - ... tofile: 'Current', - ... fromfiledate: '2005-01-26 23:30:50', - ... tofiledate: '2010-04-02 10:20:52', - ... lineterm: '' - ... }) - [ '--- Original\t2005-01-26 23:30:50', - '+++ Current\t2010-04-02 10:20:52', - '@@ -1,4 +1,4 @@', - '+zero', - ' one', - '-two', - '-three', - '+tree', - ' four' ] - */ - + >>> unifiedDiff('one two three four'.split(' '), + ... 'zero one tree four'.split(' '), { + ... fromfile: 'Original' + ... tofile: 'Current', + ... fromfiledate: '2005-01-26 23:30:50', + ... tofiledate: '2010-04-02 10:20:52', + ... lineterm: '' + ... }) + [ '--- Original\t2005-01-26 23:30:50', + '+++ Current\t2010-04-02 10:20:52', + '@@ -1,4 +1,4 @@', + '+zero', + ' one', + '-two', + '-three', + '+tree', + ' four' ] + */ if (fromfile == null) { fromfile = ''; } @@ -1233,10 +1234,10 @@ Class Differ: }; _formatRangeContext = function(start, stop) { - /* - Convert range to the "ed" format' - */ + /* + Convert range to the "ed" format' + */ var beginning, length; beginning = start + 1; length = stop - start; @@ -1252,47 +1253,47 @@ Class Differ: contextDiff = function(a, b, _arg) { var file1Range, file2Range, first, fromdate, fromfile, fromfiledate, group, i1, i2, j1, j2, last, line, lines, lineterm, n, prefix, started, tag, todate, tofile, tofiledate, _, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6; _ref = _arg != null ? _arg : {}, fromfile = _ref.fromfile, tofile = _ref.tofile, fromfiledate = _ref.fromfiledate, tofiledate = _ref.tofiledate, n = _ref.n, lineterm = _ref.lineterm; + /* - Compare two sequences of lines; generate the delta as a context diff. + Compare two sequences of lines; generate the delta as a context diff. - Context diffs are a compact way of showing line changes and a few - lines of context. The number of context lines is set by 'n' which - defaults to three. + Context diffs are a compact way of showing line changes and a few + lines of context. The number of context lines is set by 'n' which + defaults to three. - By default, the diff control lines (those with *** or ---) are - created with a trailing newline. This is helpful so that inputs - created from file.readlines() result in diffs that are suitable for - file.writelines() since both the inputs and outputs have trailing - newlines. + By default, the diff control lines (those with *** or ---) are + created with a trailing newline. This is helpful so that inputs + created from file.readlines() result in diffs that are suitable for + file.writelines() since both the inputs and outputs have trailing + newlines. - For inputs that do not have trailing newlines, set the lineterm - argument to "" so that the output will be uniformly newline free. + For inputs that do not have trailing newlines, set the lineterm + argument to "" so that the output will be uniformly newline free. - The context diff format normally has a header for filenames and - modification times. Any or all of these may be specified using - strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. - The modification times are normally expressed in the ISO 8601 format. - If not specified, the strings default to blanks. + The context diff format normally has a header for filenames and + modification times. Any or all of these may be specified using + strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. + The modification times are normally expressed in the ISO 8601 format. + If not specified, the strings default to blanks. - Example: - >>> a = ['one\n', 'two\n', 'three\n', 'four\n'] - >>> b = ['zero\n', 'one\n', 'tree\n', 'four\n'] - >>> contextDiff(a, b, {fromfile: 'Original', tofile: 'Current'}) - [ '*** Original\n', - '--- Current\n', - '***************\n', - '*** 1,4 ****\n', - ' one\n', - '! two\n', - '! three\n', - ' four\n', - '--- 1,4 ----\n', - '+ zero\n', - ' one\n', - '! tree\n', - ' four\n' ] - */ - + Example: + >>> a = ['one\n', 'two\n', 'three\n', 'four\n'] + >>> b = ['zero\n', 'one\n', 'tree\n', 'four\n'] + >>> contextDiff(a, b, {fromfile: 'Original', tofile: 'Current'}) + [ '*** Original\n', + '--- Current\n', + '***************\n', + '*** 1,4 ****\n', + ' one\n', + '! two\n', + '! three\n', + ' four\n', + '--- 1,4 ----\n', + '+ zero\n', + ' one\n', + '! tree\n', + ' four\n' ] + */ if (fromfile == null) { fromfile = ''; } @@ -1383,61 +1384,61 @@ Class Differ: if (charjunk == null) { charjunk = IS_CHARACTER_JUNK; } + /* - Compare `a` and `b` (lists of strings); return a `Differ`-style delta. + Compare `a` and `b` (lists of strings); return a `Differ`-style delta. - Optional keyword parameters `linejunk` and `charjunk` are for filter - functions (or None): + Optional keyword parameters `linejunk` and `charjunk` are for filter + functions (or None): - - linejunk: A function that should accept a single string argument, and - return true iff the string is junk. The default is null, and is - recommended; + - linejunk: A function that should accept a single string argument, and + return true iff the string is junk. The default is null, and is + recommended; - - charjunk: A function that should accept a string of length 1. The - default is module-level function IS_CHARACTER_JUNK, which filters out - whitespace characters (a blank or tab; note: bad idea to include newline - in this!). + - charjunk: A function that should accept a string of length 1. The + default is module-level function IS_CHARACTER_JUNK, which filters out + whitespace characters (a blank or tab; note: bad idea to include newline + in this!). - Example: - >>> a = ['one\n', 'two\n', 'three\n'] - >>> b = ['ore\n', 'tree\n', 'emu\n'] - >>> ndiff(a, b) - [ '- one\n', - '? ^\n', - '+ ore\n', - '? ^\n', - '- two\n', - '- three\n', - '? -\n', - '+ tree\n', - '+ emu\n' ] - */ - + Example: + >>> a = ['one\n', 'two\n', 'three\n'] + >>> b = ['ore\n', 'tree\n', 'emu\n'] + >>> ndiff(a, b) + [ '- one\n', + '? ^\n', + '+ ore\n', + '? ^\n', + '- two\n', + '- three\n', + '? -\n', + '+ tree\n', + '+ emu\n' ] + */ return (new Differ(linejunk, charjunk)).compare(a, b); }; restore = function(delta, which) { - /* - Generate one of the two sequences that generated a delta. - - Given a `delta` produced by `Differ.compare()` or `ndiff()`, extract - lines originating from file 1 or 2 (parameter `which`), stripping off line - prefixes. - - Examples: - >>> a = ['one\n', 'two\n', 'three\n'] - >>> b = ['ore\n', 'tree\n', 'emu\n'] - >>> diff = ndiff(a, b) - >>> restore(diff, 1) - [ 'one\n', - 'two\n', - 'three\n' ] - >>> restore(diff, 2) - [ 'ore\n', - 'tree\n', - 'emu\n' ] - */ + /* + Generate one of the two sequences that generated a delta. + + Given a `delta` produced by `Differ.compare()` or `ndiff()`, extract + lines originating from file 1 or 2 (parameter `which`), stripping off line + prefixes. + + Examples: + >>> a = ['one\n', 'two\n', 'three\n'] + >>> b = ['ore\n', 'tree\n', 'emu\n'] + >>> diff = ndiff(a, b) + >>> restore(diff, 1) + [ 'one\n', + 'two\n', + 'three\n' ] + >>> restore(diff, 2) + [ 'ore\n', + 'tree\n', + 'emu\n' ] + */ var line, lines, prefixes, tag, _i, _len, _ref; tag = { 1: '- ', diff --git a/src/difflib.coffee b/src/difflib.coffee index 7cbd396..b28a605 100644 --- a/src/difflib.coffee +++ b/src/difflib.coffee @@ -678,7 +678,7 @@ class SequenceMatcher # shorter sequence _calculateRatio(min(la, lb), la + lb) -getCloseMatches = (word, possibilities, n=3, cutoff=0.6) -> +getCloseMatches = (word, possibilities, n=3, cutoff=0.6, formatter) -> ### Use SequenceMatcher to return list of the best "good enough" matches. @@ -694,6 +694,9 @@ getCloseMatches = (word, possibilities, n=3, cutoff=0.6) -> Optional arg cutoff (default 0.6) is a float in [0, 1]. Possibilities that don't score at least that similar to word are ignored. + Optional arg formatter is a function that is run on each element from possibilities + before matching is run. + The best (no more than n) matches among the possibilities are returned in a list, sorted by similarity score, most similar first. @@ -713,11 +716,14 @@ getCloseMatches = (word, possibilities, n=3, cutoff=0.6) -> s = new SequenceMatcher() s.setSeq2(word) for x in possibilities + o = x + if formatter + x = formatter x s.setSeq1(x) if s.realQuickRatio() >= cutoff and s.quickRatio() >= cutoff and s.ratio() >= cutoff - result.push([s.ratio(), x]) + result.push([s.ratio(), o]) # Move the best scorers to head of list result = Heap.nlargest(result, n, _arrayCmp) diff --git a/test/global.coffee b/test/global.coffee index a5bb19c..09a51b9 100644 --- a/test/global.coffee +++ b/test/global.coffee @@ -32,6 +32,17 @@ test '.getCloseMatches', -> getCloseMatches('wheel', KEYWORDS).should.eql ['when', 'while'] getCloseMatches('accost', KEYWORDS).should.eql ['const'] + # format callback: + m = getCloseMatches 'appel', [ + { id: 'a', fruit: 'apple' } + { id: 'b', fruit: 'pineapple' } + { id: 'c', fruit: 'cherry' } + { id: 'd', fruit: 'mango' } + ], null, 0.5, (i) -> + i.fruit + m[0].id.should.eql 'a' + m[1].id.should.eql 'b' + test '._countLeading', -> _countLeading(' abc', ' ').should.eql 3 diff --git a/util/build.coffee b/util/build.coffee index c4c5fb0..bf9016f 100755 --- a/util/build.coffee +++ b/util/build.coffee @@ -16,8 +16,8 @@ BANNER = ''' build = (dest) -> browserified = browserify.bundle(__dirname + '/../lib/difflib.js') namespaced = 'var difflib = (function() {' + browserified + 'return require("/difflib");})();' - uglified = uglify(namespaced) - bannered = BANNER + uglified + uglified = uglify.minify({'difflib.js': namespaced}, {fromString: true}) + bannered = BANNER + uglified.code fs.writeFileSync(dest, bannered) build(__dirname + '/../dist/difflib-browser.js')