4747 * </code>
4848 */
4949public class DiffRowGenerator {
50-
50+ public static final Pattern SPLIT_BY_WORD_PATTERN = Pattern .compile ("\\ s+|[,.\\ [\\ ](){}/\\ \\ *+\\ -#]" );
51+
5152 public static final BiPredicate <String , String > IGNORE_WHITESPACE_EQUALIZER = (original , revised )
5253 -> original .trim ().replaceAll ("\\ s+" , " " ).equals (revised .trim ().replaceAll ("\\ s+" , " " ));
54+
5355 public static final BiPredicate <String , String > DEFAULT_EQUALIZER = Object ::equals ;
54- private static final Pattern SPLIT_PATTERN = Pattern .compile ("\\ s+|[,.\\ [\\ ](){}/\\ \\ *+\\ -#]" );
56+
57+ /**
58+ * Splitting lines by word to achieve word by word diff checking.
59+ */
60+ public static final Function <String , List <String >> SPLITTER_BY_WORD = line -> splitStringPreserveDelimiter (line , SPLIT_BY_WORD_PATTERN );
61+
62+ /**
63+ * Splitting lines by character to achieve char by char diff checking.
64+ */
65+ public static final Function <String , List <String >> SPLITTER_BY_CHARACTER = line -> {
66+ List <String > list = new ArrayList <>(line .length ());
67+ for (Character character : line .toCharArray ()) {
68+ list .add (character .toString ());
69+ }
70+ return list ;
71+ };
72+
5573 private final boolean showInlineDiffs ;
5674 private final boolean ignoreWhiteSpaces ;
5775 private final Function <Boolean , String > oldTag ;
5876 private final Function <Boolean , String > newTag ;
59- private final boolean inlineDiffByWord ;
77+ private final Function < String , List < String >> inlineDiffSplitter ;
6078 private final int columnWidth ;
6179 private final BiPredicate <String , String > equalizer ;
6280 private final boolean mergeOriginalRevised ;
@@ -78,8 +96,8 @@ public static class Builder {
7896
7997 private int columnWidth = 0 ;
8098 private boolean mergeOriginalRevised = false ;
81- private boolean inlineDiffByWord = false ;
8299 private boolean reportLinesUnchanged = false ;
100+ private Function <String , List <String >> inlineDiffSplitter = SPLITTER_BY_CHARACTER ;
83101
84102 private Builder () {
85103 }
@@ -177,7 +195,13 @@ public Builder mergeOriginalRevised(boolean mergeOriginalRevised) {
177195 * deliver no in word changes.
178196 */
179197 public Builder inlineDiffByWord (boolean inlineDiffByWord ) {
180- this .inlineDiffByWord = inlineDiffByWord ;
198+ inlineDiffSplitter = inlineDiffByWord ?SPLITTER_BY_WORD :SPLITTER_BY_CHARACTER ;
199+ return this ;
200+ }
201+
202+
203+ public Builder inlineDiffBySplitter (Function <String , List <String >> inlineDiffSplitter ) {
204+ this .inlineDiffSplitter = inlineDiffSplitter ;
181205 return this ;
182206 }
183207 }
@@ -193,9 +217,11 @@ private DiffRowGenerator(Builder builder) {
193217 newTag = builder .newTag ;
194218 columnWidth = builder .columnWidth ;
195219 mergeOriginalRevised = builder .mergeOriginalRevised ;
196- inlineDiffByWord = builder .inlineDiffByWord ;
220+ inlineDiffSplitter = builder .inlineDiffSplitter ;
197221 equalizer = ignoreWhiteSpaces ? IGNORE_WHITESPACE_EQUALIZER : DEFAULT_EQUALIZER ;
198222 reportLinesUnchanged = builder .reportLinesUnchanged ;
223+
224+ Objects .requireNonNull (inlineDiffSplitter );
199225 }
200226
201227 /**
@@ -318,19 +344,8 @@ private List<DiffRow> generateInlineDiffs(Delta<String> delta) throws DiffExcept
318344 String joinedOrig = String .join ("\n " , orig );
319345 String joinedRev = String .join ("\n " , rev );
320346
321- if (inlineDiffByWord ) {
322- origList = splitStringPreserveDelimiter (joinedOrig );
323- revList = splitStringPreserveDelimiter (joinedRev );
324- } else {
325- origList = new ArrayList <>(joinedOrig .length ());
326- revList = new ArrayList <>(joinedRev .length ());
327- for (Character character : joinedOrig .toCharArray ()) {
328- origList .add (character .toString ());
329- }
330- for (Character character : joinedRev .toCharArray ()) {
331- revList .add (character .toString ());
332- }
333- }
347+ origList = inlineDiffSplitter .apply (joinedOrig );
348+ revList = inlineDiffSplitter .apply (joinedRev );
334349
335350 List <Delta <String >> inlineDeltas = DiffUtils .diff (origList , revList ).getDeltas ();
336351
@@ -404,7 +419,7 @@ public static void wrapInTag(List<String> sequence, int startPosition,
404419 sequence .add (endPosition , generator .apply (false ));
405420 }
406421
407- protected final static List <String > splitStringPreserveDelimiter (String str ) {
422+ protected final static List <String > splitStringPreserveDelimiter (String str , Pattern SPLIT_PATTERN ) {
408423 List <String > list = new ArrayList <>();
409424 if (str != null ) {
410425 Matcher matcher = SPLIT_PATTERN .matcher (str );
0 commit comments