Skip to content

Commit 2549873

Browse files
committed
support for applying diffs to sequences
1 parent cb1eeb1 commit 2549873

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

diff.lisp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,52 @@ of context; the default of three should be good enough for most situations.")
315315
(window-chunks :initform nil
316316
:accessor window-chunks)))
317317

318+
(defun apply-seq-window (original-seq window &key (offset 0))
319+
"Apply the edits encoded in WINDOW to the ORIGINAL-SEQ."
320+
(multiple-value-bind (interner interned-seqs)
321+
(apply #'intern-seqs original-seq
322+
(mapcar #'chunk-lines (window-chunks window)))
323+
(let ((index (original-start-line window))
324+
(result (coerce (first interned-seqs) 'list)))
325+
(flet ((ind () (+ index offset))
326+
(back (line) (interned-object interner line)))
327+
(loop
328+
for chunk in (window-chunks window)
329+
for lines in (mapcar (lambda (l) (coerce l 'list)) (cdr interned-seqs))
330+
do (case (chunk-kind chunk)
331+
(:common
332+
(mapc (lambda (line)
333+
(assert (eql line (nth (ind) result))
334+
(line result index)
335+
"window does not apply at ~d, ~s!=~s "
336+
(ind) (back line) (back (nth (ind) result)))
337+
(incf index))
338+
lines))
339+
(:delete
340+
(setf result
341+
(append (subseq result 0 (ind))
342+
(subseq result (+ (ind) (length lines)))))
343+
(incf index (length lines))
344+
(decf offset (length lines)))
345+
(:create
346+
(setf result (append (subseq result 0 (ind))
347+
lines
348+
(subseq result (ind))))
349+
(incf offset (length lines)))
350+
((:insert :replace)
351+
(error "unimplemented chunk-kind ~a" (chunk-kind chunk)))))
352+
(values (mapcar #'back result) offset)))))
353+
354+
(defun apply-seq-diff (original-seq diff)
355+
"Apply DIFF to the sequence ORIGINAL-SEQ."
356+
(apply #'values
357+
(reduce
358+
(lambda (accumulator window)
359+
(destructuring-bind (seq offset) accumulator
360+
(multiple-value-call #'list
361+
(apply-seq-window seq window :offset offset))))
362+
(diff-windows diff) :initial-value (list original-seq 0))))
363+
318364
(deftype chunk-kind () '(member :common :delete :replace :insert :create))
319365

320366
(defclass chunk ()

package.lisp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
#:generate-diff
77
#:generate-seq-diff
88
#:unified-diff #:context-diff
9-
9+
10+
#:apply-seq-window
11+
#:apply-seq-diff
12+
1013
#:render-diff
1114
#:render-diff-window
1215
#:format-diff

0 commit comments

Comments
 (0)