patch_make method

List<Patch> patch_make(
  1. String text1,
  2. List<Diff> diffs
)

Compute a list of patches to turn text1 into text2.

Implementation

List<Patch> patch_make(String text1, List<Diff> diffs) {
  // Method 3: text1, diffs
  final patches = <Patch>[];
  if (diffs.isEmpty) {
    return patches; // Get rid of the null case.
  }
  var patch = Patch();
  int char_count1 = 0; // Number of characters into the text1 string.
  int char_count2 = 0; // Number of characters into the text2 string.
  // Start with text1 (prepatch_text) and apply the diffs until we arrive at
  // text2 (postpatch_text). We recreate the patches one by one to determine
  // context info.
  String prepatch_text = text1;
  String postpatch_text = text1;
  for (final aDiff in diffs) {
    if (patch.diffs.isEmpty && aDiff.operation != Operation.equal) {
      // A new patch starts here.
      patch.start1 = char_count1;
      patch.start2 = char_count2;
    }

    switch (aDiff.operation) {
      case Operation.insert:
        patch.diffs.add(aDiff);
        patch.length2 += aDiff.text.length;
        postpatch_text = postpatch_text.substring(0, char_count2) +
            aDiff.text +
            postpatch_text.substring(char_count2);
        break;
      case Operation.delete:
        patch.length1 += aDiff.text.length;
        patch.diffs.add(aDiff);
        postpatch_text = postpatch_text.substring(0, char_count2) +
            postpatch_text.substring(char_count2 + aDiff.text.length);
        break;
      case Operation.equal:
        if (aDiff.text.length <= 2 * Patch_Margin &&
            patch.diffs.isNotEmpty &&
            aDiff != diffs.last) {
          // Small equality inside a patch.
          patch.diffs.add(aDiff);
          patch.length1 += aDiff.text.length;
          patch.length2 += aDiff.text.length;
        }

        if (aDiff.text.length >= 2 * Patch_Margin) {
          // Time for a new patch.
          if (patch.diffs.isNotEmpty) {
            _patch_addContext(patch, prepatch_text);
            patches.add(patch);
            patch = Patch();
            // Unlike Unidiff, our patch lists have a rolling context.
            // https://github.com/google/diff-match-patch/wiki/Unidiff
            // Update prepatch text & pos to reflect the application of the
            // just completed patch.
            prepatch_text = postpatch_text;
            char_count1 = char_count2;
          }
        }
        break;
    }

    // Update the current character count.
    if (aDiff.operation != Operation.insert) {
      char_count1 += aDiff.text.length;
    }
    if (aDiff.operation != Operation.delete) {
      char_count2 += aDiff.text.length;
    }
  }
  // Pick up the leftover patch if not empty.
  if (patch.diffs.isNotEmpty) {
    _patch_addContext(patch, prepatch_text);
    patches.add(patch);
  }

  return patches;
}