private static RdTextChange CreateTextChange(int offset, [CanBeNull] InsertText insert, [CanBeNull] DeleteText delete, int documentLength) { var newText = insert?.Text ?? ""; var oldText = delete?.Text ?? ""; var startOffset = offset - (insert?.GetTextLengthAfter() ?? 0); RdTextChangeKind kind; if (insert != null && delete != null) { kind = RdTextChangeKind.Replace; } else if (insert != null) { kind = RdTextChangeKind.Insert; } else if (delete != null) { kind = RdTextChangeKind.Remove; } else { throw new ArgumentOutOfRangeException(); } return(new RdTextChange(kind, startOffset, oldText, newText, documentLength)); }
private static IEnumerable <OtChange> Normalize(IEnumerable <OtChange> changes) { var result = new List <OtChange>(); OtChange prev = null; foreach (var curr in changes) { if (curr.IsId()) { continue; } if (prev is Retain && curr is Retain) { prev = new Retain(((Retain)prev).Offset + ((Retain)curr).Offset); } else if (prev is InsertText && curr is InsertText) { prev = new InsertText(((InsertText)prev).Text + ((InsertText)curr).Text); } else if (prev is DeleteText && curr is DeleteText) { prev = new DeleteText(((DeleteText)prev).Text + ((DeleteText)curr).Text); } else { if (prev != null) { result.Add(prev); } prev = curr; } } if (prev != null) { result.Add(prev); } if (result.Count == 0) { result.Add(new Retain(0)); } return(result); }
public static List <RdTextChange> ToRdTextChanges(this OtOperation op) { var documentLength = op.DocumentLengthBefore(); var currOffset = 0; InsertText lastInsert = null; DeleteText lastDelete = null; var res = new List <RdTextChange>(); foreach (var change in op.Changes) { switch (change) { case Retain _: { if (lastDelete != null || lastInsert != null) { res.Add(CreateTextChange(currOffset, lastInsert, lastDelete, documentLength)); lastDelete = null; lastInsert = null; } break; } case InsertText i: { if (lastInsert != null) { res.Add(CreateTextChange(currOffset, lastInsert, lastDelete, documentLength)); lastDelete = null; } documentLength += change.GetTextLengthAfter(); lastInsert = i; break; } case DeleteText d: { if (lastDelete != null) { res.Add(CreateTextChange(currOffset, lastInsert, lastDelete, documentLength)); lastInsert = null; } documentLength -= change.GetTextLengthBefore(); lastDelete = d; break; } } currOffset += change.GetTextLengthAfter(); } if (lastDelete != null || lastInsert != null) { res.Add(CreateTextChange(currOffset, lastInsert, lastDelete, documentLength)); } return(res); }