Skip to content

Commit ef5c1d3

Browse files
committed
by word inline diff changes
1 parent e3924b0 commit ef5c1d3

File tree

2 files changed

+85
-26
lines changed

2 files changed

+85
-26
lines changed

src/main/java/difflib/text/DiffRowGenerator.java

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import difflib.patch.Patch;
3131
import difflib.text.DiffRow.Tag;
3232
import java.util.*;
33+
import java.util.regex.Matcher;
34+
import java.util.regex.Pattern;
3335

3436
/**
3537
* This class for generating DiffRows for side-by-sidy view. You can customize the way of
@@ -54,9 +56,10 @@ public class DiffRowGenerator {
5456
private final String inlineNewTag;
5557
private final String inlineOldCssClass;
5658
private final String inlineNewCssClass;
59+
private final boolean inlineDiffByWord;
5760
private final int columnWidth;
5861
private final Equalizer<String> equalizer;
59-
private final boolean mergeInline;
62+
private final boolean mergeOriginalRevised;
6063

6164
/**
6265
* This class used for building the DiffRowGenerator.
@@ -73,7 +76,8 @@ public static class Builder {
7376
private String inlineOldCssClass = "editOldInline";
7477
private String inlineNewCssClass = "editNewInline";
7578
private int columnWidth = 80;
76-
private boolean mergeInline = false;
79+
private boolean mergeOriginalRevised = false;
80+
private boolean inlineDiffByWord = false;
7781

7882
private Builder() {
7983
}
@@ -166,11 +170,25 @@ public DiffRowGenerator build() {
166170
return new DiffRowGenerator(this);
167171
}
168172

169-
public Builder mergeInline(boolean mergeInline) {
170-
this.mergeInline = mergeInline;
173+
/**
174+
* Merge the complete result within the original text. This makes sense for one line
175+
* display.
176+
* @param mergeOriginalRevised
177+
* @return
178+
*/
179+
public Builder mergeOriginalRevised(boolean mergeOriginalRevised) {
180+
this.mergeOriginalRevised = mergeOriginalRevised;
181+
return this;
182+
}
183+
184+
/**
185+
* Per default each character is separatly processed. This variant introduces processing
186+
* by word, which should deliver no in word changes.
187+
*/
188+
public Builder inlineDiffByWord(boolean inlineDiffByWord) {
189+
this.inlineDiffByWord = inlineDiffByWord;
171190
return this;
172191
}
173-
174192
}
175193

