src/main/java/com/sksamuel/diffpatch/DiffMatchPatch.java
public void diff_cleanupSemanticLossless(LinkedList<Diff> diffs) {
    String equality1, edit, equality2;
    String commonString;
    int commonOffset;
    int score, bestScore;
    String bestEquality1, bestEdit, bestEquality2;
    // Create a new iterator at the start.
    ListIterator<Diff> pointer = diffs.listIterator();
    Diff prevDiff = pointer.hasNext() ? pointer.next() : null;
    Diff thisDiff = pointer.hasNext() ? pointer.next() : null;
    Diff nextDiff = pointer.hasNext() ? pointer.next() : null;
    // Intentionally ignore the first and last element (don't need checking).
    while (nextDiff != null) {
      if (prevDiff.operation == Operation.EQUAL &&
          nextDiff.operation == Operation.EQUAL) {
        // This is a single edit surrounded by equalities.
        equality1 = prevDiff.text;
        edit = thisDiff.text;
        equality2 = nextDiff.text;

        // First, shift the edit as far left as possible.
        commonOffset = diff_commonSuffix(equality1, edit);
        if (commonOffset != 0) {
          commonString = edit.substring(edit.length() - commonOffset);
          equality1 = equality1.substring(0, equality1.length() - commonOffset);
          edit = commonString + edit.substring(0, edit.length() - commonOffset);
          equality2 = commonString + equality2;
        }

        // Second, step character by character right, looking for the best fit.
        bestEquality1 = equality1;
        bestEdit = edit;
        bestEquality2 = equality2;
        bestScore = diff_cleanupSemanticScore(equality1, edit)
            + diff_cleanupSemanticScore(edit, equality2);
        while (edit.length() != 0 && equality2.length() != 0
            && edit.charAt(0) == equality2.charAt(0)) {
          equality1 += edit.charAt(0);
          edit = edit.substring(1) + equality2.charAt(0);
          equality2 = equality2.substring(1);
          score = diff_cleanupSemanticScore(equality1, edit)
              + diff_cleanupSemanticScore(edit, equality2);
          // The >= encourages trailing rather than leading whitespace on edits.
          if (score >= bestScore) {
            bestScore = score;
            bestEquality1 = equality1;
            bestEdit = edit;
            bestEquality2 = equality2;
          }
        }

        if (!prevDiff.text.equals(bestEquality1)) {
          // We have an improvement, save it back to the diff.
          if (bestEquality1.length() != 0) {
            prevDiff.text = bestEquality1;
          } else {
            pointer.previous(); // Walk past nextDiff.
            pointer.previous(); // Walk past thisDiff.
            pointer.previous(); // Walk past prevDiff.
            pointer.remove(); // Delete prevDiff.
            pointer.next(); // Walk past thisDiff.
            pointer.next(); // Walk past nextDiff.
          }
          thisDiff.text = bestEdit;
          if (bestEquality2.length() != 0) {
            nextDiff.text = bestEquality2;
          } else {
            pointer.remove(); // Delete nextDiff.
            nextDiff = thisDiff;
            thisDiff = prevDiff;
          }
        }
      }
      prevDiff = thisDiff;
      thisDiff = nextDiff;
      nextDiff = pointer.hasNext() ? pointer.next() : null;
    }
  }
public void diff_cleanupSemanticLossless(LinkedList<Diff> diffs) {
    String equality1, edit, equality2;
    String commonString;
    int commonOffset;
    int score, bestScore;
    String bestEquality1, bestEdit, bestEquality2;
    // Create a new iterator at the start.
    ListIterator<Diff> pointer = diffs.listIterator();
    Diff prevDiff = pointer.hasNext() ? pointer.next() : null;
    Diff thisDiff = pointer.hasNext() ? pointer.next() : null;
    Diff nextDiff = pointer.hasNext() ? pointer.next() : null;
    // Intentionally ignore the first and last element (don't need checking).
    while (nextDiff != null) {
      if (prevDiff.operation == Operation.EQUAL &&
          nextDiff.operation == Operation.EQUAL) {
        // This is a single edit surrounded by equalities.
        equality1 = prevDiff.text;
        edit = thisDiff.text;
        equality2 = nextDiff.text;

        // First, shift the edit as far left as possible.
        commonOffset = diff_commonSuffix(equality1, edit);
        if (commonOffset != 0) {
          commonString = edit.substring(edit.length() - commonOffset);
          equality1 = equality1.substring(0, equality1.length() - commonOffset);
          edit = commonString + edit.substring(0, edit.length() - commonOffset);
          equality2 = commonString + equality2;
        }

        // Second, step character by character right, looking for the best fit.
        bestEquality1 = equality1;
        bestEdit = edit;
        bestEquality2 = equality2;
        bestScore = diff_cleanupSemanticScore(equality1, edit)
            + diff_cleanupSemanticScore(edit, equality2);
        while (edit.length() != 0 && equality2.length() != 0
            && edit.charAt(0) == equality2.charAt(0)) {
          equality1 += edit.charAt(0);
          edit = edit.substring(1) + equality2.charAt(0);
          equality2 = equality2.substring(1);
          score = diff_cleanupSemanticScore(equality1, edit)
              + diff_cleanupSemanticScore(edit, equality2);
          // The >= encourages trailing rather than leading whitespace on edits.
          if (score >= bestScore) {
            bestScore = score;
            bestEquality1 = equality1;
            bestEdit = edit;
            bestEquality2 = equality2;
          }
        }

        if (!prevDiff.text.equals(bestEquality1)) {
          // We have an improvement, save it back to the diff.
          if (bestEquality1.length() != 0) {
            prevDiff.text = bestEquality1;
          } else {
            pointer.previous(); // Walk past nextDiff.
            pointer.previous(); // Walk past thisDiff.
            pointer.previous(); // Walk past prevDiff.
            pointer.remove(); // Delete prevDiff.
            pointer.next(); // Walk past thisDiff.
            pointer.next(); // Walk past nextDiff.
          }
          thisDiff.text = bestEdit;
          if (bestEquality2.length() != 0) {
            nextDiff.text = bestEquality2;
          } else {
            pointer.remove(); // Delete nextDiff.
            nextDiff = thisDiff;
            thisDiff = prevDiff;
          }
        }
      }
      prevDiff = thisDiff;
      thisDiff = nextDiff;
      nextDiff = pointer.hasNext() ? pointer.next() : null;
    }
  }
