home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 April / macformat-075.iso / Shareware Plus / Applications / Alpha / Tcl / SystemCode / CorePackages / procUtils.tcl < prev    next >
Encoding:
Text File  |  1998-12-05  |  5.1 KB  |  197 lines  |  [TEXT/ALFA]

  1. ## -*-Tcl-*-
  2.  # ###################################################################
  3.  #  Vince's Additions - an extension package for Alpha
  4.  # 
  5.  #  FILE: "procUtils.tcl"
  6.  #                                    created: 2/8/97 {6:18:16 pm} 
  7.  #                                last update: 5/12/1998 {11:08:36 pm} 
  8.  #  Author: Vince Darley
  9.  #  E-mail: <darley@fas.harvard.edu>
  10.  #    mail: Division of Engineering and Applied Sciences, Harvard University
  11.  #          Oxford Street, Cambridge MA 02138, USA
  12.  #     www: <http://www.fas.harvard.edu/~darley/>
  13.  #  
  14.  # Copyright (c) 1997-1998  Vince Darley, all rights reserved
  15.  # 
  16.  # ###################################################################
  17.  ##
  18.  
  19. namespace eval procs {}
  20. proc procs::patchOriginalsFromFile {f {alerts 1} {keepwin ""}} {
  21.     set openWins [winNames -f]
  22.     # get fixed procs
  23.     uplevel \#0 [list source $f]
  24.     # use 'c' to store comments before each proc
  25.     set procs [procs::listInFile $f c]
  26.     # replace all Alpha's originals
  27.     foreach p $procs {
  28.         if {[catch {procs::replace $p 0 1 c}]} {
  29.             # should not happen
  30.             lappend failed $p
  31.         }
  32.     }
  33.     set nowOpen [winNames -f]    
  34.     foreach f [lremove -l $nowOpen $openWins] {
  35.         if {$f != $keepwin} {
  36.             bringToFront $f
  37.             goto [minPos]
  38.             killWindow
  39.         }
  40.     }    
  41.     if {[info exists failed]} {
  42.         userMessage $alerts "Couldn't find: $failed, this is BAD."
  43.     }
  44.     userMessage $alerts "Replaced [llength $procs] procs successfully."
  45. }
  46.  
  47. proc procs::listInFile {f {comments ""}} {
  48.     if {$comments != ""} { upvar $comments c }
  49.     # open the window
  50.     file::openQuietly $f
  51.     # get procs in order
  52.     set pos [minPos]
  53.     set markExpr "^\[ \t\]*proc"
  54.     set procs ""
  55.     while {![catch {search -s -f 1 -r 1 -m 0 -i 0 "$markExpr" $pos} res]} {
  56.         set start [lindex $res 0]
  57.         set end [nextLineStart $start]
  58.         set text [lindex [getText $start $end] 1]
  59.         set pos $end
  60.         lappend procs $text
  61.         set c($text) [getText [procs::getCommentPos $start] $start]
  62.     }
  63.     killWindow
  64.     return $procs
  65. }
  66.  
  67. ## 
  68.  # -------------------------------------------------------------------------
  69.  # 
  70.  # "procs::getCommentPos" --
  71.  # 
  72.  #  'p' should be the start of a proc.  This looks for a comment which
  73.  #  precedes that procedure.  It returns the start of such a comment,
  74.  #  or 'p' if none was found.  Blank lines are not allowed.
  75.  # -------------------------------------------------------------------------
  76.  ##
  77. proc procs::getCommentPos {p} {
  78.     set q [prevLineStart $p]
  79.     while {[pos::compare $p > [minPos]]} {
  80.     set pp [lindex [search -n -s -f 1 -m 0 -r 1 -l $p -- "\[ \t\]*#" $q] 0]
  81.     if {$pp == "" || ([pos::compare $pp != $q])} {
  82.         break
  83.     }
  84.     set p $q
  85.     set q [prevLineStart $q]
  86.     }
  87.     return $p
  88. }
  89.  
  90. proc procs::generate {p} {
  91.     set a "proc $p \{"
  92.     foreach arg [info args $p] {
  93.         if {[info default $p $arg v]} {
  94.             append a "\{[list $arg $v]\} "
  95.         } else {
  96.             append a "$arg "
  97.         }
  98.     }
  99.     set a [string trimright $a]
  100.     append a "\} \{"
  101.     append a [info body $p]
  102.     append a "\}"
  103.     regsub -all "\n" $a "\r" a
  104.     return $a
  105. }
  106.  
  107. proc procs::replace {p {ask 1} {addAfterLast 0} {comment ""}} {
  108.     if {$comment != ""} { upvar $comment c }
  109.     set f [procs::find $p]
  110.     if {$f != ""} {file::openQuietly $f}
  111.     if {[info exists c($p)] && $c($p) != ""} {
  112.     set newp "$c($p)[procs::generate $p]"
  113.     } else {
  114.     set newp [procs::generate $p]
  115.     }    
  116.     if {[catch {set a [search -s -f 1 -r 1 -m 0 "^\[ \t\]*proc\[ \t\]+${p}\[ \t\]" 0]}]} {
  117.     if {!$addAfterLast} {
  118.         if {$ask} {
  119.         alertnote "Failed to find proc"
  120.         }
  121.         error "Failed to find proc"
  122.     } else {
  123.         # we just add it after the last one
  124.         insertText "\r" $newp "\r\r"
  125.         saveUnmodified
  126.         return
  127.     }
  128.     }
  129.     goto [lindex $a 0]
  130.     set entire [procs::findEnclosing [lindex $a 1]]
  131.     if {[info exists c($p)] && $c($p) != ""} {
  132.     set entire [list [procs::getCommentPos [lindex $entire 0]] [lindex $entire 1]]
  133.     }    
  134.     eval select $entire
  135.     if {$newp == [getSelect]} { 
  136.     message "No change"
  137.     return 
  138.     }
  139.     if {$ask} {
  140.     if {![dialog::yesno "Replace this proc?"]} {
  141.         error "Cancelled"
  142.     }
  143.     }
  144.     eval replaceText $entire [list $newp]
  145.     saveUnmodified
  146. }
  147.  
  148. # If the first brace after 'proc' ends the current line, then
  149. # assume the argument was a single arg with no braces.
  150. proc procs::findEnclosing { pos {type "proc"} {may_move 0}} {
  151.     set start [lindex [search -s -m 0 -r 1 -f 0 "^\[ \t\]*;?($type) " $pos] 0]
  152.  
  153.     # find the parameter block
  154.     set p1 [lindex [search -s -f 1 "\{" $start] 0]
  155.     set p [matchIt "\{" [pos::math $p1 + 1]]
  156.     if { [string trim [getText $p1 [nextLineStart $p1]]] == "\{" } {
  157.         if {[pos::compare $p < $pos]} {
  158.             error "couldn't get proc"
  159.         } else {
  160.             return [list $start [pos::math $p + 1]]
  161.         }
  162.     }
  163.  
  164.     # find the body
  165.     set p [lindex [search -s -f 1 "\{" $p] 0]
  166.     # this should not fail.  
  167.     if {[catch {set p [matchIt "\{" [pos::math $p + 1]]}]} {
  168.     # work around Alpha bug
  169.     set rem [getPos]
  170.     goto $start
  171.     endOfLine
  172.     balance
  173.     set p [selEnd]
  174.     if {!$may_move} {goto $rem}
  175.     } else {
  176.     set p [pos::math $p + 1]
  177.     }
  178.     if {[pos::compare $p < $pos] } { error "couldn't get proc" }
  179.     return [list $start $p]
  180. }
  181.  
  182. proc procs::findEnclosingName {pos} {
  183.     set p [lindex [procs::findEnclosing $pos] 0]
  184.     return [lindex [string trim [getText $p [nextLineStart $p]] "\{ \t\r"] 1]
  185. }
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.