Merge adjacent operations of the same type and convert delete+insert to replace.
(ops: Vec<WordDiffOp>)
| 709 | |
| 710 | /// Merge adjacent operations of the same type and convert delete+insert to replace. |
| 711 | fn merge_operations(ops: Vec<WordDiffOp>) -> Vec<WordDiffOp> { |
| 712 | if ops.is_empty() { |
| 713 | return ops; |
| 714 | } |
| 715 | |
| 716 | let mut merged: Vec<WordDiffOp> = Vec::with_capacity(ops.len()); |
| 717 | |
| 718 | for op in ops { |
| 719 | if merged.is_empty() { |
| 720 | merged.push(op); |
| 721 | continue; |
| 722 | } |
| 723 | |
| 724 | let last = merged.last_mut().unwrap(); |
| 725 | |
| 726 | // Try to merge with the previous operation |
| 727 | match (&last, &op) { |
| 728 | // Merge adjacent Equals |
| 729 | ( |
| 730 | WordDiffOp::Equal { |
| 731 | old_range: old1, |
| 732 | new_range: new1, |
| 733 | }, |
| 734 | WordDiffOp::Equal { |
| 735 | old_range: old2, |
| 736 | new_range: new2, |
| 737 | }, |
| 738 | ) if old1.end == old2.start && new1.end == new2.start => { |
| 739 | *last = WordDiffOp::Equal { |
| 740 | old_range: old1.start..old2.end, |
| 741 | new_range: new1.start..new2.end, |
| 742 | }; |
| 743 | } |
| 744 | |
| 745 | // Merge adjacent Inserts |
| 746 | ( |
| 747 | WordDiffOp::Insert { |
| 748 | old_pos: pos1, |
| 749 | new_range: range1, |
| 750 | }, |
| 751 | WordDiffOp::Insert { |
| 752 | old_pos: pos2, |
| 753 | new_range: range2, |
| 754 | }, |
| 755 | ) if pos1 == pos2 && range1.end == range2.start => { |
| 756 | *last = WordDiffOp::Insert { |
| 757 | old_pos: *pos1, |
| 758 | new_range: range1.start..range2.end, |
| 759 | }; |
| 760 | } |
| 761 | |
| 762 | // Merge adjacent Deletes |
| 763 | ( |
| 764 | WordDiffOp::Delete { |
| 765 | old_range: range1, |
| 766 | new_pos: pos1, |
| 767 | }, |
| 768 | WordDiffOp::Delete { |