public void diff_cleanupSemanticLossless ( LinkedList < Diff > diffs ) { String equality1 , edit , equality2 ; String commonString ; int commonOffset ; int score , bestScore ; String bestEquality1 , bestEdit , bestEquality2 ; // Create a new iterator at the start. ListIterator < Diff > pointer = diffs . listIterator ( ) ; Diff prevDiff = pointer . hasNext ( ) ? pointer . next ( ) : null ; Diff thisDiff = pointer . hasNext ( ) ? pointer . next ( ) : null ; Diff nextDiff = pointer . hasNext ( ) ? pointer . next ( ) : null ; // Intentionally ignore the first and last element (don't need checking). while ( nextDiff != null ) { if ( prevDiff . operation == Operation . EQUAL && nextDiff . operation == Operation . EQUAL ) { // This is a single edit surrounded by equalities. equality1 = prevDiff . text ; edit = thisDiff . text ; equality2 = nextDiff . text ; // First, shift the edit as far left as possible. commonOffset = diff_commonSuffix ( equality1 , edit ) ; if ( commonOffset != 0 ) { commonString = edit . substring ( edit . length ( ) - commonOffset ) ; equality1 = equality1 . substring ( 0 , equality1 . length ( ) - commonOffset ) ; edit = commonString + edit . substring ( 0 , edit . length ( ) - commonOffset ) ; equality2 = commonString + equality2 ; } // Second, step character by character right, looking for the best fit. bestEquality1 = equality1 ; bestEdit = edit ; bestEquality2 = equality2 ; bestScore = diff_cleanupSemanticScore ( equality1 , edit ) + diff_cleanupSemanticScore ( edit , equality2 ) ; while ( edit . length ( ) != 0 && equality2 . length ( ) != 0 && edit . charAt ( 0 ) == equality2 . charAt ( 0 ) ) { equality1 += edit . charAt ( 0 ) ; edit = edit . substring ( 1 ) + equality2 . charAt ( 0 ) ; equality2 = equality2 . substring ( 1 ) ; score = diff_cleanupSemanticScore ( equality1 , edit ) + diff_cleanupSemanticScore ( edit , equality2 ) ; // The >= encourages trailing rather than leading whitespace on edits. if ( score >= bestScore ) { bestScore = score ; bestEquality1 = equality1 ; bestEdit = edit ; bestEquality2 = equality2 ; } } if ( ! prevDiff . text . equals ( bestEquality1 ) ) { // We have an improvement, save it back to the diff. if ( bestEquality1 . length ( ) != 0 ) { prevDiff . text = bestEquality1 ; } else { pointer . previous ( ) ; // Walk past nextDiff. pointer . previous ( ) ; // Walk past thisDiff. pointer . previous ( ) ; // Walk past prevDiff. pointer . remove ( ) ; // Delete prevDiff. pointer . next ( ) ; // Walk past thisDiff. pointer . next ( ) ; // Walk past nextDiff. } thisDiff . text = bestEdit ; if ( bestEquality2 . length ( ) != 0 ) { nextDiff . text = bestEquality2 ; } else { pointer . remove ( ) ; // Delete nextDiff. nextDiff = thisDiff ; thisDiff = prevDiff ; } } } prevDiff = thisDiff ; thisDiff = nextDiff ; nextDiff = pointer . hasNext ( ) ? pointer . next ( ) : null ; } }
Look for single edits surrounded on both sides by equalities
which can be shifted sideways to align the edit to a word boundary.
e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.
@param diffs LinkedList of Diff objects.
Look for single edits surrounded on both sides by equalities which can be shifted sideways to align the edit to a word boundary . e . g : The c<ins > at c< / ins > ame . - > The <ins > cat < / ins > came .