diff --git a/addon/merge/merge.js b/addon/merge/merge.js index d83bfb63b700675edbd7eadf8b54f519fe731598..81cc95471a7d1ae02a108f2dfc4f997dedd8341b 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -446,8 +446,6 @@ this.options = options; var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight; - if (origLeft && origRight && options.collapseIdentical) - throw new Error("collapseIdentical option is not supported for three-way merge views"); var hasLeft = origLeft != null, hasRight = origRight != null; var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0); @@ -481,7 +479,7 @@ if (right) right.init(rightPane, origRight, options); if (options.collapseIdentical) - collapseIdenticalStretches(left || right, options.collapseIdentical); + collapseIdenticalStretches(this, options.collapseIdentical); if (options.connect == "align") { this.aligners = []; alignChunks(this.left || this.right, true); @@ -648,26 +646,48 @@ return {mark: mark, clear: clear}; } - function collapseStretch(dv, origStart, editStart, size) { - var mOrig = collapseSingle(dv.orig, origStart, origStart + size); - var mEdit = collapseSingle(dv.edit, editStart, editStart + size); - mOrig.mark.on("clear", function() { mEdit.clear(); }); - mEdit.mark.on("clear", function() { mOrig.clear(); }); + function collapseStretch(size, editors) { + var marks = []; + function clear() { + for (var i = 0; i < marks.length; i++) marks[i].clear(); + } + for (var i = 0; i < editors.length; i++) { + var editor = editors[i]; + var mark = collapseSingle(editor.cm, editor.line, editor.line + size); + marks.push(mark); + mark.mark.on("clear", clear); + } } - function collapseIdenticalStretches(dv, margin) { - if (typeof margin != "number") margin = 2; - var lastOrig = dv.orig.firstLine(), lastEdit = dv.edit.firstLine(); + function unclearNearChunks(dv, margin, off, clear) { for (var i = 0; i < dv.chunks.length; i++) { var chunk = dv.chunks[i]; - var identicalSize = chunk.origFrom - margin - lastOrig; - if (identicalSize > margin) - collapseStretch(dv, lastOrig, lastEdit, identicalSize); - lastOrig = chunk.origTo + margin; lastEdit = chunk.editTo + margin; - } - var bottomSize = dv.orig.lastLine() + 1 - lastOrig; - if (bottomSize > margin) - collapseStretch(dv, lastOrig, lastEdit, bottomSize); + for (var l = chunk.editFrom - margin; l < chunk.editTo + margin; l++) { + var pos = l + off; + if (pos >= 0 && pos < clear.length) clear[pos] = false; + } + } + } + + function collapseIdenticalStretches(mv, margin) { + if (typeof margin != "number") margin = 2; + var clear = [], edit = (mv.left || mv.right).edit, off = edit.firstLine(); + for (var l = off, e = edit.lastLine(); l <= e; l++) clear.push(true); + if (mv.left) unclearNearChunks(mv.left, margin, off, clear); + if (mv.right) unclearNearChunks(mv.right, margin, off, clear); + + for (var i = 0; i < clear.length; i++) { + if (clear[i]) { + var line = i + off; + for (var size = 1; i < clear.length - 1 && clear[i + 1]; i++, size++) {} + if (size > margin) { + var editors = [{line: line, cm: edit}]; + if (mv.left) editors.push({line: getMatchingOrigLine(line, mv.left.chunks), cm: mv.left.orig}); + if (mv.right) editors.push({line: getMatchingOrigLine(line, mv.right.chunks), cm: mv.right.orig}); + collapseStretch(size, editors); + } + } + } } // General utilities