((section 2 "Outdated egg!" (p "This is an egg for CHICKEN 4, the unsupported old release.  You're almost certainly looking for " (int-link "/eggref/5/npdiff" "the CHICKEN 5 version of this egg") ", if it exists.") (p "If it does not exist, there may be equivalent functionality provided by another egg; have a look at the " (link "https://wiki.call-cc.org/chicken-projects/egg-index-5.html" "egg index") ". Otherwise, please consider porting this egg to the current version of CHICKEN.") (tags "egg")) (section 2 "npdiff" (p "Compute the longest common subsequence of two sequences, and generate a script to transform one sequence into the other.") (toc)) (section 2 "Usage" (p "(require-extension npdiff)")) (section 2 "Documentation" (p "The " (tt "npdiff") " library is an implementation of an algorithm for sequence comparison that has a worst-case running time of " (tt "O(N*P)") ", where " (tt "P") " is the number of deletions required by the shortest edit script between the two sequences.  The algorithm is described in the following paper:") (pre "Sun Wu, Udi Manber, Eugene Myers, and Webb Miller. An O(NP) sequence comparison algorithm. \nIn Information Processing Letters, volume 35, pages 317--323, September 1990.") (p "This library defines a data type that describes the three basic operations of an edit script (remove, insert, change) and a procedure that implements the algorithm for sequences of an arbitrary type, provided an equality predicate for that type, and accessors for the sequence.") (section 3 "Data types" (p (tt "(define-datatype diffop diffop? ...)")) (p "Representation of the three diff operations: insert, remove, change. The target in each operation is an index or a range of indices in the sequence being transformed (target sequence), and the source is a range of indices in the sequence being read from (source sequence). The operation definitions are:") (dl (dt (tt "(Insert target source seq context)")) (dd "Insert operation")) (ul (li (tt "TARGET") " is the index at which the insertion takes place; ") (li (tt "SOURCE") " is a range in the form (x . y) that specifies the indices of those elements in the source sequence that are inserted in the target sequence; ") (li (tt "SEQ") " is the target sequence, and ") (li (tt "CONTEXT") " is an optional context provided  in the form " (tt "(BEFORE . AFTER)") " where " (tt "BEFORE") " is a sequence of elements from the source preceding the elements being inserted, and " (tt "AFTER") " is a sequence of elements from the source that follow the elements being inserted. ")) (dl (dt (tt "(Remove target seq context)")) (dd "Remove operation")) (ul (li (tt "TARGET") " is a range of elements in the form (x . y) that are being deleted from the target sequence; ") (li (tt "SEQ") " is the target sequence, and ") (li (tt "CONTEXT") " is an optional context provided  in the form " (tt "(BEFORE . AFTER)") " where " (tt "BEFORE") " is a sequence of elements from the target preceding the elements being deleted, and " (tt "AFTER") " is a sequence of elements from the target that follow the elements being deleted. ")) (dl (dt (tt "(Change target source seqin seqout contextin contextout)")) (dd "Change operation")) (ul (li (tt "TARGET") " is a range of elements in the form (x . y) that are being modified in the target sequence; ") (li (tt "SOURCE") " is a range of elements in the form (x . y) from the source sequence that are replacing the specified elements in the target sequence; ") (li (tt "SEQIN") " is the source sequence, and " (tt "SEQOUT") " is the target sequence; ") (li (tt "CONTEXTOUT") " is an optional context provided  in the form " (tt "(BEFORE . AFTER)") " where " (tt "BEFORE") " is a sequence of elements from the target preceding the elements being changed (SEQOUT), and " (tt "AFTER") " is a sequence of element from the target that follow the elements being changed (SEQOUT); " (tt "CONTEXTIN") " is an optional context provided  in the form " (tt "(BEFORE . AFTER)") " where " (tt "BEFORE") " is a sequence of elements from the source preceding the replacement elements (SEQIN), and " (tt "AFTER") " is a sequence of elements from the source that follow the replacement elements (SEQIN); "))) (section 3 "Procedures" (def (sig (procedure "make-diff:: EQUAL? SEQ-REF SEQ-LENGTH HUNKS-PROC -> DIFF-PROC" (id make-diff))) (p "Creates a diff procedure, where") (ul (li (tt "EQUAL?") " is an equality predicate for elements of the type being compared; ") (li (tt "SEQ-REF") " is a procedure of the form " (tt "LAMBDA SEQ INDEX -> ELEMENT") " which returns element " (tt "INDEX") " from sequence " (tt "SEQ") "; ") (li (tt "SEQ-LENGTH") " is a procedure of the form " (tt "LAMBDA SEQ -> LEN") " which returns the length  of sequence " (tt "SEQ") "; ") (li (tt "HUNKS") " is a procedure of the type created by " (tt "make-hunks") ", which is described below.")) (p "The returned procedure is of the form " (tt "LAMBDA A B [CONTEXT-LEN] -> (HUNK ... )") " where " (tt "A") " and " (tt "B") " are two sequences to be compared, and " (tt "CONTEXT-LEN") " is an optional context length, which is used by the " (tt "HUNKS") " procedure to create context in the hunks of the edit script")) (def (sig (procedure "make-hunks:: SEQ-REF SEQ-LENGTH SEQ-SLICE -> HUNKS-PROC" (id make-hunks))) (p "creates a procedure that creates insert/remove/change hunks given a stack of matching index ranges that is produced by the " (tt "diff") " procedure above.") (ul (li (tt "SEQ-REF") " is a procedure of the form " (tt "LAMBDA SEQ INDEX -> ELEMENT") " which returns element " (tt "INDEX") " from sequence " (tt "SEQ") "; ") (li (tt "SEQ-LENGTH") " is a procedure of the form " (tt "LAMBDA SEQ -> LEN") " which returns the length  of sequence " (tt "SEQ") "; ") (li (tt "SEQ-SLICE") " is a procedure of the form " (tt "LAMBDA SEQ START END -> SEQ") " which returns a list  with the elements contained within the specified range in the input sequence " (tt "SEQ") "; ")) (p "The returned procedure is of the form " (tt "LAMBDA A B CSS [CONTEXT] -> (HUNK ... )") " where " (tt "A") " and " (tt "B") " are the two sequences compared, " (tt "CSS") " is the stack of matching ranges returned by " (tt "diff") ", and " (tt "CONTEXT") " is an optional argument that is used to add context to the generated hunks, if specified.")))) (section 2 "Examples" (pre ";; Creates a function to find the differences between two vectors\n;; containing strings\n(use npdiff vector-lib)\n\n(define  (textdiff text1 text2 . rest)\n  (let-optionals  rest ((context-len 0))\n    (let ((A   (list->vector text1))\n\t  (B   (list->vector text2)))\n      ((make-npdiff  string=? vector-ref vector-length \n\t\t     (make-hunks vector-ref vector-length \n\t\t\t\t (compose vector->list vector-copy)))\n       A B context-len))))")) (section 2 "About this egg" (section 3 "Author" (p (int-link "/users/ivan-raikov" "Ivan Raikov"))) (section 3 "Version history" (dl (dt "1.16") (dd "Added missing else clause when constructing hunks for completely different sequences [thanks to Felix Winkelmann]") (dt "1.15") (dd "Increased amount of context used for remove hunks [related to a bug discovered by Daishi Kato]") (dt "1.14") (dd "Proper handling of boundary cases when either input sequence is empty [thanks to Daishi Kato]") (dt "1.13") (dd "Make sure context is included even if the two sequences are completely different") (dt "1.12") (dd "Updated version in setup file") (dt "1.11") (dd "Documentation converted to wiki format") (dt "1.10") (dd "Eliminated dependency on matchable") (dt "1.9") (dd "Ported to Chicken 4") (dt "1.8") (dd "Added missing files to the file manifest") (dt "1.7") (dd "Removed dependence on stack egg") (dt "1.5") (dd "Build script updated for better cross-platform compatibility") (dt "1.4") (dd "eggdoc documentation fix") (dt "1.3") (dd "License upgrade to GPL v3") (dt "1.2") (dd "Added license text to source files") (dt "1.1") (dd "Documentation fixes") (dt "1.0") (dd "Initial release"))) (section 3 "License" (pre "Copyright 2007-2011 Ivan Raikov. \n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\nGeneral Public License for more details.\n\nA full copy of the GPL license can be found at\n<http://www.gnu.org/licenses/>."))))