util::word_diff (public)
util::word_diff -old old -new new [ -split_by split_by ] \ [ -filter_proc filter_proc ] [ -start_old start_old ] \ [ -end_old end_old ] [ -start_new start_new ] [ -end_new end_new ]
Defined in packages/acs-tcl/tcl/utilities-procs.tcl
Does a word (or character) diff on two lines of text and indicates text that has been deleted/changed or added by enclosing it in start/end_old/new.
- Switches:
- -old (required)
- The original text.
- -new (required)
- The modified text.
- -split_by (optional)
- If split_by is a space, the diff will be made on a word-by-word basis. If it is the empty string, it will be made on a char-by-char basis.
- -filter_proc (optional, defaults to
"ns_quotehtml"
)- A filter to run the old/new text through before doing the diff and inserting the HTML fragments below. Keep in mind that if the input text is HTML, and the start_old, etc... fragments are inserted at arbitrary locations depending on where the diffs are, you might end up with invalid HTML unless the original HTML is quoted.
- -start_old (optional, defaults to
"<strike><i><font color="blue">"
)- HTML fragment to place before text that has been removed.
- -end_old (optional, defaults to
"</font></i></strike>"
)- HTML fragment to place after text that has been removed.
- -start_new (optional, defaults to
"<u><b><font color="red">"
)- HTML fragment to place before new text.
- -end_new (optional, defaults to
"</font></b></u>"
)- HTML fragment to place after new text.
- Author:
- Gabriel Burca
- See Also:
- ns_quotehtml
- Partial Call Graph (max 5 caller/called nodes):
- Testcases:
- word_diff
Source code: if {$filter_proc ne ""} { set old [$filter_proc $old] set new [$filter_proc $new] } set old_fd [file tempfile old_f [ad_tmpdir]/nsdiff-XXXXXX] set new_fd [file tempfile new_f [ad_tmpdir]/nsdiff-XXXXXX] puts $old_fd [join [split $old $split_by] "\n"] puts $new_fd [join [split $new $split_by] "\n"] close $old_fd close $new_fd # # Diff output is 1 based, our lists are 0 based, so insert a dummy # element to start the list with. # set old_w [linsert [split $old $split_by] 0 {}] set sv 1 try { exec -ignorestderr [util::which diff] -f $old_f $new_f } on error {output} { } on ok {output} { } set lines [split $output \n] set pos -1 set nrLines [llength $lines] while {1} { if {$nrLines < $pos} { break } set diff [lindex $lines [incr pos]] if {[regexp {^d(\d+)(\s+(\d+))?$} $diff full m1 m2]} { if {$m2 ne ""} {set d_end $m2} else {set d_end $m1} for {set i $sv} {$i < $m1} {incr i} { append res "${split_by}[lindex $old_w $i]" } for {set i $m1} {$i <= $d_end} {incr i} { append res "${split_by}${start_old}[lindex $old_w $i]${end_old}" } set sv [expr {$d_end + 1}] } elseif {[regexp {^c(\d+)(\s+(\d+))?$} $diff full m1 m2]} { if {$m2 ne ""} {set d_end $m2} else {set d_end $m1} for {set i $sv} {$i < $m1} {incr i} { append res "${split_by}[lindex $old_w $i]" } for {set i $m1} {$i <= $d_end} {incr i} { append res "${split_by}${start_old}[lindex $old_w $i]${end_old}" } while {1} { if {$nrLines < $pos} { break } set diff [lindex $lines [incr pos]] if {$diff eq "."} { break } else { append res "${split_by}${start_new}${diff}${end_new}" } } set sv [expr {$d_end + 1}] } elseif {[regexp {^a(\d+)$} $diff full m1]} { set d_end $m1 for {set i $sv} {$i <= $m1} {incr i} { append res "${split_by}[lindex $old_w $i]" } while {1} { if {$nrLines < $pos} { break } set diff [lindex $lines [incr pos]] if {$diff eq "."} { break } else { append res "${split_by}${start_new}${diff}${end_new}" } } set sv [expr {$d_end + 1}] } } for {set i $sv} {$i < [llength $old_w]} {incr i} { append res "${split_by}[lindex $old_w $i]" } file delete -- $old_f $new_f return $resXQL Not present: PostgreSQL, Oracle Generic XQL file: packages/acs-tcl/tcl/utilities-procs.xql