@@ -70,10 +70,13 @@ function DiffCompare pFrom, pTo, pContext
7070 put 3 into pContext
7171 end if
7272
73+ put _split(pFrom , return) into pFrom
74+ put _split(pTo , return) into pTo
75+
7376 local tEdits
74- put diff_strings (pFrom , pTo ) into tEdits
75- split pFrom by cr
76- return convert_to_unified(tEdits , pFrom , the number of elements in pFrom , pContext )
77+ put diff_arrays (pFrom , pTo ) into tEdits
78+
79+ return convert_to_unified(tEdits , pFrom , pTo , pContext )
7780end DiffCompare
7881
7982/* *
@@ -96,9 +99,9 @@ An updated version of pSource with the changes from pDiff applied.
9699*/
97100
98101function DiffPatch pSource, pDiff
99- local tEdits
100- put parse_unified( pDiff ) into tEdits
101- return patch_string(pSource , tEdits )
102+ local tEdits , tContent
103+ parse_unified pDiff , tEdits , tContent
104+ return patch_string(pSource , tEdits , tContent )
102105end DiffPatch
103106
104107/* *
@@ -220,14 +223,17 @@ constant kLastSourceIndex = "lastSourceIndex"
220223constant kDelta = "delta"
221224
222225-- produce unified diff from edit list, containing pContextLength lines of context
223- private function convert_to_unified pEdits, pSource, pSourceLength, pContextLength
226+ private function convert_to_unified pEdits, pA, pB, pContextLength
227+ local tALength , tBLength
228+ put the number of elements in pA into tALength
229+ put the number of elements in pB into tBLength
224230 local tDiff
225231 local tHunk
226232 local tDelta = 0
227233
228234 repeat for each line tEdit in pEdits
229- local tA , tB , tOperation , tContent
230- parse_edit tEdit , tA , tB , tOperation , tContent
235+ local tA , tB , tOperation
236+ parse_edit tEdit , tA , tB , tOperation
231237
232238 if tHunk is an array and not continue_hunk(tHunk , tA , tOperation ) then
233239 end_hunk tHunk
@@ -237,13 +243,13 @@ private function convert_to_unified pEdits, pSource, pSourceLength, pContextLeng
237243 end if
238244
239245 if tHunk is not an array then
240- begin_hunk tHunk , pSource , pSourceLength , pContextLength
246+ begin_hunk tHunk , pA , tALength , pContextLength
241247 end if
242248
243249 if tOperation is kDiffOperationAdd then
244- add_addition tHunk , tA , tContent
250+ add_addition tHunk , tA , pB [ tB ]
245251 else if tOperation is kDiffOperationDelete then
246- add_deletion tHunk , tA , tContent
252+ add_deletion tHunk , tA , pA [ tA ]
247253 end if
248254 end repeat
249255
@@ -279,22 +285,30 @@ end continue_hunk
279285
280286private command add_deletion @pHunk, pIndex, pContent
281287 add_context_before pHunk , pIndex
282- put "-" & pContent & cr after pHunk [kContent ]
288+ put "-" & pContent after pHunk [kContent ]
283289 if pHunk [kFirstSourceIndex ] is empty then
284290 put pIndex into pHunk [kFirstSourceIndex ]
285291 end if
286292 put pIndex into pHunk [kLastSourceIndex ]
287293 subtract 1 from pHunk [kDelta ]
294+
295+ if not (pContent ends with return ) then
296+ put return & "\ No newline at end of file" & return after pHunk [kContent ]
297+ end if
288298end add_deletion
289299
290300private command add_addition @pHunk, pIndex, pContent
291301 add_context_before pHunk , pIndex + 1
292- put "+" & pContent & cr after pHunk [kContent ]
293302 if pHunk [kFirstSourceIndex ] is empty then
294303 put pIndex into pHunk [kFirstSourceIndex ]
295304 end if
296305 put pIndex into pHunk [kLastSourceIndex ]
306+ put "+" & pContent after pHunk [kContent ]
297307 add 1 to pHunk [kDelta ]
308+
309+ if not (pContent ends with return ) then
310+ put return & "\ No newline at end of file" & return after pHunk [kContent ]
311+ end if
298312end add_addition
299313
300314private command add_context_before @pHunk, pIndex
@@ -318,9 +332,13 @@ private command add_context_before @pHunk, pIndex
318332 end if
319333
320334 repeat with i = tStart to tEnd
321- put space & pHunk [kSource ][i] & cr after pHunk [kContent ]
335+ put space & pHunk [kSource ][i] after pHunk [kContent ]
322336 end repeat
323337
338+ if not (pHunk [kContent ] ends with return ) then
339+ put return & "\ No newline at end of file" & return after pHunk [kContent ]
340+ end if
341+
324342 if pHunk [kFirstSourceIndex ] is empty then
325343 put tStart into pHunk [kFirstSourceIndex ]
326344 end if
@@ -358,8 +376,10 @@ end add_hunk
358376-- --------
359377
360378-- convert unified diff to edit list
361- private function parse_unified pUniDiff
379+ private command parse_unified pUniDiff, @rEdits, @rContent
362380 local tEdits
381+ local tContent
382+ local tLastEdit
363383 repeat for each line tLine in pUniDiff
364384 // skip file headers if present
365385 if tLine begins with "+++" or tLine begins with "---" then
@@ -388,20 +408,35 @@ private function parse_unified pUniDiff
388408 end if
389409 else if tLine begins with space then
390410 // skip context line
411+ put empty into tLastEdit
412+
391413 add 1 to tAStart
392414 add 1 to tBStart
393415 subtract 1 from tALength
394416 subtract 1 from tBLength
395417 else if tLine begins with "+" then
396418 // addition
397- put format_edit(tAStart - 1 , tBStart , kDiffOperationAdd , char 2 to - 1 of tLine ) & return after tEdits
419+ put tAStart - 1 ,kDiffOperationAdd ,tBStart into tLastEdit
420+ put tLastEdit & return after tEdits
421+ put char 2 to - 1 of tLine & return into tContent [tBStart ]
422+
398423 add 1 to tBStart
399424 subtract 1 from tBLength
400425 else if tLine begins with "-" then
401426 // deletion
402- put format_edit(tAStart , tBStart - 1 , kDiffOperationDelete , char 2 to - 1 of tLine ) & return after tEdits
427+ put tAStart , kDiffOperationDelete , tBStart - 1 into tLastEdit
428+ put tLastEdit & return after tEdits
429+
403430 add 1 to tAStart
404431 subtract 1 from tALength
432+ else if tLine begins with "\" then
433+ // no newline
434+ local tA , tB , tLastOp
435+ parse_edit tLastEdit , tA , tB , tLastOp
436+ // remove newline from content of last operation (if addition)
437+ if tLastOp is kDiffOperationAdd then
438+ delete the last char of tContent [tB ]
439+ end if
405440 end if
406441 end repeat
407442
@@ -438,13 +473,36 @@ private function _combine @pArray, pDelimiter
438473 return tCombined
439474end _combine
440475
476+ -- split function which retains delimiter chars
477+ private function _split pString, pDelim
478+ local tArray
479+ local tIndex = 0
480+ set the linedelimiter to pDelim
481+ repeat for each line tLine in pString
482+ add 1 to tIndex
483+ put tLine & pDelim into tArray [tIndex ]
484+ end repeat
485+
486+ // remove delim from last line if missing from string
487+ if not (pString ends with pDelim ) then
488+ delete last char of tArray [tIndex ]
489+ end if
490+
491+ return tArray
492+ end _split
493+
441494-- ------------------------------------------------------------------------------
442495
443496-- generate list of edits between two strings
444497private function diff_strings pA, pB
445- split pA by cr
446- split pB by cr
498+ put _split( pA , return) into pA
499+ put _split( pB , return) into pB
447500
501+ return diff_arrays(pA , pB )
502+ end diff_strings
503+
504+ -- generate list of edits between two arrays
505+ private function diff_arrays pA, pB
448506 local tALength , tBLength
449507 put the number of elements in pA into tALength
450508 put the number of elements in pB into tBLength
@@ -465,15 +523,15 @@ private function diff_strings pA, pB
465523 end if
466524
467525 return tEdits
468- end diff_strings
526+ end diff_arrays
469527
470528-- apply edit list to string
471- private function patch_string pString, pEdits
472- split pString by cr
529+ private function patch_string pString, pEdits, pContent
530+ put _split( pString , return) into pString
473531 local tOutput
474- put patch_arrays(pString , the number of elements in pString , pEdits ) into tOutput
532+ put patch_arrays(pString , pEdits , pContent ) into tOutput
475533
476- return _combine(tOutput , cr )
534+ return _combine(tOutput , empty )
477535
478536 return tOutput
479537end patch_string
@@ -512,27 +570,9 @@ private function compare_arrays pA, pALength, pB, pBLength
512570
513571 end repeat
514572
515- return add_content_to_edits( tPath [tDelta ], pA , pB )
573+ return tPath [tDelta ]
516574end compare_arrays
517575
518- private function add_content_to_edits pEdits, pA, pB
519- local tEdits
520- repeat for each line tEdit in pEdits
521- local tA , tB , tOperation
522- put item 2 of tEdit into tOperation
523- local tContent
524- if tOperation is kDiffOperationAdd then
525- put item 3 of tEdit into tB
526- put pB [tB ] into tContent
527- else
528- put item 1 of tEdit into tA
529- put pA [tA ] into tContent
530- end if
531- put tEdit ,tContent & return after tEdits
532- end repeat
533- return tEdits
534- end add_content_to_edits
535-
536576private command compare_diagonal @pFP, @pPath, @pA, pALength, @pB, pBLength, k
537577 local tLeft , tRight , tNext , tPrevPath , tOperation , tContent
538578 put pFP [k - 1 ] + 1 into tLeft
@@ -578,18 +618,18 @@ private function snake @pA, pALength, @pB, pBLength, k, y
578618end snake
579619
580620-- apply edits to source array, producing output array
581- private function patch_arrays @ pA, pALength, pEdits
621+ private function patch_arrays pA, pEdits, pContent
582622 local tOutput
583623 local tIndex , tAIndex
584624 put 1 into tIndex
585625 put 1 into tAIndex
586626 repeat for each line tEdit in pEdits
587- local tA , tB , tOperation , tContent
588- parse_edit tEdit , tA , tB , tOperation , tContent
627+ local tA , tB , tOperation
628+ parse_edit tEdit , tA , tB , tOperation
589629
590630 if tOperation is kDiffOperationAdd then
591631 skip_edits tOutput , tIndex , pA , tAIndex , tA
592- put tContent into tOutput [tIndex ]
632+ put pContent [ tB ] into tOutput [tIndex ]
593633 add 1 to tIndex
594634 put tA + 1 into tAIndex
595635 else if tOperation is kDiffOperationDelete then
@@ -599,7 +639,7 @@ private function patch_arrays @pA, pALength, pEdits
599639
600640 end repeat
601641
602- skip_edits tOutput , tIndex , pA , tAIndex , pALength
642+ skip_edits tOutput , tIndex , pA , tAIndex , the number of elements in pA
603643
604644 return tOutput
605645end patch_arrays
@@ -617,12 +657,12 @@ private function reverse_edits pEdits
617657 local tA , tB , tOperation , tContent
618658
619659 repeat for each line tEdit in pEdits
620- parse_edit tEdit , tA , tB , tOperation , tContent
660+ parse_edit tEdit , tA , tB , tOperation
621661
622662 if tOperation is kDiffOperationAdd then put kDiffOperationDelete into tOperation
623663 else if tOperation is kDiffOperationDelete then put kDiffOperationAdd into tOperation
624664
625- put format_edit( tB , tA , tOperation , tContent ) & return after tEdits
665+ put tB , tOperation , tA & return after tEdits
626666 end repeat
627667
628668 return tEdits
@@ -632,11 +672,10 @@ private function format_edit pAIndex, pBIndex, pOperation, pContent
632672 return pAIndex ,pOperation ,pBIndex ,pContent
633673end format_edit
634674
635- private command parse_edit pEdit @rAIndex, @rBIndex, @rOperation, @rContent
675+ private command parse_edit pEdit @rAIndex, @rBIndex, @rOperation
636676 put item 1 of pEdit into rAIndex
637677 put item 2 of pEdit into rOperation
638678 put item 3 of pEdit into rBIndex
639- put item 4 to - 1 of pEdit into rContent
640679end parse_edit
641680
642681-- ------------------------------------------------------------------------------
0 commit comments