Print prints the edits in the unified diff format without the header. Ref: https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html
(from, to [][]byte, edits []Edit)
| 57 | // |
| 58 | // Ref: https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html |
| 59 | func Print(from, to [][]byte, edits []Edit) ([]byte, error) { |
| 60 | const contextThreshold = 2 |
| 61 | type printLine struct { |
| 62 | EditKind EditKind |
| 63 | line []byte |
| 64 | hunk bool |
| 65 | } |
| 66 | // If the last line of from is not a newline append one. |
| 67 | if len(from) > 0 && from[len(from)-1] != nil { |
| 68 | last := from[len(from)-1] |
| 69 | if last[len(last)-1] != '\n' { |
| 70 | from[len(from)-1] = append(last, '\n') |
| 71 | } |
| 72 | } |
| 73 | // We preallocate the slice to avoid reallocations. |
| 74 | // |
| 75 | // Each edit is either a delete or an insert so the total number of lines |
| 76 | // in the diff is the number of edits plus the number of lines in the |
| 77 | // original sequence. The worst case for the hunk headers are |
| 78 | // as many edits. |
| 79 | out := make([]*printLine, 0, len(from)+2*len(edits)) |
| 80 | var fromIndex, toIndex, bufferSize int |
| 81 | for i := 0; i < len(edits); i++ { |
| 82 | // Remember the start of the hunk. We add 1 to the indexes because |
| 83 | // we want to print the line number and they start at 1. |
| 84 | hunkOldStart := fromIndex + 1 |
| 85 | hunkNewStart := toIndex + 1 |
| 86 | // Reserve the space for the hunk header. |
| 87 | hunk := &printLine{hunk: true} |
| 88 | out = append(out, hunk) |
| 89 | var ( |
| 90 | insertCount, deleteCount int |
| 91 | printHunk bool |
| 92 | ) |
| 93 | // Print the lines in the edit. |
| 94 | for j := i; j < len(edits); j++ { |
| 95 | // Print the lines before the edit. |
| 96 | var advance int |
| 97 | for _, line := range from[fromIndex:edits[i].FromPosition] { |
| 98 | out = append(out, &printLine{line: line}) |
| 99 | bufferSize += len(line) + 1 |
| 100 | advance++ |
| 101 | } |
| 102 | // Advance the indexes. |
| 103 | toIndex += advance |
| 104 | fromIndex += advance |
| 105 | insertCount += advance |
| 106 | deleteCount += advance |
| 107 | if advance > contextThreshold { |
| 108 | i-- |
| 109 | break |
| 110 | } |
| 111 | printHunk = true |
| 112 | switch edits[j].Kind { |
| 113 | case EditKindDelete: |
| 114 | deleteCount++ |
| 115 | fromIndex++ |
| 116 | out = append(out, &printLine{ |