public static List<string> Generate(DiffResult diffresult) { var uniLines = new List<string>(); int bPos = 0; foreach (DiffBlock diffBlock in diffresult.DiffBlocks) { for (; bPos < diffBlock.InsertStartB; bPos++) { uniLines.Add(NoChangeSymbol + diffresult.PiecesNew[bPos]); } int i = 0; for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++) { uniLines.Add(DeleteSymbol + diffresult.PiecesOld[i + diffBlock.DeleteStartA]); uniLines.Add(InsertSymbol + diffresult.PiecesNew[i + diffBlock.InsertStartB]); bPos++; } if (diffBlock.DeleteCountA > diffBlock.InsertCountB) { for (; i < diffBlock.DeleteCountA; i++) { uniLines.Add(DeleteSymbol + diffresult.PiecesOld[i + diffBlock.DeleteStartA]); } } else { for (; i < diffBlock.InsertCountB; i++) { uniLines.Add(InsertSymbol + diffresult.PiecesNew[i + diffBlock.InsertStartB]); bPos++; } } } //***** added bugfix (thanks Wawel for pointing this out) for (; bPos < diffresult.PiecesNew.Length; bPos++) { // bugfix: uniLines.Add(diffresult.PiecesNew[bPos]); uniLines.Add(NoChangeSymbol + diffresult.PiecesNew[bPos]); } //**** end bugfix return uniLines; }
/// <summary> /// Format the result for a RichTextBox /// </summary> /// <param name="lineDiff"></param> /// <returns></returns> public static string Format(DiffResult lineDiff) { var uniLines = new StringBuilder(); int bPos = 0; foreach (var diffBlock in lineDiff.DiffBlocks) { for (; bPos < diffBlock.InsertStartB; bPos++) uniLines.Append(lineDiff.PiecesNew[bPos]); int i = 0; for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++) { uniLines.Append(DeleteSymbolS + lineDiff.PiecesOld[i + diffBlock.DeleteStartA] + DeleteSymbolE); //uniLines.Append(InsertSymbolS + lineDiff.PiecesNew[i + diffBlock.InsertStartB] + InsertSymbolE); bPos++; } if (diffBlock.DeleteCountA > diffBlock.InsertCountB) { uniLines.Append(DeleteSymbolS); for (; i < diffBlock.DeleteCountA; i++) uniLines.Append(lineDiff.PiecesOld[i + diffBlock.DeleteStartA]); uniLines.Append(DeleteSymbolE); } else { if (i < diffBlock.InsertCountB) { //uniLines.Append(InsertSymbolS); for (; i < diffBlock.InsertCountB; i++) { //uniLines.Append(lineDiff.PiecesNew[i + diffBlock.InsertStartB]); bPos++; } //uniLines.Append(InsertSymbolE); } } } for (; bPos < lineDiff.PiecesNew.Length; bPos++) uniLines.Append(lineDiff.PiecesNew[bPos]); return uniLines.ToString(); }
private static void BuildDiffPieces(DiffResult diffResult, List<DiffPiece> pieces) { int bPos = 0; foreach (var diffBlock in diffResult.DiffBlocks) { for (; bPos < diffBlock.InsertStartB; bPos++) pieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1)); int i = 0; for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++) pieces.Add(new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted)); i = 0; for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++) { pieces.Add(new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1)); bPos++; } if (diffBlock.DeleteCountA > diffBlock.InsertCountB) { for (; i < diffBlock.DeleteCountA; i++) pieces.Add(new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted)); } else { for (; i < diffBlock.InsertCountB; i++) { pieces.Add(new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1)); bPos++; } } } for (; bPos < diffResult.PiecesNew.Length; bPos++) pieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1)); }
private static void BuildDiffPieces(DiffResult diffResult, List<DiffPiece> oldPieces, List<DiffPiece> newPieces, PieceBuilder subPieceBuilder) { int aPos = 0; int bPos = 0; foreach (var diffBlock in diffResult.DiffBlocks) { while (bPos < diffBlock.InsertStartB && aPos < diffBlock.DeleteStartA) { oldPieces.Add(new DiffPiece(diffResult.PiecesOld[aPos], ChangeType.Unchanged, aPos + 1)); newPieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1)); aPos++; bPos++; } int i = 0; for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++) { var oldPiece = new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted, aPos + 1); var newPiece = new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1); if (subPieceBuilder != null) { subPieceBuilder(diffResult.PiecesOld[aPos], diffResult.PiecesNew[bPos], oldPiece.SubPieces, newPiece.SubPieces); newPiece.Type = oldPiece.Type = ChangeType.Modified; } oldPieces.Add(oldPiece); newPieces.Add(newPiece); aPos++; bPos++; } if (diffBlock.DeleteCountA > diffBlock.InsertCountB) { for (; i < diffBlock.DeleteCountA; i++) { oldPieces.Add(new DiffPiece(diffResult.PiecesOld[i + diffBlock.DeleteStartA], ChangeType.Deleted, aPos + 1)); newPieces.Add(new DiffPiece()); aPos++; } } else { for (; i < diffBlock.InsertCountB; i++) { newPieces.Add(new DiffPiece(diffResult.PiecesNew[i + diffBlock.InsertStartB], ChangeType.Inserted, bPos + 1)); oldPieces.Add(new DiffPiece()); bPos++; } } } while (bPos < diffResult.PiecesNew.Length && aPos < diffResult.PiecesOld.Length) { oldPieces.Add(new DiffPiece(diffResult.PiecesOld[aPos], ChangeType.Unchanged, aPos + 1)); newPieces.Add(new DiffPiece(diffResult.PiecesNew[bPos], ChangeType.Unchanged, bPos + 1)); aPos++; bPos++; } }
private void ProcessDiff(string original, string myVersion, string newVersion) { // Do a line-by-line diff, marking changed line groups. // Also, find intersecting diffs and mark them as conflicted changes for resolution. var d = new Differ(); var diffs = new DiffResult[2] { d.CreateLineDiffs(original, myVersion ?? "", false), d.CreateLineDiffs(original, newVersion ?? "", false) }; string[][] newPieces = new string[2][]; newPieces[0] = diffs[0].PiecesNew; newPieces[1] = diffs[1].PiecesNew; if (myVersion == "") newPieces[0] = new string[] { "" }; if (newVersion == "") newPieces[1] = new string[] { "" }; var dblocks = new List<Tuple<DiffBlock, int>>(); for (int side = 0; side < 2; side++) { foreach (var block in diffs[side].DiffBlocks) { DiffBlock actualBlock = block; if (diffs[side].PiecesNew.Length == 0 && block.InsertCountB == 0 && block.InsertStartB == 0) { actualBlock = new DiffBlock(block.DeleteStartA, block.DeleteCountA, 0, 1); } dblocks.Add(new Tuple<DiffBlock, int>(actualBlock, side)); } } dblocks.Sort((a, b) => a.Item1.DeleteStartA.CompareTo(b.Item1.DeleteStartA)); content = new List<LineBlock>[2]; for (int i = 0; i < 2; i++) { content[i] = new List<LineBlock>(); } conflictOrigBlocks = new List<LineBlock>(); string[] origLines = diffs[0].PiecesOld; int nextOriginalLine = 0; for (int i = 0; i < dblocks.Count; ) { DiffBlock block = dblocks[i].Item1; int owner = dblocks[i].Item2; // Add unchanged (original) lines. if (block.DeleteStartA > nextOriginalLine) { foreach (var lineBlocks in content) { lineBlocks.Add(new LineBlock(Util.ArraySlice(origLines, nextOriginalLine, block.DeleteStartA - nextOriginalLine))); } nextOriginalLine = block.DeleteStartA; } int rangeStart = block.DeleteStartA; int rangeEnd = rangeStart + block.DeleteCountA; int j = i; // If this change intersects any other changes, then merge them together to form a block. while (j < dblocks.Count && dblocks[j].Item1.DeleteStartA <= rangeEnd) { rangeEnd = Math.Max(rangeEnd, dblocks[j].Item1.DeleteStartA + dblocks[j].Item1.DeleteCountA); j++; } if (j == i + 1) { // A regular change. var oldBlock = new LineBlock(Util.ArraySlice(diffs[owner].PiecesOld, block.DeleteStartA, block.DeleteCountA), BlockType.ChangeDelete); var newBlock = new LineBlock(Util.ArraySlice(newPieces[owner], block.InsertStartB, block.InsertCountB), BlockType.ChangeAdd); if (block.DeleteCountA != 0 && block.InsertCountB != 0) { oldBlock.type = BlockType.Conflict; newBlock.type = BlockType.Conflict; } else if (block.DeleteCountA == 0) { oldBlock.type = BlockType.Blank; } else if (block.InsertCountB == 0) { newBlock.type = BlockType.Blank; } // can't both be empty! ProcessBlockDiff(oldBlock, newBlock); content[owner].Add(newBlock); content[1 - owner].Add(oldBlock); conflictOrigBlocks.Add(owner == 0 ? newBlock : oldBlock); } else { // Create a change block. for (int side = 0; side < 2; side++) { int curOriginalLine = rangeStart; var conflictBlock = new LineBlock(); var origBlock = new LineBlock(); conflictBlock.type = BlockType.Conflict; for (int k = i; k < j; k++) { DiffBlock subBlock = dblocks[k].Item1; if (dblocks[k].Item2 != side) continue; if (subBlock.DeleteStartA > curOriginalLine) { conflictBlock.AddLines(Util.ArraySlice(origLines, curOriginalLine, subBlock.DeleteStartA - curOriginalLine)); } curOriginalLine = subBlock.DeleteStartA + subBlock.DeleteCountA; var oldBlock = new LineBlock(Util.ArraySlice(diffs[side].PiecesOld, subBlock.DeleteStartA, subBlock.DeleteCountA), BlockType.ChangeDelete); var newBlock = new LineBlock(Util.ArraySlice(newPieces[side], subBlock.InsertStartB, subBlock.InsertCountB), BlockType.ChangeAdd); ProcessBlockDiff(oldBlock, newBlock, false); origBlock.Append(oldBlock); conflictBlock.Append(newBlock); } if (rangeEnd > curOriginalLine) { conflictBlock.AddLines(Util.ArraySlice(origLines, curOriginalLine, rangeEnd - curOriginalLine)); } if (conflictBlock.lines.Count == 0) { conflictBlock.type = BlockType.ChangeDelete; } content[side].Add(conflictBlock); if (side == 0) { conflictOrigBlocks.Add(origBlock); } } int last = content[0].Count - 1; if (content[0][last].ToString() == content[1][last].ToString()) { // Not actually a conflict if they're both the same change. if (content[0][last].lines.Count == 0) { // If both are deleted, just show nothing. content[0].RemoveAt(last); content[1].RemoveAt(last); } else { // Make them normal blocks. content[0][last] = new LineBlock(content[0][last].lines.Select(x => x.ToString()).ToArray()); content[1][last] = new LineBlock(content[1][last].lines.Select(x => x.ToString()).ToArray()); } conflictOrigBlocks.RemoveAt(conflictOrigBlocks.Count - 1); } } nextOriginalLine = rangeEnd; i = j; } // Add any remaining unchanged lines. if (origLines.Length > nextOriginalLine) { foreach (var lineBlocks in content) { lineBlocks.Add(new LineBlock(Util.ArraySlice(origLines, nextOriginalLine, origLines.Length - nextOriginalLine))); } } origBlocks = new LineBlock[2][]; origBlocks[0] = new LineBlock[content[0].Count]; origBlocks[1] = new LineBlock[content[1].Count]; content[0].CopyTo(origBlocks[0]); content[1].CopyTo(origBlocks[1]); }
public static List<UnidiffEntry> GenerateWithLineNumbers(DiffResult diffresult) { var uniLines = new List<UnidiffEntry>(); int bPos = 0; foreach (DiffBlock diffBlock in diffresult.DiffBlocks) { for (; bPos < diffBlock.InsertStartB; bPos++) { uniLines.Add(new UnidiffEntry(bPos, NoChangeSymbol + diffresult.PiecesNew[bPos], UnidiffType.NoChange)); } int i = 0; for (; i < Math.Min(diffBlock.DeleteCountA, diffBlock.InsertCountB); i++) { uniLines.Add(new UnidiffEntry(bPos, DeleteSymbol + diffresult.PiecesOld[i + diffBlock.DeleteStartA], UnidiffType.Delete)); uniLines.Add(new UnidiffEntry(bPos, InsertSymbol + diffresult.PiecesNew[i + diffBlock.InsertStartB], UnidiffType.Insert)); bPos++; } if (diffBlock.DeleteCountA > diffBlock.InsertCountB) { for (; i < diffBlock.DeleteCountA; i++) { uniLines.Add(new UnidiffEntry(bPos, DeleteSymbol + diffresult.PiecesOld[i + diffBlock.DeleteStartA], UnidiffType.Delete)); } } else { for (; i < diffBlock.InsertCountB; i++) { uniLines.Add(new UnidiffEntry(bPos, InsertSymbol + diffresult.PiecesNew[i + diffBlock.InsertStartB], UnidiffType.Insert)); bPos++; } } } //***** added bugfix (thanks Wawel for pointing this out) for (; bPos < diffresult.PiecesNew.Length; bPos++) { // bugfix: uniLines.Add(diffresult.PiecesNew[bPos]); uniLines.Add(new UnidiffEntry(bPos, NoChangeSymbol + diffresult.PiecesNew[bPos], UnidiffType.NoChange)); } //**** end bugfix return uniLines; }
public static string GenerateSeq(DiffResult diffresult, string insertSymbolS, string insertSymbolE, string deleteSymbolS, string deleteSymbolE) { List<string> result = Generate(diffresult); var outputSb = new StringBuilder(); while (result.Count > 0) { if (result[0].StartsWith(DeleteSymbol)) { int dix = 0; outputSb.Append(deleteSymbolS); while (dix < result.Count && result.Count > 0 && !result[dix].StartsWith(NoChangeSymbol)) { if (result[dix].StartsWith(DeleteSymbol)) { outputSb.Append(result[dix].Substring(1)); result.RemoveAt(dix); } else { ++dix; } } outputSb.Append(deleteSymbolE); } else if (result[0].StartsWith(InsertSymbol)) { int dix = 0; outputSb.Append(insertSymbolS); while (dix < result.Count && result.Count > 0 && !result[dix].StartsWith(NoChangeSymbol)) { if (result[dix].StartsWith(InsertSymbol)) { outputSb.Append(result[dix].Substring(1)); result.RemoveAt(dix); } else { ++dix; } } outputSb.Append(insertSymbolE); } else { outputSb.Append(result[0].Substring(1)); result.RemoveAt(0); } } return outputSb.ToString(); }
public static string GenerateSeq(DiffResult diffresult) { return GenerateSeq(diffresult, "[+[", "]+]", "[-[", "]-]"); }
public static string GenerateOnlyChangedSeq(DiffResult diffresult, string insertSymbolS, string insertSymbolE, string deleteSymbolS, string deleteSymbolE) { List<UnidiffEntry> result = GenerateWithLineNumbers(diffresult); var outputSb = new StringBuilder(); while (result.Count > 0) { if (result[0].Type == UnidiffType.Delete) { int dix = 0; outputSb.Append(deleteSymbolS); while (dix < result.Count && result.Count > 0 && result[dix].Type != UnidiffType.NoChange) { if (result[dix].Type == UnidiffType.Delete) { outputSb.Append(result[dix].Index + ":"); outputSb.Append(result[dix].Text.Substring(1)); result.RemoveAt(dix); } else { ++dix; } } outputSb.Append(deleteSymbolE); } else if (result[0].Type == UnidiffType.Insert) { int dix = 0; outputSb.Append(insertSymbolS); while (dix < result.Count && result.Count > 0 && result[dix].Type != UnidiffType.NoChange) { if (result[dix].Type == UnidiffType.Insert) { outputSb.Append(result[dix].Index + ":"); outputSb.Append(result[dix].Text.Substring(1)); result.RemoveAt(dix); } else { ++dix; } } outputSb.Append(insertSymbolE); } else { //outputSb.Append(result[0].Index); //outputSb.Append(result[0].Text.Substring(1)); result.RemoveAt(0); } } return outputSb.ToString(); }