Julian Noble
3 months ago
78 changed files with 10404 additions and 769 deletions
@ -1,2 +1,2 @@
|
||||
if {![package vsatisfies [package provide Tcl] 8.2]} {return} |
||||
package ifneeded control 0.1.3 [list source [file join $dir control.tcl]] |
||||
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return} |
||||
package ifneeded control 0.1.4 [list source [file join $dir control.tcl]] |
||||
|
@ -0,0 +1,207 @@
|
||||
# -*- tcl -*- |
||||
# ### ### ### ######### ######### ######### |
||||
## Copyright (c) 2008-2009 ActiveState Software Inc., Andreas Kupries |
||||
## 2016 Andreas Kupries |
||||
## BSD License |
||||
## |
||||
# Package to help the writing of file decoders. Provides generic |
||||
# low-level support commands. |
||||
|
||||
package require Tcl 8.5 9 |
||||
|
||||
namespace eval ::fileutil::decode { |
||||
namespace export mark go rewind at |
||||
namespace export byte short-le long-le nbytes skip |
||||
namespace export unsigned match recode getval |
||||
namespace export clear get put putloc setbuf |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## |
||||
|
||||
proc ::fileutil::decode::open {fname} { |
||||
variable chan |
||||
set chan [::open $fname r] |
||||
fconfigure $chan \ |
||||
-translation binary \ |
||||
-encoding binary \ |
||||
-eofchar {} |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::close {} { |
||||
variable chan |
||||
::close $chan |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## |
||||
|
||||
proc ::fileutil::decode::mark {} { |
||||
variable chan |
||||
variable mark |
||||
set mark [tell $chan] |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::go {to} { |
||||
variable chan |
||||
seek $chan $to start |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::rewind {} { |
||||
variable chan |
||||
variable mark |
||||
if {$mark == {}} { |
||||
return -code error \ |
||||
-errorcode {FILE DECODE NO MARK} \ |
||||
"No mark to rewind to" |
||||
} |
||||
seek $chan $mark start |
||||
set mark {} |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::at {} { |
||||
variable chan |
||||
return [tell $chan] |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## |
||||
|
||||
proc ::fileutil::decode::byte {} { |
||||
variable chan |
||||
variable mask 0xff |
||||
variable val [read $chan 1] |
||||
binary scan $val c val |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::short-le {} { |
||||
variable chan |
||||
variable mask 0xffff |
||||
variable val [read $chan 2] |
||||
binary scan $val s val |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::long-le {} { |
||||
variable chan |
||||
variable mask 0xffffffff |
||||
variable val [read $chan 4] |
||||
binary scan $val i val |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::nbytes {n} { |
||||
variable chan |
||||
variable mask {} |
||||
variable val [read $chan $n] |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::skip {n} { |
||||
variable chan |
||||
#read $chan $n |
||||
seek $chan $n current |
||||
return |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## |
||||
|
||||
proc ::fileutil::decode::unsigned {} { |
||||
variable val |
||||
if {$val >= 0} return |
||||
variable mask |
||||
if {$mask eq {}} { |
||||
return -code error \ |
||||
-errorcode {FILE DECODE ILLEGAL UNSIGNED} \ |
||||
"Unsigned not possible here" |
||||
} |
||||
set val [format %u [expr {$val & $mask}]] |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::match {eval} { |
||||
variable val |
||||
|
||||
#puts "Match: Expected $eval, Got: [format 0x%08x $val]" |
||||
|
||||
if {$val == $eval} {return 1} |
||||
rewind |
||||
return 0 |
||||
} |
||||
|
||||
proc ::fileutil::decode::recode {cmdpfx} { |
||||
variable val |
||||
lappend cmdpfx $val |
||||
set val [uplevel 1 $cmdpfx] |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::getval {} { |
||||
variable val |
||||
return $val |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## |
||||
|
||||
proc ::fileutil::decode::clear {} { |
||||
variable buf {} |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::get {} { |
||||
variable buf |
||||
return $buf |
||||
} |
||||
|
||||
proc ::fileutil::decode::setbuf {list} { |
||||
variable buf $list |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::put {name} { |
||||
variable buf |
||||
variable val |
||||
lappend buf $name $val |
||||
return |
||||
} |
||||
|
||||
proc ::fileutil::decode::putloc {name} { |
||||
variable buf |
||||
variable chan |
||||
lappend buf $name [tell $chan] |
||||
return |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## |
||||
|
||||
namespace eval ::fileutil::decode { |
||||
# Stream to read from |
||||
variable chan {} |
||||
|
||||
# Last value read from the stream, or modified through decoder |
||||
# operations. |
||||
variable val {} |
||||
|
||||
# Remembered location in the stream |
||||
variable mark {} |
||||
|
||||
# Buffer for accumulating structured results |
||||
variable buf {} |
||||
|
||||
# Mask for trimming a value to unsigned. |
||||
# Size-dependent |
||||
variable mask {} |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## Ready |
||||
package provide fileutil::decode 0.2.2 |
||||
return |
@ -0,0 +1,28 @@
|
||||
# ### ### ### ######### ######### ######### |
||||
## |
||||
# (c) 2007 Andreas Kupries. |
||||
|
||||
# Multi file operations. Singleton based on the multiop processor. |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## Requisites |
||||
|
||||
package require fileutil::multi::op |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## API & Implementation |
||||
|
||||
namespace eval ::fileutil {} |
||||
|
||||
# Create the multiop processor object and make its do method the main |
||||
# command of this package. |
||||
::fileutil::multi::op ::fileutil::multi::obj |
||||
|
||||
proc ::fileutil::multi {args} { |
||||
return [uplevel 1 [linsert $args 0 ::fileutil::multi::obj do]] |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## Ready |
||||
|
||||
package provide fileutil::multi 0.2 |
@ -0,0 +1,645 @@
|
||||
# ### ### ### ######### ######### ######### |
||||
## |
||||
# (c) 2007-2008 Andreas Kupries. |
||||
|
||||
# DSL allowing the easy specification of multi-file copy and/or move |
||||
# and/or deletion operations. Alternate names would be scatter/gather |
||||
# processor, or maybe even assembler. |
||||
|
||||
# Examples: |
||||
# (1) copy |
||||
# into [installdir_of tls] |
||||
# from c:/TDK/PrivateOpenSSL/bin |
||||
# the *.dll |
||||
# |
||||
# (2) move |
||||
# from /sources |
||||
# into /scratch |
||||
# the * |
||||
# but not *.html |
||||
# (Alternatively: except for *.html) |
||||
# |
||||
# (3) into /scratch |
||||
# from /sources |
||||
# move |
||||
# as pkgIndex.tcl |
||||
# the index |
||||
# |
||||
# (4) in /scratch |
||||
# remove |
||||
# the *.txt |
||||
|
||||
# The language is derived from the parts of TclApp's option language |
||||
# dealing with files and their locations, yet not identical. In parts |
||||
# simplified, in parts more capable, keyword names were changed |
||||
# throughout. |
||||
|
||||
# Language commands |
||||
|
||||
# From the examples |
||||
# |
||||
# into DIR : Specify destination directory. |
||||
# in DIR : See 'into'. |
||||
# from DIR : Specify source directory. |
||||
# the PATTERN (...) : Specify files to operate on. |
||||
# but not PATTERN : Specify exceptions to 'the'. |
||||
# but exclude PATTERN : Specify exceptions to 'the'. |
||||
# except for PATTERN : See 'but not'. |
||||
# as NAME : New name for file. |
||||
# move : Move files. |
||||
# copy : Copy files. |
||||
# remove : Delete files. |
||||
# |
||||
# Furthermore |
||||
# |
||||
# reset : Force to defaults. |
||||
# cd DIR : Change destination to subdirectory. |
||||
# up : Change destination to parent directory. |
||||
# ( : Save a copy of the current state. |
||||
# ) : Restore last saved state and make it current. |
||||
|
||||
# The main active element is the command 'the'. In other words, this |
||||
# command not only specifies the files to operate on, but also |
||||
# executes the operation as defined in the current state. All other |
||||
# commands modify the state to set the operation up, and nothing |
||||
# else. To allow for a more natural syntax the active command also |
||||
# looks ahead for the commands 'as', 'but', and 'except', and executes |
||||
# them, like qualifiers, so that they take effect as if they had been |
||||
# written before. The command 'but' and 'except use identical |
||||
# constructions to handle their qualifiers, i.e. 'not' and 'for'. |
||||
|
||||
# Note that the fact that most commands just modify the state allows |
||||
# us to use more off forms as specifications instead of just natural |
||||
# language sentences For example the example 2 can re-arranged into: |
||||
# |
||||
# (5) from /sources |
||||
# into /scratch |
||||
# but not *.html |
||||
# move |
||||
# the * |
||||
# |
||||
# and the result is still a valid specification. |
||||
|
||||
# Further note that the information collected by 'but', 'except', and |
||||
# 'as' is automatically reset after the associated 'the' was |
||||
# executed. However no other state is reset in that manner, allowing |
||||
# the user to avoid repetitions of unchanging information. Lets us for |
||||
# example merge the examples 2 and 3. The trivial merge is: |
||||
|
||||
# (6) move |
||||
# into /scratch |
||||
# from /sources |
||||
# the * |
||||
# but not *.html not index |
||||
# move |
||||
# into /scratch |
||||
# from /sources |
||||
# the index |
||||
# as pkgIndex.tcl |
||||
# |
||||
# With less repetitions |
||||
# |
||||
# (7) move |
||||
# into /scratch |
||||
# from /sources |
||||
# the * |
||||
# but not *.html not index |
||||
# the index |
||||
# as pkgIndex.tcl |
||||
|
||||
# I have not yet managed to find a suitable syntax to specify when to |
||||
# add a new extension to the moved/copied files, or have to strip all |
||||
# extensions, a specific extension, or even replace extensions. |
||||
|
||||
# Other possibilities to muse about: Load the patterns for 'not'/'for' |
||||
# from a file ... Actually, load the whole exceptions from a file, |
||||
# with its contents a proper interpretable word list. Which makes it |
||||
# general processing of include files. |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## Requisites |
||||
|
||||
# This processor uses the 'wip' word list interpreter as its |
||||
# foundation. |
||||
|
||||
package require fileutil ; # File testing |
||||
package require snit ; # OO support |
||||
package require struct::stack ; # Context stack |
||||
package require wip ; # DSL execution core |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## API & Implementation |
||||
|
||||
snit::type ::fileutil::multi::op { |
||||
# ### ### ### ######### ######### ######### |
||||
## API |
||||
|
||||
constructor {args} {} ; # create processor |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## API - Implementation. |
||||
|
||||
constructor {args} { |
||||
install stack using struct::stack ${selfns}::stack |
||||
$self wip_setup |
||||
|
||||
# Mapping dsl commands to methods. |
||||
defdva \ |
||||
reset Reset ( Push ) Pop \ |
||||
into Into in Into from From \ |
||||
cd ChDir up ChUp as As \ |
||||
move Move copy Copy remove Remove \ |
||||
but But not Exclude the The \ |
||||
except Except for Exclude exclude Exclude \ |
||||
to Into -> Save the-set TheSet \ |
||||
recursive Recursive recursively Recursive \ |
||||
for-win ForWindows for-unix ForUnix \ |
||||
for-windows ForWindows expand Expand \ |
||||
invoke Invoke strict Strict !strict NotStrict \ |
||||
files Files links Links all Everything \ |
||||
dirs Directories directories Directories \ |
||||
state? QueryState from? QueryFrom into? QueryInto \ |
||||
excluded? QueryExcluded as? QueryAs type? QueryType \ |
||||
recursive? QueryRecursive operation? QueryOperation \ |
||||
strict? QueryStrict !recursive NotRecursive |
||||
|
||||
$self Reset |
||||
runl $args |
||||
return |
||||
} |
||||
|
||||
destructor { |
||||
$mywip destroy |
||||
return |
||||
} |
||||
|
||||
method do {args} { |
||||
return [runl $args] |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## DSL Implementation |
||||
wip::dsl |
||||
|
||||
# General reset of processor state |
||||
method Reset {} { |
||||
$stack clear |
||||
set base "" |
||||
set alias "" |
||||
set op "" |
||||
set recursive 0 |
||||
set src "" |
||||
set excl "" |
||||
set types {} |
||||
set strict 0 |
||||
return |
||||
} |
||||
|
||||
# Stack manipulation |
||||
method Push {} { |
||||
$stack push [list $base $alias $op $opcmd $recursive $src $excl $types $strict] |
||||
return |
||||
} |
||||
|
||||
method Pop {} { |
||||
if {![$stack size]} { |
||||
return -code error {Stack underflow} |
||||
} |
||||
foreach {base alias op opcmd recursive src excl types strict} [$stack pop] break |
||||
return |
||||
} |
||||
|
||||
# Destination directory |
||||
method Into {dir} { |
||||
if {$dir eq ""} {set dir [pwd]} |
||||
if {$strict && ![fileutil::test $dir edr msg {Destination directory}]} { |
||||
return -code error $msg |
||||
} |
||||
set base $dir |
||||
return |
||||
} |
||||
|
||||
method ChDir {dir} { $self Into [file join $base $dir] ; return } |
||||
method ChUp {} { $self Into [file dirname $base] ; return } |
||||
|
||||
# Detail |
||||
method As {fname} { |
||||
set alias [ForceRelative $fname] |
||||
return |
||||
} |
||||
|
||||
# Operations |
||||
method Move {} { set op move ; return } |
||||
method Copy {} { set op copy ; return } |
||||
method Remove {} { set op remove ; return } |
||||
method Expand {} { set op expand ; return } |
||||
|
||||
method Invoke {cmdprefix} { |
||||
set op invoke |
||||
set opcmd $cmdprefix |
||||
return |
||||
} |
||||
|
||||
# Operation qualifier |
||||
method Recursive {} { set recursive 1 ; return } |
||||
method NotRecursive {} { set recursive 0 ; return } |
||||
|
||||
# Source directory |
||||
method From {dir} { |
||||
if {$dir eq ""} {set dir [pwd]} |
||||
if {![fileutil::test $dir edr msg {Source directory}]} { |
||||
return -code error $msg |
||||
} |
||||
set src $dir |
||||
return |
||||
} |
||||
|
||||
# Exceptions |
||||
method But {} { run_next_while {not exclude} ; return } |
||||
method Except {} { run_next_while {for} ; return } |
||||
|
||||
method Exclude {pattern} { |
||||
lappend excl $pattern |
||||
return |
||||
} |
||||
|
||||
# Define the files to operate on, and perform the operation. |
||||
method The {pattern} { |
||||
run_next_while {as but except exclude from into in to files dirs directories links all} |
||||
|
||||
switch -exact -- $op { |
||||
invoke {Invoke [Resolve [Remember [Exclude [Expand $src $pattern]]]]} |
||||
move {Move [Resolve [Remember [Exclude [Expand $src $pattern]]]]} |
||||
copy {Copy [Resolve [Remember [Exclude [Expand $src $pattern]]]]} |
||||
remove {Remove [Remember [Exclude [Expand $base $pattern]]] } |
||||
expand { Remember [Exclude [Expand $base $pattern]] } |
||||
} |
||||
|
||||
# Reset the per-pattern flags of the resolution context back |
||||
# to their defaults, for the next pattern. |
||||
|
||||
set alias {} |
||||
set excl {} |
||||
set recursive 0 |
||||
return |
||||
} |
||||
|
||||
# Like 'The' above, except that the fileset is taken from the |
||||
# specified variable. Semi-complementary to 'Save' below. |
||||
# Exclusion data and recursion info do not apply for this, this is |
||||
# already implicitly covered by the set, when it was generated. |
||||
|
||||
method TheSet {varname} { |
||||
# See 'Save' for the levels we jump here. |
||||
upvar 5 $varname var |
||||
|
||||
run_next_while {as from into in to} |
||||
|
||||
switch -exact -- $op { |
||||
invoke {Invoke [Resolve $var]} |
||||
move {Move [Resolve $var]} |
||||
copy {Copy [Resolve $var]} |
||||
remove {Remove $var } |
||||
expand { |
||||
return -code error "Expansion does not make sense\ |
||||
when we already have a set of files." |
||||
} |
||||
} |
||||
|
||||
# Reset the per-pattern flags of the resolution context back |
||||
# to their defaults, for the next pattern. |
||||
|
||||
set alias {} |
||||
return |
||||
} |
||||
|
||||
# Save the last expansion result to a variable for use by future commands. |
||||
|
||||
method Save {varname} { |
||||
# Levels to jump. Brittle. |
||||
# 5: Caller |
||||
# 4: object do ... |
||||
# 3: runl |
||||
# 2: wip::runl |
||||
# 1: run_next |
||||
# 0: Here |
||||
upvar 5 $varname v |
||||
set v $lastexpansion |
||||
return |
||||
} |
||||
|
||||
# Platform conditionals ... |
||||
|
||||
method ForUnix {} { |
||||
global tcl_platform |
||||
if {$tcl_platform(platform) eq "unix"} return |
||||
# Kill the remaining code. This effectively aborts processing. |
||||
replacel {} |
||||
return |
||||
} |
||||
|
||||
method ForWindows {} { |
||||
global tcl_platform |
||||
if {$tcl_platform(platform) eq "windows"} return |
||||
# Kill the remaining code. This effectively aborts processing. |
||||
replacel {} |
||||
return |
||||
} |
||||
|
||||
# Strictness |
||||
|
||||
method Strict {} { |
||||
set strict 1 |
||||
return |
||||
} |
||||
|
||||
method NotStrict {} { |
||||
set strict 0 |
||||
return |
||||
} |
||||
|
||||
# Type qualifiers |
||||
|
||||
method Files {} { |
||||
set types files |
||||
return |
||||
} |
||||
|
||||
method Links {} { |
||||
set types links |
||||
return |
||||
} |
||||
|
||||
method Directories {} { |
||||
set types dirs |
||||
return |
||||
} |
||||
|
||||
method Everything {} { |
||||
set types {} |
||||
return |
||||
} |
||||
|
||||
# State interogation |
||||
|
||||
method QueryState {} { |
||||
return [list \ |
||||
from $src \ |
||||
into $base \ |
||||
as $alias \ |
||||
op $op \ |
||||
excluded $excl \ |
||||
recursive $recursive \ |
||||
type $types \ |
||||
strict $strict \ |
||||
] |
||||
} |
||||
method QueryExcluded {} { |
||||
return $excl |
||||
} |
||||
method QueryFrom {} { |
||||
return $src |
||||
} |
||||
method QueryInto {} { |
||||
return $base |
||||
} |
||||
method QueryAs {} { |
||||
return $alias |
||||
} |
||||
method QueryOperation {} { |
||||
return $op |
||||
} |
||||
method QueryRecursive {} { |
||||
return $recursive |
||||
} |
||||
method QueryType {} { |
||||
return $types |
||||
} |
||||
method QueryStrict {} { |
||||
return $strict |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## DSL State |
||||
|
||||
component stack ; # State stack - ( ) |
||||
variable base "" ; # Destination dir - into, in, cd, up |
||||
variable alias "" ; # Detail - as |
||||
variable op "" ; # Operation - move, copy, remove, expand, invoke |
||||
variable opcmd "" ; # Command prefix for invoke. |
||||
variable recursive 0 ; # Op. qualifier: recursive expansion? |
||||
variable src "" ; # Source dir - from |
||||
variable excl "" ; # Excluded files - but not|exclude, except for |
||||
# incl ; # Included files - the (immediate use) |
||||
variable types {} ; # Limit glob/find to specific types (f, l, d). |
||||
variable strict 0 ; # Strictness of into/Expand |
||||
|
||||
variable lastexpansion "" ; # Area for last expansion result, for 'Save' to take from. |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## Internal -- Path manipulation helpers. |
||||
|
||||
proc ForceRelative {path} { |
||||
set pathtype [file pathtype $path] |
||||
switch -exact -- $pathtype { |
||||
relative { |
||||
return $path |
||||
} |
||||
absolute { |
||||
# Chop off the first element in the path, which is the |
||||
# root, either '/' or 'x:/'. If this was the only |
||||
# element assume an empty path. |
||||
|
||||
set path [lrange [file split $path] 1 end] |
||||
if {![llength $path]} {return {}} |
||||
return [eval [linsert $path 0 file join]] |
||||
} |
||||
volumerelative { |
||||
return -code error {Unable to handle volumerelative path, yet} |
||||
} |
||||
} |
||||
|
||||
return -code error \ |
||||
"file pathtype returned unknown type \"$pathtype\"" |
||||
} |
||||
|
||||
proc ForceAbsolute {path} { |
||||
return [file join [pwd] $path] |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## Internal - Operation execution helpers |
||||
|
||||
proc Invoke {files} { |
||||
upvar 1 base base src src opcmd opcmd |
||||
uplevel #0 [linsert $opcmd end $src $base $files] |
||||
return |
||||
} |
||||
|
||||
proc Move {files} { |
||||
upvar 1 base base src src |
||||
|
||||
foreach {s d} $files { |
||||
set s [file join $src $s] |
||||
set d [file join $base $d] |
||||
|
||||
file mkdir [file dirname $d] |
||||
file rename -force $s $d |
||||
} |
||||
return |
||||
} |
||||
|
||||
proc Copy {files} { |
||||
upvar 1 base base src src |
||||
|
||||
foreach {s d} $files { |
||||
set s [file join $src $s] |
||||
set d [file join $base $d] |
||||
|
||||
file mkdir [file dirname $d] |
||||
if { |
||||
[file isdirectory $s] && |
||||
[file exists $d] && |
||||
[file isdirectory $d] |
||||
} { |
||||
# Special case: source and destination are |
||||
# directories, and the latter exists. This puts the |
||||
# source under the destination, and may even prevent |
||||
# copying at all. The semantics of the operation is |
||||
# that the source is the destination. We avoid the |
||||
# trouble by copying the contents of the source, |
||||
# instead of the directory itself. |
||||
foreach path [glob -directory $s *] { |
||||
file copy -force $path $d |
||||
} |
||||
} else { |
||||
file copy -force $s $d |
||||
} |
||||
} |
||||
return |
||||
} |
||||
|
||||
proc Remove {files} { |
||||
upvar 1 base base |
||||
|
||||
foreach f $files { |
||||
file delete -force [file join $base $f] |
||||
} |
||||
return |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## Internal -- Resolution helper commands |
||||
|
||||
typevariable tmap -array { |
||||
files {f TFile} |
||||
links {l TLink} |
||||
dirs {d TDir} |
||||
{} {{} {}} |
||||
} |
||||
|
||||
proc Expand {dir pattern} { |
||||
upvar 1 recursive recursive strict strict types types tmap tmap |
||||
# FUTURE: struct::list filter ... |
||||
|
||||
set files {} |
||||
if {$recursive} { |
||||
# Recursion through the entire directory hierarchy, save |
||||
# all matching paths. |
||||
|
||||
set filter [lindex $tmap($types) 1] |
||||
if {$filter ne ""} { |
||||
set filter [myproc $filter] |
||||
} |
||||
|
||||
foreach f [fileutil::find $dir $filter] { |
||||
if {![string match $pattern [file tail $f]]} continue |
||||
lappend files [fileutil::stripPath $dir $f] |
||||
} |
||||
} else { |
||||
# No recursion, just scan the whole directory for matching paths. |
||||
# check for specific types integrated. |
||||
|
||||
set filter [lindex $tmap($types) 0] |
||||
if {$filter ne ""} { |
||||
foreach f [glob -nocomplain -directory $dir -types $filter -- $pattern] { |
||||
lappend files [fileutil::stripPath $dir $f] |
||||
} |
||||
} else { |
||||
foreach f [glob -nocomplain -directory $dir -- $pattern] { |
||||
lappend files [fileutil::stripPath $dir $f] |
||||
} |
||||
} |
||||
} |
||||
|
||||
if {[llength $files]} {return $files} |
||||
if {!$strict} {return {}} |
||||
|
||||
return -code error \ |
||||
"No files matching pattern \"$pattern\" in directory \"$dir\"" |
||||
} |
||||
|
||||
proc TFile {f} {file isfile $f} |
||||
proc TDir {f} {file isdirectory $f} |
||||
proc TLink {f} {expr {[file type $f] eq "link"}} |
||||
|
||||
proc Exclude {files} { |
||||
upvar 1 excl excl |
||||
|
||||
# FUTURE: struct::list filter ... |
||||
set res {} |
||||
foreach f $files { |
||||
if {[IsExcluded $f $excl]} continue |
||||
lappend res $f |
||||
} |
||||
return $res |
||||
} |
||||
|
||||
proc IsExcluded {f patterns} { |
||||
foreach p $patterns { |
||||
if {[string match $p $f]} {return 1} |
||||
} |
||||
return 0 |
||||
} |
||||
|
||||
proc Resolve {files} { |
||||
upvar 1 alias alias |
||||
set res {} |
||||
foreach f $files { |
||||
|
||||
# Remember alias for processing and auto-invalidate to |
||||
# prevent contamination of the next file. |
||||
|
||||
set thealias $alias |
||||
set alias "" |
||||
|
||||
if {$thealias eq ""} { |
||||
set d $f |
||||
} else { |
||||
set d [file dirname $f] |
||||
if {$d eq "."} { |
||||
set d $thealias |
||||
} else { |
||||
set d [file join $d $thealias] |
||||
} |
||||
} |
||||
|
||||
lappend res $f $d |
||||
} |
||||
return $res |
||||
} |
||||
|
||||
proc Remember {files} { |
||||
upvar 1 lastexpansion lastexpansion |
||||
set lastexpansion $files |
||||
return $files |
||||
} |
||||
|
||||
## |
||||
# ### ### ### ######### ######### ######### |
||||
} |
||||
|
||||
# ### ### ### ######### ######### ######### |
||||
## Ready |
||||
|
||||
package provide fileutil::multi::op 0.5.4 |
@ -0,0 +1,7 @@
|
||||
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return} |
||||
package ifneeded fileutil 1.16.2 [list source [file join $dir fileutil.tcl]] |
||||
package ifneeded fileutil::traverse 0.7 [list source [file join $dir traverse.tcl]] |
||||
package ifneeded fileutil::multi 0.2 [list source [file join $dir multi.tcl]] |
||||
package ifneeded fileutil::multi::op 0.5.4 [list source [file join $dir multiop.tcl]] |
||||
package ifneeded fileutil::decode 0.2.2 [list source [file join $dir decode.tcl]] |
||||
package ifneeded fileutil::paths 1.1 [list source [file join $dir paths.tcl]] |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
if {[package vsatisfies [package provide Tcl] 8.5 9]} { |
||||
package ifneeded snit 2.3.3 \ |
||||
[list source [file join $dir snit2.tcl]] |
||||
} |
||||
|
||||
package ifneeded snit 1.4.2 [list source [file join $dir snit.tcl]] |
@ -0,0 +1,32 @@
|
||||
#----------------------------------------------------------------------- |
||||
# TITLE: |
||||
# snit.tcl |
||||
# |
||||
# AUTHOR: |
||||
# Will Duquette |
||||
# |
||||
# DESCRIPTION: |
||||
# Snit's Not Incr Tcl, a simple object system in Pure Tcl. |
||||
# |
||||
# Snit 1.x Loader |
||||
# |
||||
# Copyright (C) 2003-2006 by William H. Duquette |
||||
# This code is licensed as described in license.txt. |
||||
# |
||||
#----------------------------------------------------------------------- |
||||
|
||||
package require Tcl 8.5 9 |
||||
|
||||
# Define the snit namespace and save the library directory |
||||
|
||||
namespace eval ::snit:: { |
||||
set library [file dirname [info script]] |
||||
} |
||||
|
||||
source [file join $::snit::library main1.tcl] |
||||
|
||||
# Load the library of Snit validation types. |
||||
|
||||
source [file join $::snit::library validate.tcl] |
||||
|
||||
package provide snit 1.4.2 |
@ -0,0 +1,32 @@
|
||||
#----------------------------------------------------------------------- |
||||
# TITLE: |
||||
# snit2.tcl |
||||
# |
||||
# AUTHOR: |
||||
# Will Duquette |
||||
# |
||||
# DESCRIPTION: |
||||
# Snit's Not Incr Tcl, a simple object system in Pure Tcl. |
||||
# |
||||
# Snit 2.x Loader |
||||
# |
||||
# Copyright (C) 2003-2006 by William H. Duquette |
||||
# This code is licensed as described in license.txt. |
||||
# |
||||
#----------------------------------------------------------------------- |
||||
|
||||
package require Tcl 8.5 9 |
||||
|
||||
# Define the snit namespace and save the library directory |
||||
|
||||
namespace eval ::snit:: { |
||||
set library [file dirname [info script]] |
||||
} |
||||
|
||||
# Load the kernel. |
||||
source [file join $::snit::library main2.tcl] |
||||
|
||||
# Load the library of Snit validation types. |
||||
source [file join $::snit::library validate.tcl] |
||||
|
||||
package provide snit 2.3.3 |
@ -0,0 +1,720 @@
|
||||
#----------------------------------------------------------------------- |
||||
# TITLE: |
||||
# validate.tcl |
||||
# |
||||
# AUTHOR: |
||||
# Will Duquette |
||||
# |
||||
# DESCRIPTION: |
||||
# Snit validation types. |
||||
# |
||||
#----------------------------------------------------------------------- |
||||
|
||||
namespace eval ::snit:: { |
||||
namespace export \ |
||||
boolean \ |
||||
double \ |
||||
enum \ |
||||
fpixels \ |
||||
integer \ |
||||
listtype \ |
||||
pixels \ |
||||
stringtype \ |
||||
window |
||||
} |
||||
|
||||
#----------------------------------------------------------------------- |
||||
# snit::boolean |
||||
|
||||
snit::type ::snit::boolean { |
||||
#------------------------------------------------------------------- |
||||
# Type Methods |
||||
|
||||
typemethod validate {value} { |
||||
if {![string is boolean -strict $value]} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid boolean \"$value\", should be one of: 1, 0, true, false, yes, no, on, off" |
||||
|
||||
} |
||||
|
||||
return $value |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Constructor |
||||
|
||||
# None needed; no options |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Public Methods |
||||
|
||||
method validate {value} { |
||||
$type validate $value |
||||
} |
||||
} |
||||
|
||||
#----------------------------------------------------------------------- |
||||
# snit::double |
||||
|
||||
snit::type ::snit::double { |
||||
#------------------------------------------------------------------- |
||||
# Options |
||||
|
||||
# -min value |
||||
# |
||||
# Minimum value |
||||
|
||||
option -min -default "" -readonly 1 |
||||
|
||||
# -max value |
||||
# |
||||
# Maximum value |
||||
|
||||
option -max -default "" -readonly 1 |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Type Methods |
||||
|
||||
typemethod validate {value} { |
||||
if {![string is double -strict $value]} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid value \"$value\", expected double" |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Constructor |
||||
|
||||
constructor {args} { |
||||
# FIRST, get the options |
||||
$self configurelist $args |
||||
|
||||
if {"" != $options(-min) && |
||||
![string is double -strict $options(-min)]} { |
||||
return -code error \ |
||||
"invalid -min: \"$options(-min)\"" |
||||
} |
||||
|
||||
if {"" != $options(-max) && |
||||
![string is double -strict $options(-max)]} { |
||||
return -code error \ |
||||
"invalid -max: \"$options(-max)\"" |
||||
} |
||||
|
||||
if {"" != $options(-min) && |
||||
"" != $options(-max) && |
||||
$options(-max) < $options(-min)} { |
||||
return -code error "-max < -min" |
||||
} |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Public Methods |
||||
|
||||
# Fixed method for the snit::double type. |
||||
# WHD, 6/7/2010. |
||||
method validate {value} { |
||||
$type validate $value |
||||
|
||||
if {("" != $options(-min) && $value < $options(-min)) || |
||||
("" != $options(-max) && $value > $options(-max))} { |
||||
|
||||
set msg "invalid value \"$value\", expected double" |
||||
|
||||
if {"" != $options(-min) && "" != $options(-max)} { |
||||
append msg " in range $options(-min), $options(-max)" |
||||
} elseif {"" != $options(-min)} { |
||||
append msg " no less than $options(-min)" |
||||
} elseif {"" != $options(-max)} { |
||||
append msg " no greater than $options(-max)" |
||||
} |
||||
|
||||
return -code error -errorcode INVALID $msg |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
} |
||||
|
||||
#----------------------------------------------------------------------- |
||||
# snit::enum |
||||
|
||||
snit::type ::snit::enum { |
||||
#------------------------------------------------------------------- |
||||
# Options |
||||
|
||||
# -values list |
||||
# |
||||
# Valid values for this type |
||||
|
||||
option -values -default {} -readonly 1 |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Type Methods |
||||
|
||||
typemethod validate {value} { |
||||
# No -values specified; it's always valid |
||||
return $value |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Constructor |
||||
|
||||
constructor {args} { |
||||
$self configurelist $args |
||||
|
||||
if {[llength $options(-values)] == 0} { |
||||
return -code error \ |
||||
"invalid -values: \"\"" |
||||
} |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Public Methods |
||||
|
||||
method validate {value} { |
||||
if {[lsearch -exact $options(-values) $value] == -1} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid value \"$value\", should be one of: [join $options(-values) {, }]" |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
} |
||||
|
||||
#----------------------------------------------------------------------- |
||||
# snit::fpixels |
||||
|
||||
snit::type ::snit::fpixels { |
||||
#------------------------------------------------------------------- |
||||
# Options |
||||
|
||||
# -min value |
||||
# |
||||
# Minimum value |
||||
|
||||
option -min -default "" -readonly 1 |
||||
|
||||
# -max value |
||||
# |
||||
# Maximum value |
||||
|
||||
option -max -default "" -readonly 1 |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Instance variables |
||||
|
||||
variable min "" ;# -min, no suffix |
||||
variable max "" ;# -max, no suffix |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Type Methods |
||||
|
||||
typemethod validate {value} { |
||||
if {[catch {winfo fpixels . $value} dummy]} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid value \"$value\", expected fpixels" |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Constructor |
||||
|
||||
constructor {args} { |
||||
# FIRST, get the options |
||||
$self configurelist $args |
||||
|
||||
if {"" != $options(-min) && |
||||
[catch {winfo fpixels . $options(-min)} min]} { |
||||
return -code error \ |
||||
"invalid -min: \"$options(-min)\"" |
||||
} |
||||
|
||||
if {"" != $options(-max) && |
||||
[catch {winfo fpixels . $options(-max)} max]} { |
||||
return -code error \ |
||||
"invalid -max: \"$options(-max)\"" |
||||
} |
||||
|
||||
if {"" != $min && |
||||
"" != $max && |
||||
$max < $min} { |
||||
return -code error "-max < -min" |
||||
} |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Public Methods |
||||
|
||||
method validate {value} { |
||||
$type validate $value |
||||
|
||||
set val [winfo fpixels . $value] |
||||
|
||||
if {("" != $min && $val < $min) || |
||||
("" != $max && $val > $max)} { |
||||
|
||||
set msg "invalid value \"$value\", expected fpixels" |
||||
|
||||
if {"" != $min && "" != $max} { |
||||
append msg " in range $options(-min), $options(-max)" |
||||
} elseif {"" != $min} { |
||||
append msg " no less than $options(-min)" |
||||
} |
||||
|
||||
return -code error -errorcode INVALID $msg |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
} |
||||
|
||||
#----------------------------------------------------------------------- |
||||
# snit::integer |
||||
|
||||
snit::type ::snit::integer { |
||||
#------------------------------------------------------------------- |
||||
# Options |
||||
|
||||
# -min value |
||||
# |
||||
# Minimum value |
||||
|
||||
option -min -default "" -readonly 1 |
||||
|
||||
# -max value |
||||
# |
||||
# Maximum value |
||||
|
||||
option -max -default "" -readonly 1 |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Type Methods |
||||
|
||||
typemethod validate {value} { |
||||
if {![string is integer -strict $value]} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid value \"$value\", expected integer" |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Constructor |
||||
|
||||
constructor {args} { |
||||
# FIRST, get the options |
||||
$self configurelist $args |
||||
|
||||
if {"" != $options(-min) && |
||||
![string is integer -strict $options(-min)]} { |
||||
return -code error \ |
||||
"invalid -min: \"$options(-min)\"" |
||||
} |
||||
|
||||
if {"" != $options(-max) && |
||||
![string is integer -strict $options(-max)]} { |
||||
return -code error \ |
||||
"invalid -max: \"$options(-max)\"" |
||||
} |
||||
|
||||
if {"" != $options(-min) && |
||||
"" != $options(-max) && |
||||
$options(-max) < $options(-min)} { |
||||
return -code error "-max < -min" |
||||
} |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Public Methods |
||||
|
||||
method validate {value} { |
||||
$type validate $value |
||||
|
||||
if {("" != $options(-min) && $value < $options(-min)) || |
||||
("" != $options(-max) && $value > $options(-max))} { |
||||
|
||||
set msg "invalid value \"$value\", expected integer" |
||||
|
||||
if {"" != $options(-min) && "" != $options(-max)} { |
||||
append msg " in range $options(-min), $options(-max)" |
||||
} elseif {"" != $options(-min)} { |
||||
append msg " no less than $options(-min)" |
||||
} |
||||
|
||||
return -code error -errorcode INVALID $msg |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
} |
||||
|
||||
#----------------------------------------------------------------------- |
||||
# snit::list |
||||
|
||||
snit::type ::snit::listtype { |
||||
#------------------------------------------------------------------- |
||||
# Options |
||||
|
||||
# -type type |
||||
# |
||||
# Specifies a value type |
||||
|
||||
option -type -readonly 1 |
||||
|
||||
# -minlen len |
||||
# |
||||
# Minimum list length |
||||
|
||||
option -minlen -readonly 1 -default 0 |
||||
|
||||
# -maxlen len |
||||
# |
||||
# Maximum list length |
||||
|
||||
option -maxlen -readonly 1 |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Type Methods |
||||
|
||||
typemethod validate {value} { |
||||
if {[catch {llength $value} result]} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid value \"$value\", expected list" |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Constructor |
||||
|
||||
constructor {args} { |
||||
# FIRST, get the options |
||||
$self configurelist $args |
||||
|
||||
if {"" != $options(-minlen) && |
||||
(![string is integer -strict $options(-minlen)] || |
||||
$options(-minlen) < 0)} { |
||||
return -code error \ |
||||
"invalid -minlen: \"$options(-minlen)\"" |
||||
} |
||||
|
||||
if {"" == $options(-minlen)} { |
||||
set options(-minlen) 0 |
||||
} |
||||
|
||||
if {"" != $options(-maxlen) && |
||||
![string is integer -strict $options(-maxlen)]} { |
||||
return -code error \ |
||||
"invalid -maxlen: \"$options(-maxlen)\"" |
||||
} |
||||
|
||||
if {"" != $options(-maxlen) && |
||||
$options(-maxlen) < $options(-minlen)} { |
||||
return -code error "-maxlen < -minlen" |
||||
} |
||||
} |
||||
|
||||
|
||||
#------------------------------------------------------------------- |
||||
# Methods |
||||
|
||||
method validate {value} { |
||||
$type validate $value |
||||
|
||||
set len [llength $value] |
||||
|
||||
if {$len < $options(-minlen)} { |
||||
return -code error -errorcode INVALID \ |
||||
"value has too few elements; at least $options(-minlen) expected" |
||||
} elseif {"" != $options(-maxlen)} { |
||||
if {$len > $options(-maxlen)} { |
||||
return -code error -errorcode INVALID \ |
||||
"value has too many elements; no more than $options(-maxlen) expected" |
||||
} |
||||
} |
||||
|
||||
# NEXT, check each value |
||||
if {"" != $options(-type)} { |
||||
foreach item $value { |
||||
set cmd $options(-type) |
||||
lappend cmd validate $item |
||||
uplevel \#0 $cmd |
||||
} |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
} |
||||
|
||||
#----------------------------------------------------------------------- |
||||
# snit::pixels |
||||
|
||||
snit::type ::snit::pixels { |
||||
#------------------------------------------------------------------- |
||||
# Options |
||||
|
||||
# -min value |
||||
# |
||||
# Minimum value |
||||
|
||||
option -min -default "" -readonly 1 |
||||
|
||||
# -max value |
||||
# |
||||
# Maximum value |
||||
|
||||
option -max -default "" -readonly 1 |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Instance variables |
||||
|
||||
variable min "" ;# -min, no suffix |
||||
variable max "" ;# -max, no suffix |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Type Methods |
||||
|
||||
typemethod validate {value} { |
||||
if {[catch {winfo pixels . $value} dummy]} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid value \"$value\", expected pixels" |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Constructor |
||||
|
||||
constructor {args} { |
||||
# FIRST, get the options |
||||
$self configurelist $args |
||||
|
||||
if {"" != $options(-min) && |
||||
[catch {winfo pixels . $options(-min)} min]} { |
||||
return -code error \ |
||||
"invalid -min: \"$options(-min)\"" |
||||
} |
||||
|
||||
if {"" != $options(-max) && |
||||
[catch {winfo pixels . $options(-max)} max]} { |
||||
return -code error \ |
||||
"invalid -max: \"$options(-max)\"" |
||||
} |
||||
|
||||
if {"" != $min && |
||||
"" != $max && |
||||
$max < $min} { |
||||
return -code error "-max < -min" |
||||
} |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Public Methods |
||||
|
||||
method validate {value} { |
||||
$type validate $value |
||||
|
||||
set val [winfo pixels . $value] |
||||
|
||||
if {("" != $min && $val < $min) || |
||||
("" != $max && $val > $max)} { |
||||
|
||||
set msg "invalid value \"$value\", expected pixels" |
||||
|
||||
if {"" != $min && "" != $max} { |
||||
append msg " in range $options(-min), $options(-max)" |
||||
} elseif {"" != $min} { |
||||
append msg " no less than $options(-min)" |
||||
} |
||||
|
||||
return -code error -errorcode INVALID $msg |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
} |
||||
|
||||
#----------------------------------------------------------------------- |
||||
# snit::stringtype |
||||
|
||||
snit::type ::snit::stringtype { |
||||
#------------------------------------------------------------------- |
||||
# Options |
||||
|
||||
# -minlen len |
||||
# |
||||
# Minimum list length |
||||
|
||||
option -minlen -readonly 1 -default 0 |
||||
|
||||
# -maxlen len |
||||
# |
||||
# Maximum list length |
||||
|
||||
option -maxlen -readonly 1 |
||||
|
||||
# -nocase 0|1 |
||||
# |
||||
# globs and regexps are case-insensitive if -nocase 1. |
||||
|
||||
option -nocase -readonly 1 -default 0 |
||||
|
||||
# -glob pattern |
||||
# |
||||
# Glob-match pattern, or "" |
||||
|
||||
option -glob -readonly 1 |
||||
|
||||
# -regexp regexp |
||||
# |
||||
# Regular expression to match |
||||
|
||||
option -regexp -readonly 1 |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Type Methods |
||||
|
||||
typemethod validate {value} { |
||||
# By default, any string (hence, any Tcl value) is valid. |
||||
return $value |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Constructor |
||||
|
||||
constructor {args} { |
||||
# FIRST, get the options |
||||
$self configurelist $args |
||||
|
||||
# NEXT, validate -minlen and -maxlen |
||||
if {"" != $options(-minlen) && |
||||
(![string is integer -strict $options(-minlen)] || |
||||
$options(-minlen) < 0)} { |
||||
return -code error \ |
||||
"invalid -minlen: \"$options(-minlen)\"" |
||||
} |
||||
|
||||
if {"" == $options(-minlen)} { |
||||
set options(-minlen) 0 |
||||
} |
||||
|
||||
if {"" != $options(-maxlen) && |
||||
![string is integer -strict $options(-maxlen)]} { |
||||
return -code error \ |
||||
"invalid -maxlen: \"$options(-maxlen)\"" |
||||
} |
||||
|
||||
if {"" != $options(-maxlen) && |
||||
$options(-maxlen) < $options(-minlen)} { |
||||
return -code error "-maxlen < -minlen" |
||||
} |
||||
|
||||
# NEXT, validate -nocase |
||||
if {[catch {snit::boolean validate $options(-nocase)} result]} { |
||||
return -code error "invalid -nocase: $result" |
||||
} |
||||
|
||||
# Validate the glob |
||||
if {"" != $options(-glob) && |
||||
[catch {string match $options(-glob) ""} dummy]} { |
||||
return -code error \ |
||||
"invalid -glob: \"$options(-glob)\"" |
||||
} |
||||
|
||||
# Validate the regexp |
||||
if {"" != $options(-regexp) && |
||||
[catch {regexp $options(-regexp) ""} dummy]} { |
||||
return -code error \ |
||||
"invalid -regexp: \"$options(-regexp)\"" |
||||
} |
||||
} |
||||
|
||||
|
||||
#------------------------------------------------------------------- |
||||
# Methods |
||||
|
||||
method validate {value} { |
||||
# Usually we'd call [$type validate $value] here, but |
||||
# as it's a no-op, don't bother. |
||||
|
||||
# FIRST, validate the length. |
||||
set len [string length $value] |
||||
|
||||
if {$len < $options(-minlen)} { |
||||
return -code error -errorcode INVALID \ |
||||
"too short: at least $options(-minlen) characters expected" |
||||
} elseif {"" != $options(-maxlen)} { |
||||
if {$len > $options(-maxlen)} { |
||||
return -code error -errorcode INVALID \ |
||||
"too long: no more than $options(-maxlen) characters expected" |
||||
} |
||||
} |
||||
|
||||
# NEXT, check the glob match, with or without case. |
||||
if {"" != $options(-glob)} { |
||||
if {$options(-nocase)} { |
||||
set result [string match -nocase $options(-glob) $value] |
||||
} else { |
||||
set result [string match $options(-glob) $value] |
||||
} |
||||
|
||||
if {!$result} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid value \"$value\"" |
||||
} |
||||
} |
||||
|
||||
# NEXT, check regexp match with or without case |
||||
if {"" != $options(-regexp)} { |
||||
if {$options(-nocase)} { |
||||
set result [regexp -nocase -- $options(-regexp) $value] |
||||
} else { |
||||
set result [regexp -- $options(-regexp) $value] |
||||
} |
||||
|
||||
if {!$result} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid value \"$value\"" |
||||
} |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
} |
||||
|
||||
#----------------------------------------------------------------------- |
||||
# snit::window |
||||
|
||||
snit::type ::snit::window { |
||||
#------------------------------------------------------------------- |
||||
# Type Methods |
||||
|
||||
typemethod validate {value} { |
||||
if {![winfo exists $value]} { |
||||
return -code error -errorcode INVALID \ |
||||
"invalid value \"$value\", value is not a window" |
||||
} |
||||
|
||||
return $value |
||||
} |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Constructor |
||||
|
||||
# None needed; no options |
||||
|
||||
#------------------------------------------------------------------- |
||||
# Public Methods |
||||
|
||||
method validate {value} { |
||||
$type validate $value |
||||
} |
||||
} |
@ -1,29 +1,25 @@
|
||||
if {![package vsatisfies [package provide Tcl] 8.2]} {return} |
||||
package ifneeded struct 2.1 [list source [file join $dir struct.tcl]] |
||||
package ifneeded struct 1.4 [list source [file join $dir struct1.tcl]] |
||||
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return} |
||||
package ifneeded struct 2.2 [list source [file join $dir struct.tcl]] |
||||
package ifneeded struct 1.5 [list source [file join $dir struct1.tcl]] |
||||
|
||||
package ifneeded struct::queue 1.4.5 [list source [file join $dir queue.tcl]] |
||||
package ifneeded struct::stack 1.5.3 [list source [file join $dir stack.tcl]] |
||||
package ifneeded struct::tree 2.1.2 [list source [file join $dir tree.tcl]] |
||||
package ifneeded struct::pool 1.2.3 [list source [file join $dir pool.tcl]] |
||||
package ifneeded struct::record 1.2.2 [list source [file join $dir record.tcl]] |
||||
package ifneeded struct::set 2.2.3 [list source [file join $dir sets.tcl]] |
||||
package ifneeded struct::prioqueue 1.4 [list source [file join $dir prioqueue.tcl]] |
||||
package ifneeded struct::skiplist 1.3 [list source [file join $dir skiplist.tcl]] |
||||
package ifneeded struct::queue 1.4.6 [list source [file join $dir queue.tcl]] |
||||
package ifneeded struct::stack 1.5.4 [list source [file join $dir stack.tcl]] |
||||
package ifneeded struct::tree 2.1.3 [list source [file join $dir tree.tcl]] |
||||
package ifneeded struct::pool 1.2.4 [list source [file join $dir pool.tcl]] |
||||
package ifneeded struct::record 1.2.3 [list source [file join $dir record.tcl]] |
||||
package ifneeded struct::set 2.2.4 [list source [file join $dir sets.tcl]] |
||||
package ifneeded struct::prioqueue 1.5 [list source [file join $dir prioqueue.tcl]] |
||||
package ifneeded struct::skiplist 1.4 [list source [file join $dir skiplist.tcl]] |
||||
|
||||
package ifneeded struct::graph 1.2.1 [list source [file join $dir graph1.tcl]] |
||||
package ifneeded struct::tree 1.2.2 [list source [file join $dir tree1.tcl]] |
||||
package ifneeded struct::graph 1.2.2 [list source [file join $dir graph1.tcl]] |
||||
package ifneeded struct::tree 1.2.3 [list source [file join $dir tree1.tcl]] |
||||
|
||||
if {![package vsatisfies [package provide Tcl] 8.4]} {return} |
||||
package ifneeded struct::list 1.8.5 [list source [file join $dir list.tcl]] |
||||
package ifneeded struct::list::test 1.8.4 [list source [file join $dir list.test.tcl]] |
||||
package ifneeded struct::graph 2.4.3 [list source [file join $dir graph.tcl]] |
||||
package ifneeded struct::map 1 [list source [file join $dir map.tcl]] |
||||
package ifneeded struct::list 1.8.6 [list source [file join $dir list.tcl]] |
||||
package ifneeded struct::list::test 1.8.5 [list source [file join $dir list.test.tcl]] |
||||
package ifneeded struct::graph 2.4.4 [list source [file join $dir graph.tcl]] |
||||
package ifneeded struct::map 1.1 [list source [file join $dir map.tcl]] |
||||
|
||||
if {![package vsatisfies [package provide Tcl] 8.5]} {return} |
||||
package ifneeded struct::matrix 2.2 [list source [file join $dir matrix.tcl]] |
||||
|
||||
package ifneeded struct::matrix 2.1 [list source [file join $dir matrix.tcl]] |
||||
|
||||
if {![package vsatisfies [package provide Tcl] 8.6]} {return} |
||||
package ifneeded struct::disjointset 1.1 [list source [file join $dir disjointset.tcl]] |
||||
package ifneeded struct::graph::op 0.11.3 [list source [file join $dir graphops.tcl]] |
||||
package ifneeded struct::disjointset 1.2 [list source [file join $dir disjointset.tcl]] |
||||
package ifneeded struct::graph::op 0.11.4 [list source [file join $dir graphops.tcl]] |
||||
|
@ -1,13 +1,13 @@
|
||||
if {![package vsatisfies [package provide Tcl] 8.4]} return |
||||
package ifneeded term 0.1 [list source [file join $dir term.tcl]] |
||||
package ifneeded term::ansi::code 0.2 [list source [file join $dir ansi/code.tcl]] |
||||
package ifneeded term::ansi::code::attr 0.1 [list source [file join $dir ansi/code/attr.tcl]] |
||||
package ifneeded term::ansi::code::ctrl 0.3 [list source [file join $dir ansi/code/ctrl.tcl]] |
||||
package ifneeded term::ansi::code::macros 0.1 [list source [file join $dir ansi/code/macros.tcl]] |
||||
package ifneeded term::ansi::ctrl::unix 0.1.1 [list source [file join $dir ansi/ctrlunix.tcl]] |
||||
package ifneeded term::ansi::send 0.2 [list source [file join $dir ansi/send.tcl]] |
||||
package ifneeded term::interact::menu 0.1 [list source [file join $dir imenu.tcl]] |
||||
package ifneeded term::interact::pager 0.1 [list source [file join $dir ipager.tcl]] |
||||
package ifneeded term::receive 0.1 [list source [file join $dir receive.tcl]] |
||||
package ifneeded term::receive::bind 0.1 [list source [file join $dir bind.tcl]] |
||||
package ifneeded term::send 0.1 [list source [file join $dir send.tcl]] |
||||
if {![package vsatisfies [package provide Tcl] 8.5 9]} return |
||||
package ifneeded term 0.2 [list source [file join $dir term.tcl]] |
||||
package ifneeded term::ansi::code 0.3 [list source [file join $dir ansi/code.tcl]] |
||||
package ifneeded term::ansi::code::attr 0.2 [list source [file join $dir ansi/code/attr.tcl]] |
||||
package ifneeded term::ansi::code::ctrl 0.4 [list source [file join $dir ansi/code/ctrl.tcl]] |
||||
package ifneeded term::ansi::code::macros 0.2 [list source [file join $dir ansi/code/macros.tcl]] |
||||
package ifneeded term::ansi::ctrl::unix 0.1.2 [list source [file join $dir ansi/ctrlunix.tcl]] |
||||
package ifneeded term::ansi::send 0.3 [list source [file join $dir ansi/send.tcl]] |
||||
package ifneeded term::interact::menu 0.2 [list source [file join $dir imenu.tcl]] |
||||
package ifneeded term::interact::pager 0.2 [list source [file join $dir ipager.tcl]] |
||||
package ifneeded term::receive 0.2 [list source [file join $dir receive.tcl]] |
||||
package ifneeded term::receive::bind 0.2 [list source [file join $dir bind.tcl]] |
||||
package ifneeded term::send 0.2 [list source [file join $dir send.tcl]] |
||||
|
Loading…
Reference in new issue