176194
public static Builder create() {
@@ -185,7 +203,8 @@ private DiffRowGenerator(Builder builder) {
185203
inlineOldCssClass = builder.inlineOldCssClass;
186204
inlineNewCssClass = builder.inlineNewCssClass;
187205
columnWidth = builder.columnWidth;
188-
mergeInline = builder.mergeInline;
206+
mergeOriginalRevised = builder.mergeOriginalRevised;
207+
inlineDiffByWord = builder.inlineDiffByWord;
189208
equalizer = new Equalizer<String>() {
190209
@Override
191210
public boolean equals(String original, String revised) {
@@ -212,11 +231,11 @@ public List<DiffRow> generateDiffRows(List<String> original, List<String> revise
212231

213232
private DiffRow buildDiffRow(Tag type, String orgline, String newline) {
214233
String wrapOrg = StringUtils.wrapText(StringUtils.normalize(orgline), columnWidth);
215-
if (showInlineDiffs && Tag.DELETE == type) {
234+
if (mergeOriginalRevised && Tag.DELETE == type) {
216235
wrapOrg = createOpenTag(inlineOldTag, inlineOldCssClass) + wrapOrg + createCloseTag(inlineOldTag);
217236
}
218237
String wrapNew = StringUtils.wrapText(StringUtils.normalize(newline), columnWidth);
219-
if (showInlineDiffs && Tag.INSERT == type) {
238+
if (mergeOriginalRevised && Tag.INSERT == type) {
220239
wrapOrg = createOpenTag(inlineNewTag, inlineNewCssClass) + wrapNew + createCloseTag(inlineNewTag);
221240
}
222241
return new DiffRow(type, wrapOrg, wrapNew);
@@ -295,14 +314,23 @@ public List<DiffRow> generateDiffRows(final List<String> original, Patch<String>
295314
private List<DiffRow> generateInlineDiffs(Delta<String> delta) throws DiffException {
296315
List<String> orig = StringUtils.normalize(delta.getOriginal().getLines());
297316
List<String> rev = StringUtils.normalize(delta.getRevised().getLines());
298-
LinkedList<String> origList = new LinkedList<>();
299-
for (Character character : String.join("\n", orig).toCharArray()) {
300-
origList.add(character.toString());
301-
}
302-
LinkedList<String> revList = new LinkedList<>();
303-
for (Character character : String.join("\n", rev).toCharArray()) {
304-
revList.add(character.toString());
317+
List<String> origList;
318+
List<String> revList;
319+
320+
if (inlineDiffByWord) {
321+
origList = splitStringPreserveDelimiter(String.join("\n", orig));
322+
revList = splitStringPreserveDelimiter(String.join("\n", rev));
323+
} else {
324+
origList = new LinkedList<>();
325+
revList = new LinkedList<>();
326+
for (Character character : String.join("\n", orig).toCharArray()) {
327+
origList.add(character.toString());
328+
}
329+
for (Character character : String.join("\n", rev).toCharArray()) {
330+
revList.add(character.toString());
331+
}
305332
}
333+
306334
List<Delta<String>> inlineDeltas = DiffUtils.diff(origList, revList).getDeltas();
307335

308336
Collections.reverse(inlineDeltas);
@@ -314,7 +342,7 @@ private List<DiffRow> generateInlineDiffs(Delta<String> delta) throws DiffExcept
314342
.getPosition()
315343
+ inlineOrig.size() + 1, this.inlineOldTag, this.inlineOldCssClass);
316344
} else if (inlineDelta instanceof InsertDelta) {
317-
if (mergeInline) {
345+
if (mergeOriginalRevised) {
318346
origList.addAll(inlineOrig.getPosition(),
319347
revList.subList(inlineRev.getPosition(), inlineRev.getPosition()
320348
+ inlineRev.size()));
@@ -325,11 +353,11 @@ private List<DiffRow> generateInlineDiffs(Delta<String> delta) throws DiffExcept
325353
+ inlineRev.size() + 1, this.inlineNewTag, this.inlineNewCssClass);
326354
}
327355
} else if (inlineDelta instanceof ChangeDelta) {
328-
if (mergeInline) {
329-
origList.addAll(inlineOrig.getPosition(),
356+
if (mergeOriginalRevised) {
357+
origList.addAll(inlineOrig.getPosition() + inlineOrig.size(),
330358
revList.subList(inlineRev.getPosition(), inlineRev.getPosition()
331359
+ inlineRev.size()));
332-
wrapInTag(origList, inlineOrig.getPosition(), inlineOrig.getPosition()
360+
wrapInTag(origList, inlineOrig.getPosition() + inlineOrig.size(), inlineOrig.getPosition() + inlineOrig.size()
333361
+ inlineRev.size() + 1, this.inlineNewTag, this.inlineNewCssClass);
334362
} else {
335363
wrapInTag(revList, inlineRev.getPosition(), inlineRev.getPosition()
@@ -370,7 +398,7 @@ private List<DiffRow> generateInlineDiffs(Delta<String> delta) throws DiffExcept
370398
* @param tag the tag name without angle brackets, just a word
371399
* @param cssClass the optional css class
372400
*/
373-
public static void wrapInTag(LinkedList<String> sequence, int startPosition,
401+
public static void wrapInTag(List<String> sequence, int startPosition,
374402
int endPosition, String tag, String cssClass) {
375403
sequence.add(startPosition, createOpenTag(tag, cssClass));
376404
sequence.add(endPosition, createCloseTag(tag));
@@ -383,4 +411,21 @@ private static String createCloseTag(String tag) {
383411
private static String createOpenTag(String tag, String cssClass) {
384412
return "<" + tag + (cssClass != null ? " class=\"" + cssClass + "\"" : "") + ">";
385413
}
414+
415+
private static final Pattern SPLIT_PATTERN = Pattern.compile("\\s+");
416+
417+
private List<String> splitStringPreserveDelimiter(String str) {
418+
List<String> list = new ArrayList<>();
419+
if (str != null) {
420+
Matcher matcher = SPLIT_PATTERN.matcher(str);
421+
int pos = 0;
422+
while (matcher.find()) {
423+
list.add(str.substring(pos, matcher.start()));
424+
list.add(matcher.group());
425+
pos = matcher.end();
426+
}
427+
list.add(str.substring(pos));
428+
}
429+
return list;
430+
}
386431
}

src/test/java/difflib/text/DiffRowGeneratorTest.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ public void testGeneratorWithWordWrap() throws DiffException {
8888
}
8989

9090
@Test
91-
public void testGeneratorWithInlineMerge() throws DiffException {
91+
public void testGeneratorWithMerge() throws DiffException {
9292
String first = "anything \n \nother";
9393
String second = "anything\n\nother";
9494

9595
DiffRowGenerator generator = DiffRowGenerator.create()
9696
.showInlineDiffs(true)
97-
.mergeInline(true)
97+
.mergeOriginalRevised(true)
9898
.build();
9999
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
100100
print(rows);
@@ -106,10 +106,10 @@ public void testGeneratorWithInlineMerge() throws DiffException {
106106
}
107107

108108
@Test
109-
public void testGeneratorWithInlineMerge2() throws DiffException {
109+
public void testGeneratorWithMerge2() throws DiffException {
110110
DiffRowGenerator generator = DiffRowGenerator.create()
111111
.showInlineDiffs(true)
112-
.mergeInline(true)
112+
.mergeOriginalRevised(true)
113113
.build();
114114
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("Test"),Arrays.asList("ester"));
115115
print(rows);
@@ -119,13 +119,13 @@ public void testGeneratorWithInlineMerge2() throws DiffException {
119119
}
120120

121121
@Test
122-
public void testGeneratorWithInlineMerge3() throws DiffException {
122+
public void testGeneratorWithMerge3() throws DiffException {
123123
String first = "test\nanything \n \nother";
124124
String second = "anything\n\nother\ntest\ntest2";
125125

126126
DiffRowGenerator generator = DiffRowGenerator.create()
127127
.showInlineDiffs(true)
128-
.mergeInline(true)
128+
.mergeOriginalRevised(true)
129129
.build();
130130
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
131131
print(rows);
@@ -138,4 +138,18 @@ public void testGeneratorWithInlineMerge3() throws DiffException {
138138
assertEquals("[INSERT,<span class=\"editNewInline\">test</span>,test]", rows.get(4).toString());
139139
assertEquals("[INSERT,<span class=\"editNewInline\">test2</span>,test2]", rows.get(5).toString());
140140
}
141+
142+
@Test
143+
public void testGeneratorWithMergeByWord4() throws DiffException {
144+
DiffRowGenerator generator = DiffRowGenerator.create()
145+
.showInlineDiffs(true)
146+
.mergeOriginalRevised(true)
147+
.inlineDiffByWord(true)
148+
.build();
149+
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("Test"),Arrays.asList("ester"));
150+
print(rows);
151+
152+
assertEquals(1, rows.size());
153+
assertEquals("[CHANGE,<span class=\"editOldInline\">Test</span><span class=\"editNewInline\">ester</span>,ester]", rows.get(0).toString());
154+
}
141155
}

0 commit comments

Comments
 (0)