home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-15 | 9.1 KB | 287 lines | [TEXT/ALFA] |
- #############################################################################
- # General utility procs (originally for TeX, BibTeX and Perl modes)
- #
- # Authors: Tom Pollard <pollard@chem.columbia.edu>
- # Tom Scavo <trscavo@syr.edu>
- #
- #############################################################################
-
- #############################################################################
- # Take any valid Macintosh filespec as input, and return the
- # corresponding absolute filespec. Filenames without an explicit
- # folder are resolved relative to the folder of the current document.
- #
- proc absolutePath {filename} {
- set name [file tail $filename]
- set subdir [file dirname $filename]
- if { [string length $subdir] > 0 && [string index $subdir 0] != ":" } {
- set dir ""
- } else {
- set dir [file dirname [lindex [winNames -f] 0]]
- }
- return "$dir$subdir:$name"
- }
-
- #############################################################################
- # Open the file specified by the full pathname "$filename"
- # If it's already open, just switch to it without any fuss.
- #
- proc openFileQuietly {filename} {
- if {[lsearch [winNames -f] $filename] >= 0} {
- bringToFront $filename
- } elseif {[file exists $filename]} {
- edit -w $filename
- } else {
- error "Couldn''t find \"$filename\""
- }
- }
-
- #############################################################################
- # Returns the position in $filename of the sought-after string.
- # A value of -1 is returned if the file or string are missing.
- #
- proc searchInFile {filename searchString} {
- if {[lsearch [winNames -f] $filename] >= 0} {
- set fileText [getText -w $filename 0 [maxPos -w $filename]]
-
- } elseif {[file exists $filename]} {
- set fd [open $filename]
- set fileText [read $fd]
- close $fd
-
- } else {
- return -1
- }
-
- # Search the file for the search string, returning position of
- # first match if found.
- message "searching $filename..."
- if {[regexp -indices $searchString $fileText mtch]} {
- return [lindex $mtch 0]
- } else {
- return -1
- }
- }
-
- #############################################################################
- # Read and return the complete contents of the specified file.
- #
- proc readFile {fileName} {
- if {[file exists $fileName] && [file readable $fileName]} {
- set fileid [open $fileName "r"]
- set contents [read $fileid]
- close $fileid
- return $contents
- } else {
- error "No readable file found"
- }
- }
-
- #############################################################################
- # Highlight (select) a particular line in the designated file, opening the
- # file if necessary. Returns the full name of the buffer containing the
- # opened file. If provided, a message is displayed on the status line.
- #
- proc gotoFileLine {fname line {mesg {}}} {
- if {[expr {[lsearch [winNames -f] "*$fname"] >= 0}]} {
- bringToFront $fname
- } elseif {[expr {[lsearch [winNames] "*$fname"] >= 0}]} {
- bringToFront $fname
- } elseif {[file exists $fname]} {
- edit $fname
- newMode Perl
- catch {shrinkWindow 1}
- } else {
- alertnote "File \" $fname \" not found."
- return
- }
- set pos [rowColToPos $line 0]
- select [lineStart $pos] [nextLineStart $pos]
- if {[string length $mesg]} { message $mesg }
- return [lindex [winNames -f] 0]
- }
-
- ###########################################################################
- # Parse a string into "word"s, which include blocks of non-space text,
- # double- and single-quoted strings, and blocks of text enclosed in
- # balanced parentheses or curly brackets.
- #
- # If a word is delimited by a quote or paren character (\", \', \(, or \{),
- # then _that_ particular delimiter may be included within the word if it is
- # backslash-quoted, as above. No other characters are special or need quoting
- # with that word. The quoted delimiters are unquoted in the list of words
- # returned.
- #
- proc parseWords {entry} {
- set slash "\\"
- set qslash "\\\\"
-
- set words {}
- set entry [string trim $entry]
-
- while {[string length $entry]} {
- set delim [string range $entry 0 0]
- set entry [string range $entry 1 end]
-
- # regexp $endPat matches the end of the word
- # $openPat matches the open delimiter
- # $unescPat matches escaped instances of the open/close delimiters
- #
- # $type == "quote" means open/close delimiters are the same
- # == "paren" means there's a close delimiter and nesting is possible
- # == "unquoted" means the word is delimited by whitespace.
- #
- if {$delim == {"}} { set endPat {^([^"]*)"}
- set unescPat {\\(")}
- set type quote
-
- } elseif {$delim == {'}} { set endPat {^([^']*)'}
- set unescPat {\\(')}
- set type quote
-
- } elseif {$delim == "\{"} { set endPat "^(\[^\}\]*)\}"
- set openPat "\{"
- set unescPat "\\\\(\[\{\}\])"
- set type paren
-
- } elseif {$delim == "("} { set endPat {^([^)]*)\)}
- set openPat {(}
- set unescPat {\\([()])}
- set type paren
-
- } else { set type unquoted
- }
-
- if {$type == "quote"} {
- set ck $qslash
- set fld ""
- while {$ck == $qslash} {
- set ok [regexp -indices $endPat $entry mtch sub1]
- if {$ok} {
- append fld [string range $entry [lindex $mtch 0] [lindex $mtch 1]]
- set ck $slash[string range $entry [lindex $sub1 1] [lindex $sub1 1]]
- set pos [expr 1 + [lindex $mtch 1]]
- set entry [string range $entry $pos end]
- } else {
- error "Couldn't match $delim as field delimiter"
- }
- }
- set pos [expr [string length $fld] - 2]
- set fld [string range $fld 0 $pos]
- regsub -all $unescPat $fld {\1} fld
-
- } elseif {$type == "paren"} {
-
- set nopen 1
- set nclose 0
- set fld ""
- while {$nopen - $nclose != 0} {
- set ok [regexp -indices $endPat $entry mtch sub1]
- if {$ok} {
- append fld [string range $entry [lindex $mtch 0] [lindex $mtch 1]]
- set ck $slash[string range $entry [lindex $sub1 1] [lindex $sub1 1]]
- set entry [string range $entry [expr 1 + [lindex $mtch 1]] end]
- regsub -all $unescPat $fld {} fld1
- set nopen [llength [split $fld1 $openPat]]
- if {$ck != $qslash} { incr nclose }
- } else {
- error "Couldn't match $delim as field delimiter"
- }
- }
- set pos [expr [string length $fld] - 2]
- set fld [string range $fld 0 $pos]
- regsub -all $unescPat $fld {\1} fld
-
- } elseif {$type == "unquoted"} {
-
- set entry ${delim}${entry}
- set ok [regexp -indices {^([^ ]*)} $entry mtch sub1]
- if {$ok} {
- set fld [string range $entry [lindex $sub1 0] [lindex $sub1 1]]
- set pos [expr 1 + [lindex $mtch 1]]
- set entry [string range $entry $pos end]
- } else {
- set fld ""
- set entry ""
- }
- } else {
- error "parseWords: unrecognized case"
- }
-
- lappend words $fld
- set entry [string trimleft $entry]
- }
- return $words
- }
-
- #############################################################################
- # This is a generally useful proc that builds a hierarchical menu
- # from the files in a given folder and all subfolders. As the menu is
- # built, the pathnames of the various files are saved in the array
- # indicated by $filePaths. The index of the file's path in this array
- # is formed by concatenating the submenu name and filename, allowing the
- # pathname to be retrieved by the procedure $proc when the menu item is
- # selected.
- #
- proc buildSubMenu {folder name proc filePaths {subMenuDepth 3}} {
- global $filePaths
- if {[file exists $folder]} {
- if {![file isdirectory $folder]} {
- set folder "[file dirname $folder]:"
- }
- if {[string length [file tail $folder]] > 0} {
- set folder "$folder:"
- }
- if {$name == 0} {
- set name [file tail [file dirname $folder]]
- }
- if {$proc == 0} {
- set pproc ""
- } else {
- set pproc "-p $proc"
- }
- set menu {}
- incr subMenuDepth -1
- set filenames [glob -nocomplain $folder\*]
- if {[llength $filenames] > 0} {
- foreach m $filenames {
- if {[file isdirectory $m] && $subMenuDepth > 0} {
- lappend menu [buildSubMenu ${m}: 0 $proc $filePaths $subMenuDepth]
- } elseif {[file isfile $m]} {
- set fname [file tail $m]
- lappend menu $fname
- set ${filePaths}($name:$fname) $m
- }
- }
- }
- return [concat {menu -m -n} [list $name] $pproc [list $menu]]
- } else {
- alertnote "Folder \"$folder\" is missing"
- return {}
- }
- }
-
- #############################################################################
- # Return a list of all subfolders found within $folder,
- # down to some maximum recursion depth. The top-level
- # folder is not included in the returned list.
- #
- proc listSubfolders {folder {depth 3}} {
- set folders {}
- if {$depth > 0} {
- incr depth -1
- if {[string length [file tail $folder]] > 0} {
- set folder "$folder:"
- }
- foreach m [glob -nocomplain $folder\*] {
- if {[file isdirectory $m]} {
- set folders [concat $folders [list $m]]
- set folders [concat $folders [listSubfolders ${m}: $depth]]
- }
- }
- }
- return $folders
- }
-
- #############################################################################
-