home *** CD-ROM | disk | FTP | other *** search
/ Internet File Formats / InternetFileFormatsCD.bin / text / latex / mac / alpha60.hqx / Tcl / SystemCode / fortran.tcl < prev    next >
Encoding:
Text File  |  1995-05-08  |  8.9 KB  |  323 lines

  1. #=============================================================================
  2. # Fortran mode definition
  3. #
  4. # modified 12/94 by Tom Pollard <pollard@chem.columbia.edu>
  5. #  - fixed funcExpr, FortMarkFile search expressions
  6. #  - changed comment character from 'C' to 'c' (why isn't it case-insensitive?)
  7. #  - added 'include' keyword
  8. #  - added FortShiftRight and FortShiftLeft procs
  9. #
  10. # modified 5/95
  11. #  - added Cmd-Dbl-Click handler
  12. #  - added auto-indentation
  13. #
  14. proc dummyFort {} {}
  15.  
  16. newModeVar Fort    prefixString    {c}    0
  17. newModeVar Fort sortedIsDefault    {0} 1
  18. newModeVar Fort wordWrap        {0}    1
  19. newModeVar Fort funcExpr    {^[^c][ \t]*(subroutine|[ \ta-z*0-9]*function|entry).*$} 0
  20. newModeVar Fort autoMark        0    1
  21.  
  22. set FortKeywords { 
  23.   backspace block call character close common complex 
  24.   continue data dimension do double else elseif end enddo endfile endif entry 
  25.   equivalence external format function goto if implicit include inquire integer 
  26.   intrinsic logical open parameter precision print program read return save 
  27.   stop real rewind subroutine then write
  28. }
  29.  
  30. regModeKeywords -e {c} -c red -k blue Fort $FortKeywords 
  31. unset FortKeywords
  32.  
  33.  
  34. bind '\[' <c>  FortShiftLeft Fort
  35. bind '\[' <co> FortShiftLeftSpace Fort
  36. bind '\]' <c>  FortShiftRight Fort
  37. bind '\]' <co> FortShiftRightSpace Fort
  38.  
  39. bind '\t' <z>     doATab Fort
  40.  
  41. #=============================================================================
  42.  
  43. proc FortMarkFile {} {
  44.   set pat1 {^[^c][ \ta-z*0-9]*(subroutine|.*function|entry)[ \t]+([a-z0-9_]+)}
  45.   set end [maxPos]
  46.   set pos 0
  47.   set l {}
  48.   while {![catch {search -f 1 -r 1 -m 0 -i 1 $pat1 $pos} mtch]} {
  49.     regexp -nocase $pat1 [eval getText $mtch] allofit subtyp name
  50.     set start [lindex $mtch 0]
  51.     set end [nextLineStart $start]
  52.     set pos $end
  53.     set inds($name) [lineStart $start]
  54.   }
  55.  
  56.   if {[info exists inds]} {
  57.     foreach f [lsort [array names inds]] {
  58.       set next [nextLineStart $inds($f)]
  59.       setNamedMark $f $inds($f) $next $next
  60.     }
  61.   }
  62. }
  63.  
  64. #================================================================================
  65. # Block shift left and right for Fortran mode (preserves cols 1-6)
  66. #================================================================================
  67.  
  68. proc FortShiftLeft {} {
  69.     global shiftChar
  70.     doFortShiftLeft "\t"
  71.     
  72. }
  73. proc FortShiftLeftSpace {} {
  74.     global shiftChar
  75.     doFortShiftLeft " "
  76. }
  77.  
  78. proc doFortShiftLeft {shiftChar} {
  79.     set start [lineStart [getPos]]
  80.     set end [nextLineStart [expr [selEnd] - 1]]
  81.     if {$start >= $end} {set end [nextLineStart $start]}
  82.     
  83.     set text [split [getText $start [expr $end - 1]] "\r"]
  84.     
  85.     set textout ""
  86.     
  87.     set pat {^(c|[ 0-9][ 0-9][ 0-9][ 0-9][ 0-9].| *[0-9]*\t)(.*)$}
  88.     foreach line $text {
  89.     if {[regexp $pat $line mtch pref body]} {
  90.         if {[string index $body 0] == $shiftChar} {
  91.         lappend textout $pref[string range $body 1 end]
  92.         } else {
  93.         lappend textout $line
  94.         }
  95.     } else {
  96.         lappend textout $line
  97.     }
  98.     }
  99.  
  100.     set text [join $textout "\r"]    
  101.     replaceText $start [expr $end - 1] $text
  102.     select $start [expr 1 + $start + [string length $text]]
  103. }
  104.  
  105. proc FortShiftRight {} {
  106.     global shiftChar
  107.     doFortShiftRight "\t"
  108.     
  109. }
  110. proc FortShiftRightSpace {} {
  111.     global shiftChar
  112.     doFortShiftRight " "
  113. }
  114.  
  115. proc doFortShiftRight {shiftChar} {
  116.     set start [lineStart [getPos]]
  117.     set end [nextLineStart [expr [selEnd] - 1]]
  118.     if {$start >= $end} {set end [nextLineStart $start]}
  119.     
  120.     set text [split [getText $start [expr $end - 1]] "\r"]
  121.     
  122.     set textout ""
  123.     
  124.     set pat {^(c|[ 0-9][ 0-9][ 0-9][ 0-9][ 0-9].| *[0-9]*\t)(.*)$}
  125.     foreach line $text {
  126.     if {[regexp $pat $line mtch pref body]} {
  127.         lappend textout $pref$shiftChar$body
  128.     } else {
  129.         lappend textout $line
  130.     }
  131.     }
  132.     
  133.     set text [join $textout "\r"]    
  134.     replaceText $start [expr $end - 1] $text
  135.     select $start [expr 1 + $start + [string length $text]]
  136. }
  137.  
  138. #=============================================================================
  139.  
  140. proc FortDblClick {from to} {
  141.     global tagFile
  142.     
  143.     select $from $to
  144.     set text [getSelect]
  145.     
  146.     set lines [grep "^$text'" $tagFile]
  147.     if {[regexp {'(.*)'(.*[^\t])(\t)+░} $lines dummy one two]} {
  148.         if {[string match "*$one*" [winNames -f]]} {
  149.             bringToFront $one
  150.         } else {
  151.             edit $one
  152.         }
  153.         set inds [search -f 1 -r 0 "$two" 0]
  154.         display [lindex $inds 0]
  155.         eval select $inds
  156.     }
  157. }
  158.  
  159. ####################################################################################
  160. # Fortan auto-indentation
  161. #
  162. # Author:    Tom Pollard <pollard@chem.columbia.edu>
  163. # Released:    2/17/95
  164. #
  165. # Logic:
  166. #    0.    Identify previous line
  167. #            a) ignore comments and continuation lines
  168. #            b) if current line is a CONTINUE that matches a DO, use the
  169. #                first corresponding DO as the previous line
  170. #
  171. #    1.    Find leading whitespace for previous line
  172. #
  173. #    2.    Increase whitespace if previous line starts a block, i.e.,
  174. #            a) DO loop
  175. #            b) IF ... THEN 
  176. #            c) ELSE
  177. #
  178. #    3.    Decrease whitespace if current line ends a block, i.e.,
  179. #            a) ELSE || ENDIF || END IF || ENDDO || END DO
  180. #            b) <linenum> CONTINUE matching a preceding DO
  181. #
  182. #        or if previous line ends a DO loop on an executable statement, i.e.,
  183. #            c) <linenum> (not CONTINUE) matching a preceding DO
  184. #
  185. proc FortindentLine {} {
  186.     set subPat {^[^c][ \ta-z*0-9]*(subroutine|.*function|entry)[ \t]+([a-z0-9_]+)}
  187.     set bolPat {^[^c\n\r][ \t]*[^ \t\n\r][^\r\n]*$}
  188.     set mtPat {^[ \t]*$}
  189.     set tab "    "
  190.  
  191.     set contPat {^     ([^ \t\n\r])[^\r\n]*$}
  192.     set lnumPat {^([ \t]*)([0-9]*)([ \t]*)(.*)$}
  193.     set comPat {^cc*([ \t]*)(.*)$}
  194.     set comPat1 {^cc*([ \t]*)(.*[^ \t])[ \t]*$}
  195.     set doPat {^[^c\n\r][ \t]*do[ \t]+}
  196.     set tailPat {[^\r\n]*$}
  197.  
  198.     set bobPat {^(if[^\n\r]*then|else|do)}
  199.     set eobPat {^(end[ \t]*if|end[ \t]*do|else)}
  200.     
  201.     set bol [lineStart [getPos]]
  202.     set eol [expr [nextLineStart $bol] - 1]
  203.     
  204.     # find the beginning of the current routine
  205.     #
  206.     if {![catch {search -f 0 -r 1 -m 0 -i 1 $subPat $bol} sublst]} {
  207.          set subLine [eval getText $sublst]
  208. #        alertnote "subLine: \/$subLine\/"
  209.         set top [lindex $sublst 0]
  210.     } else {
  211.         set top 0
  212.     } 
  213.  
  214.     set thisLine [getText $bol $eol]
  215.     
  216.     # Is the current line a comment line...
  217.     #        
  218.     if {[regexp $comPat $thisLine allofit pre body]} {
  219.         set body [string trimright $body]
  220. #        alertnote "line: \/$pre\/$body\/"
  221.         set lwhite "c     "
  222.         set lnum ""
  223.         
  224.         replaceText $bol $eol $lwhite$body
  225.     
  226.     # ... or a line of code (possibly empty)?
  227.     #    
  228.     } elseif {[regexp $lnumPat $thisLine allofit pre lnum post body]} {
  229.         set body [string trimright $body]
  230. #        alertnote "line: \/$pre\/$lnum\/$post\/$body\/"
  231.         
  232.         # is it a continuation line?
  233.         #
  234.         if {(![regexp {\t} $pre]) && ([string length $pre] == 5)} {
  235.                 set cont [string index $lnum$post$body 0]
  236.                 set body [string trimleft [string range $lnum$post$body 1 end]]
  237.         } else {
  238.             set cont {}
  239.         }
  240. #        alertnote "cont: \/$cont\/"
  241.  
  242.         # if there's a line number, check for a matching DO statement ...
  243.         #
  244.         if {[string length $lnum] &&
  245.                 ![catch {search -s -f 1 -r 1 -i 1 -l [expr $bol -1] $doPat$lnum $top} dolst]} {
  246.               set prevLine [eval getText $dolst]
  247.               set enddo 1
  248.          
  249.         # ... otherwise find the first preceding non-comment, non-continuation line
  250.         #
  251.         } else {        
  252.             set lst [search -s -f 0 -r 1 -i 1 $bolPat [expr $bol-1]]
  253.             set prevLine [eval getText $lst]
  254.             while {[regexp $contPat $prevLine]} {
  255.                 set lst [search -s -f 0 -r 1 -i 1 $bolPat [expr [lindex $lst 0] - 1]]
  256.                 set prevLine [eval getText $lst]
  257.             }
  258.               set enddo 0
  259.         }
  260. #        alertnote "prevLine: \/$prevLine\/"
  261.     
  262.         # get whitespace for preceding line (ignoring linenums)
  263.         #
  264.         if {[regexp $lnumPat $prevLine allofit pre0 lnum0 post0 body0]} {
  265. #            alertnote "prevLine: \/$pre0\/$lnum0\/$post0\/$body0\/"
  266.  
  267.             if {[string length $lnum0]} {
  268.                 if {[string index $post0 0] == $tab} {
  269.                     set lwhite $post0
  270.                 } else {
  271.                     regsub -all {[0-9]} $pre0$lnum0$post0 { } lwhite
  272.                 }
  273.                 
  274.             } else {
  275.                 set lwhite $pre0
  276.             }
  277. #            alertnote "lwhite: \/$lwhite\/ len: [string length $lwhite]"
  278.             
  279.             # if there's a line number and it's not a CONTINUE, 
  280.             # then check for a matching DO statement
  281.             #
  282.             if {[string length $lnum0] && ![regexp $contPat $body0] &&
  283.                 ![catch {search -s -f 0 -r 1 -i 1 -l $top $doPat$lnum0 [expr $lst -1]} dolst]} {
  284.     
  285.                  set doLine0 [eval getText $dolst]
  286. #                alertnote "doLine0: \/$doLine0\/"
  287.  
  288.             }    
  289.             
  290.             # If the preceeding line begins a block (IF-THEN, DO, or ELSE),
  291.             # then increase the whitespace
  292.             #    
  293.             if {[regexp $bobPat $body0]} {
  294.                 set lwhite "$lwhite   "
  295.             }
  296.         }
  297.  
  298.         # if this line ends a block, decrease the whitespace
  299.         #
  300.         if {[regexp $eobPat $body] || $enddo} {
  301.             set lwlen [expr [string length $lwhite] - 4]
  302.             set lwhite [string range $lwhite 0 $lwlen]
  303.         } 
  304.  
  305.         if {[string length $lnum]} {
  306.             if {[string index $lwhite 0] != $tab} {
  307.                 set lwhite [string range $lwhite [expr [string length $lnum] +1] end]
  308.             }
  309.             set lnum " $lnum"
  310.         }
  311. #        alertnote "lwhite: \/$lwhite\/ len: [string length $lwhite]"
  312.  
  313.         if {[string length $cont]} {
  314.             replaceText $bol $eol "     $cont$lwhite$body"    
  315.         } else {
  316.             replaceText $bol $eol $lnum$lwhite$body
  317.         }
  318.     }
  319.  
  320.     goto [expr $bol + [string length $lnum$lwhite]]
  321. }
  322.  
  323.