📄 diff.tcl
字号:
${fo}.text tag remove diff ${s1}.0 [expr ${e1} + 1].0 ${fn}.text tag remove diff ${s2}.0 [expr ${e2} + 1].0 add-tag ${fo}.text curr ${s1} ${e1} ${dt} 0 add-tag ${fn}.text curr ${s2} ${e2} ${dt} 1 # Move the view on both text widgets so that the new region is # visible. if {${setpos}} { ${this} centerOnScreen } } ######################################################################### # Center the top line of the CDR in each window. ######################################################################### method center {} { upvar #0 ${this}.pos pos scan $g(pdiff,${pos}) "%s %d %d %d %d %s" dummy s1 e1 s2 e2 dt set h [expr int([text_page_num_lines ${fo}.text] / 2)] set o [expr ${s1} - ${h} -1] if {${o} < 0} { set o 0 } set n [expr ${s2} - ${h} -1] if {${n} < 0} { set n 0 } ${fo}.text yview ${o} ${fn}.text yview ${n} } ########################################################################## # Expand filenames by replacing $foo with $env(foo) & # evaluating the result. ########################################################################## proc expand fn { global env upvar ${fn} f regsub -all {\$([^ /\.]+)} ${f} {$env(\1)} t_m_p regsub {^~$} ${t_m_p} {$env(HOME)} t_m_p regsub {^~/} ${t_m_p} {$env(HOME)/} t_m_p regsub {^~([^/]+)} ${t_m_p} {$env(HOME)/../\1} t_m_p catch "set f ${t_m_p}" } ############################################################################### # Finish off a filename if possible. If not, and the number of\ possibilities # is less than 'max', complete as much of the filename as possible. Note # that the default value for 'max' is 100. ############################################################################### method finish {fn {max 100}} { upvar ${fn} f set choices [glob -nocomplain ${f}*] set numchoices [llength "${choices}"] if {${numchoices} == 1} { set f ${choices} return 1 }\ elseif {${numchoices} > ${max}} { return 0 } set choice [lindex "${choices}" 0] set min [string length "${choice}"] set golden "${choice}" for {set idx 1} {${idx} < [llength "${choices}"]} {incr idx} { set choice [lindex "${choices}" ${idx}] set count [string length ${choice}] if {${count} < ${min}} { set min ${count} set golden "${choice}" } } while {${min} > 0} { set match 1 foreach choice "${choices}" { if {[string range "${choice}" 0 ${min}] != "${golden}"} { set match 0 break } } if {${match}} { if {[string length ${golden}] > 0} { set f "${golden}" } break } incr min -1 set golden [string range "${golden}" 0 ${min}] } return 0 } ######################################################################### # Do filename completion by expanding environment variables, resolving # directories, and then completing as much of the filename as possible. ######################################################################### method complete {fn {max 100}} { global sn_root upvar ${fn} f expand f ${this} finish f ${max} if {[file isdirectory ${f}]} { set dst ${f} set suf {} } else { set dst [file dirname ${f}] set suf [file tail ${f}] } if {[file isdirectory ${dst}]} { set c [pwd] catch {cd ${dst}} set f [pwd] catch {cd ${c}} set f [file join ${f} ${suf}] } set f [string trimright ${f} ${sn_root}] if {[llength [glob -nocomplain ${f}*]] < 2 && [file isdirectory ${f}]} { append f ${sn_root} } } ######################################################################### # Change the state on all of the diff-sensitive buttons. ######################################################################### method buttons {{newstate "normal"}} { foreach b [list $itk_component(hull).b.pos.menubutton $itk_component(hull).b.next\ $itk_component(hull).b.prev] { eval "${b} configure -state ${newstate}" } } ######################################################################### # Wipe the slate clean... ######################################################################### method wipe {} { global ${this}.pos ${this}.count set ${this}.pos 0 set ${this}.count 0 set g(cfilo) "" ${fo}.text configure -state normal ${fo}.text tag remove diff 1.0 end ${fo}.text tag remove curr 1.0 end ${fo}.text delete 1.0 end ${fn}.text configure -state normal ${fn}.text tag remove diff 1.0 end ${fn}.text tag remove curr 1.0 end ${fn}.text delete 1.0 end if {[string length $g(destroy)] > 0} { eval $g(destroy) set g(destroy) "" } $itk_component(hull).b.pos.menubutton.menu delete 0 last ${this} buttons disabled } ######################################################################### # Ready the display... ######################################################################### method ready-display {} { set g(cfilo) $g(filo) } ######################################################################### # Mark difference regions and build up the jump menu. ######################################################################### method mark-diffs {} { upvar #0 ${this}.count count set different 0 set numdiff [llength [split "$g(diff)" \n]] # If there are <= 30 diffs, do a one-level jump menu. If there are # more than 30, do a two-level jump menu with sqrt(numdiff) in each # level. if {${numdiff} <= 30} { set g(destroy) "$g(destroy) catch \"eval\ $itk_component(hull).b.pos.menubutton.menu delete 0 last\"\n" foreach d [split $g(diff) \n] { ::incr count set g(pdiff,${count}) [extract ${d}] scan $g(pdiff,${count}) "%s %d %d %d %d %s" dummy s1 e1 s2 e2 dt add-tag ${fo}.text diff ${s1} ${e1} ${dt} 0 add-tag ${fn}.text diff ${s2} ${e2} ${dt} 1 set different 1 $itk_component(hull).b.pos.menubutton.menu add command -label [format "%-6d\ --> %s" ${count} ${d}] -command " ${this} move ${count} 0 " } } else { set target 0 set increment [expr int(pow(${numdiff},0.5))] foreach d [split "$g(diff)" \n] { incr count if {${count} >= ${target}} { $itk_component(hull).b.pos.menubutton.menu add cascade -label ${target}\ -menu $itk_component(hull).b.pos.menubutton.menu.${target} menu $itk_component(hull).b.pos.menubutton.menu.${target} set current ${target} set target [expr ${target} + ${increment}] set g(destroy) "$g(destroy) catch \"eval\ $itk_component(hull).b.pos.menubutton.menu.${current} delete 0\ last\"\n catch \"eval destroy\ $itk_component(hull).b.pos.menubutton.menu.${current}\"\n" } set g(pdiff,${count}) [extract ${d}] scan $g(pdiff,${count}) "%s %d %d %d %d %s" dummy s1 e1 s2 e2 dt add-tag ${fo}.text diff ${s1} ${e1} ${dt} 0 add-tag ${fn}.text diff ${s2} ${e2} ${dt} 1 set different 1 $itk_component(hull).b.pos.menubutton.menu.${current} add command\ -label [format "%-6d --> %s" ${count} ${d}] -command\ " ${this} move ${count} 0 " } } return ${different} } ######################################################################## # Compute differences (start over, basically). ######################################################################## method rediff {} { global sn_debug upvar #0 ${this}.count count upvar #0 ${this}.pos pos ${this} wipe ${this} ready-display # Read the files into their respective widgets & add line numbers. untabify otxt $g(filo) ${fo}.text insert 1.0 ${otxt} set tgt [expr [lindex [split [${fo}.text index end] .] 0] - 1] for {set i 1} {${i} <= ${tgt}} {incr i} { ${fo}.text insert ${i}.0 [format "%-8d" ${i}] } untabify ntxt $g(filn) ${fn}.text insert 1.0 ${ntxt} set tgt [expr [lindex [split [${fn}.text index end] .] 0] - 1] for {set i 1} {${i} <= ${tgt}} {incr i} { ${fn}.text insert ${i}.0 [format "%-8d" ${i}] } # Diff the two files and store the summary lines into 'diff'. # set g(diff) [exec sh -c "diff $opts(diffopt) $g(filo) $g(filn) | # egrep -v '^(<|>|\-)' ; exit 0"] set tmpf [sn_tmpFileName] global sn_options sn_verctl_options set cmd $sn_verctl_options($sn_options(both,rcs-type),diff-command) catch {eval exec ${cmd} $opts(diffopt) [list $g(filo) $g(filn)] >&\ ${tmpf}} if {[catch {set fd [::open ${tmpf} "r"]}]} { return } fconfigure ${fd} -translation binary -blocking 0 set lst [read -nonewline ${fd}] close ${fd} file delete -- ${tmpf} regsub -all "\r" ${lst} "" lst set g(diff) [split ${lst} "\n"] set g(diff) [lmatch -regexp $g(diff) {^[^<>\-].*}] set g(diff) [join $g(diff) "\n"] # Mark up the two text widgets and go to the first diff (if there # is one). if {[${this} mark-diffs]} { set pos 1 ${this} move 1 0 ${this} buttons normal } else { ${this} buttons disabled } # Prevent tampering in the text widgets. ${fo}.text configure -state disabled ${fn}.text configure -state disabled $itk_component(hull).b.pos.num config -width [string length ${count}] if {!${sn_debug}} { file delete -- $g(filn) } }}#itcl_class RCSTopdiff& {# inherit RCSdiff& Toplevel&# constructor args {###FIXME - this constructor callout will cause the parent constructor to be called twice# eval RCSdiff&::constructor $args# }#}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -