home *** CD-ROM | disk | FTP | other *** search
- # regexpviewer.tcl -- regular expression viewer
-
- # Copyright 2004 David N. Welton <davidw@dedasys.com>
-
- # $Id: regexpviewer.tcl,v 1.1.1.1 2004/03/23 21:04:21 davidw Exp $
-
- package require Tk
- package require msgcat
- namespace import msgcat::*
-
- set auto_path [linsert $auto_path 0 .]
- package require style::lobster
- package require gridinfo
- package require about
- namespace import gridinfo::*
-
- namespace eval review {
- variable matchall
- }
-
- # review::getopts --
- #
- # Get options to insert into regexp command.
-
- proc review::getopts {} {
- set vars {all nocase linestop line lineanchor}
- set retval {}
- foreach v $vars {
- variable $v
- if { [set $v] == 1 } {
- lappend retval -$v
- }
- }
- return $retval
- }
-
- namespace eval review::gui {
- variable neutralbg "\#999999"
- variable errbg "\#dd0000"
- variable matchcolor "\#00dd00"
- variable matchbg "\#99dd99"
- variable hlcolor "\#9999ff"
- variable led
- variable matchl
- wm title . "regexp viewer"
-
- font create FixedFont -size -12 -family Courier
-
- menu .mbar
- . config -menu .mbar
-
- .mbar add cascade -label [mc "File"] -underline 0 \
- -menu [menu .mbar.file -tearoff 0]
-
- .mbar add cascade -label [mc "Options"] -underline 0 \
- -menu [menu .mbar.options -tearoff 0]
-
- .mbar add command -label [mc "About"] -underline 0 \
- -command review::gui::about
-
- set FMenu .mbar.file
- set OMenu .mbar.options
-
- $FMenu add command -label [mc "Load Text"] -underline 0 \
- -command review::gui::loadtext
- # $FMenu add command -label [mc "Save File"] -underline 0 \
- # -command review::gui::savefile
- $FMenu add command -label [mc "Exit"] -underline 0 \
- -command review::gui::quit
-
- $OMenu add check -label "Match All" -variable review::all
- $OMenu add check -label "No Case" -variable review::nocase
- $OMenu add check -label "Line Stop" -variable review::linestop
- $OMenu add check -label "Newline Sensitive" -variable review::line
- $OMenu add check -label "Line Anchor" -variable review::lineanchor
-
- # text frame.
- . configure -padx 8
- . configure -pady 4
- labelframe .txtframe -text "Text"
- variable text [text .txtframe.txt -height 5 -font FixedFont \
- -yscrollcommand [list .txtframe.scroll set]]
- set textscroll [scrollbar .txtframe.scroll -command [list $text yview]]
- bind $text <Key> [list review::gui::altered]
-
- # regular expression frame.
- labelframe .reframe -text "Regular Expression"
- variable re [text .reframe.re -height 2 -font FixedFont \
- -yscrollcommand [list .reframe.scroll set]]
- set rescroll [scrollbar .reframe.scroll -command [list $re yview]]
- bind $re <Key> [list review::gui::altered]
-
- # match frame
- labelframe .matchframe -text "Match"
- set matchl [label .matchframe.ml -text "" -justify left]
- set led [canvas .matchframe.mc -height 32 -width 32]
- .matchframe.mc create oval 4 4 28 28
- .matchframe.mc itemconfigure 1 -fill $neutralbg
-
- set run [button .run -text "Execute Regular Expression" \
- -command review::gui::run]
-
- # grid text frame
- grid .txtframe -sticky news -columnspan 2 -padx 5 -pady 3
- grid $text $textscroll -sticky news
- grid columnconfigure .txtframe [column $text] -weight 1
- grid rowconfigure .txtframe [row $text] -weight 1
-
- # grid re frame
- grid .reframe -sticky news -columnspan 2 -padx 5 -pady 3
- grid $re $rescroll -sticky news
- grid columnconfigure .reframe [column $re] -weight 1
- grid rowconfigure .reframe [row $re] -weight 1
-
- # grid match frame
- grid .matchframe $run -sticky nws -padx 5 -pady 3
- grid configure $run -sticky nes
- grid .matchframe.mc .matchframe.ml -sticky nws
-
- grid columnconfigure . [column .matchframe] -weight 1
- grid rowconfigure . [row .txtframe] -weight 5
- grid rowconfigure . [row .reframe] -weight 5
- # grid rowconfigure . [row .matchframe] -weight 1
- }
-
- # review::gui::run --
- #
- # Run the text through the regular expression.
-
- proc review::gui::run {} {
- variable text
- variable re
- set txt [string trimright [$text get 0.0 end]]
- set rexp [string trimright [$re get 0.0 end]]
- if { [catch {
- set regexp "regexp [review::getopts] -inline -indices -- {$rexp} {$txt}"
- #puts $regexp
- set resl [eval $regexp]
- } err] } {
- review::gui::nomatch $err
- return
- }
- #puts "Results $resl"
- if { [llength $resl] < 1 } {
- review::gui::nomatch
- } else {
- review::gui::match $resl
- }
- }
-
- # review::gui::nomatch --
- #
- # This is called when there is no match, either because of an
- # error (1 arg) or because the regexp just doesn't match (no
- # args).
-
- proc review::gui::nomatch {args} {
- variable errbg
- variable led
- variable matchl
- variable text
-
- $led itemconfigure 1 -fill $errbg
- if { [llength $args] != 0 } {
- $matchl configure -text "Error:\n[lindex $args 0]"
- } else {
- $matchl configure -text "No match"
- }
- $text tag delete allmatch
- }
-
- # review::gui::match --
- #
- # This is called when the regexp matches. As a side effect, it
- # creates tags in the text text widget and the regexp text
- # widget.
-
- proc review::gui::match {indices} {
- variable led
- variable matchl
- variable matchbg
- variable matchcolor
- variable text
- variable re
- $led itemconfigure 1 -fill $matchcolor
- $matchl configure -text "Match"
- array set matches [review::gui::creatematchbindings \
- [string trimright [$re get 0.0 end]]]
- set matchnum [array size matches]
-
- set x 0
- # We loop through each set of matches, which is equivalent to
- # entirematch match1 match2 matchN
- while { $x < [llength $indices] } {
- # This is the entire match part.
- foreach {start end} [lindex $indices $x] {break}
- incr end
- $text tag add allmatch "1.0 + $start chars" "1.0 + $end chars"
- $text tag configure allmatch -background $matchbg
- set i 1
- # Now loop through the indices of the matches in the text, and
- # mark them up.
- foreach {idx} [lrange $indices [expr {$x + 1}] [expr {$x + $matchnum}]] {
- set start [lindex $idx 0]
- set end [lindex $idx 1]
- incr end
- $text tag add match$i "1.0 + $start chars" "1.0 + $end chars"
- incr i
- }
-
- set i 1
- # Now loop through the () expressions in the regexp itself and
- # set them up.
- foreach {m idxs} [array get matches] {
- set start [lindex $idxs 0]
- set end [lindex $idxs 1]
- incr end
- $re tag add rematch$i "1.0 + $start chars" "1.0 + $end chars"
- $re tag bind rematch$i <Motion> [list review::gui::showtag rematch$i match$i]
- $re tag bind rematch$i <Leave> [list review::gui::showtag rematch$i]
- incr i
- }
- incr x
- incr x $matchnum
- }
- }
-
-
- # review::gui::creatematchbindings --
- #
- # Gets the indexes of matching parenthesis in a regexp, so that
- # we can highlight sub-matches.
-
- proc review::gui::creatematchbindings {rexp} {
- variable re
- variable text
- variable hlcolor
- set i 0
- set relen [string length $rexp]
- array set matches {}
- set matchno 1
- while {$i < $relen} {
- switch -exact -- [string index $rexp $i] {
- "\\" {
- set next [string index $rexp [expr {$i + 1}]]
- if { $next == "(" || $next == ")" } {
- incr i
- }
- }
- "(" {
- lappend matchstack $matchno
- lappend matches($matchno) $i
- incr matchno
- }
- ")" {
- set tmpmatchno [lindex $matchstack end]
- lappend matches($tmpmatchno) $i
- set matchstack [lreplace $matchstack end end]
- }
- default {}
- }
- incr i
- }
- return [array get matches]
- }
-
- # review::gui::showtag --
- #
- # This is the binding called when the mouse goes over the paren
- # regions in the regexp.
-
- proc review::gui::showtag {args} {
- variable re
- variable text
- variable matchbg
- variable hlcolor
- set tagname [lindex $args 1]
- set retag [lindex $args 0]
- foreach tag [$text tag names] {
- if { [string match "match*" $tag] } {
- $text tag configure $tag -background $matchbg
- }
- }
- foreach tag [$re tag names] {
- if { [string match "rematch*" $tag] } {
- $re tag configure $tag -background white
- }
- }
-
- if {$tagname != "" } {
- $text tag configure $tagname -background $hlcolor
- $text tag raise $tagname
- $re tag configure $retag -background $hlcolor
- }
- }
-
- # review::gui::altered --
- #
- # This is the binding called when the text or regexp is
- # modified. It wipes out all the 'match' stuff.
-
- proc review::gui::altered {} {
- variable text
- variable re
- variable led
- variable matchl
- variable neutralbg
-
- foreach tag [$text tag names] {
- if { [string match "match*" $tag] || $tag == "allmatch" } {
- $text tag delete $tag
- }
- }
- foreach tag [$re tag names] {
- if { [string match "rematch*" $tag] } {
- $re tag delete $tag
- }
- }
-
- $led itemconfigure 1 -fill $neutralbg
- $matchl configure -text ""
- }
-
- # review::gui::loadtext --
- #
- # Loads a file into the text text widget.
-
- proc review::gui::loadtext {} {
- variable text
- set fn [tk_getOpenFile]
- if { $fn == "" } { return }
- set fl [open $fn]
- set data [read $fl]
- close $fl
- $text delete 0.0 end
- $text insert end $data
- }
-
- # review::gui::about --
- #
- # About dialog.
-
- proc review::gui::about {} {
- about::about "regexpviewer" "David N. Welton <davidw@dedasys.com>" {
- "Visit http://dedasys.com for other programs!"
- }
- }
-
- # review::gui::quit --
- #
- # See if you can figure this one out for yourselves:-)
-
- proc review::gui::quit {} {
- exit
- }