|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
package require Tcl 8.2 |
|
|
|
|
|
package provide opt 0.4.6 |
|
|
|
namespace eval ::tcl { |
|
|
|
|
|
namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \ |
|
OptProc OptProcArgGiven OptParse \ |
|
Lempty Lget \ |
|
Lassign Lvarpop Lvarpop1 Lvarset Lvarincr \ |
|
SetMax SetMin |
|
|
|
|
|
|
|
|
|
proc OptCreateTestProc {} { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OptProc OptParseTest { |
|
{subcommand -choice {save print} "sub command"} |
|
{arg1 3 "some number"} |
|
{-aflag} |
|
{-intflag 7} |
|
{-weirdflag "help string"} |
|
{-noStatics "Not ok to load static packages"} |
|
{-nestedloading1 true "OK to load into nested slaves"} |
|
{-nestedloading2 -boolean true "OK to load into nested slaves"} |
|
{-libsOK -choice {Tk SybTcl} |
|
"List of packages that can be loaded"} |
|
{-precision -int 12 "Number of digits of precision"} |
|
{-intval 7 "An integer"} |
|
{-scale -float 1.0 "Scale factor"} |
|
{-zoom 1.0 "Zoom factor"} |
|
{-arbitrary foobar "Arbitrary string"} |
|
{-random -string 12 "Random string"} |
|
{-listval -list {} "List value"} |
|
{-blahflag -blah abc "Funny type"} |
|
{arg2 -boolean "a boolean"} |
|
{arg3 -choice "ch1 ch2"} |
|
{?optarg? -list {} "optional argument"} |
|
} { |
|
foreach v [info locals] { |
|
puts stderr [format "%14s : %s" $v [set $v]] |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
variable OptDesc |
|
array set OptDesc {} |
|
|
|
variable OptDescN 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::tcl::OptKeyRegister {desc {key ""}} { |
|
variable OptDesc |
|
variable OptDescN |
|
if {[string equal $key ""]} { |
|
|
|
while {[info exists OptDesc($OptDescN)]} {incr OptDescN} |
|
set key $OptDescN |
|
incr OptDescN |
|
} |
|
|
|
set program [list [list "P" 1]] |
|
|
|
|
|
set inflags 0 |
|
|
|
set state {} |
|
|
|
|
|
set empty 1 |
|
|
|
foreach item $desc { |
|
if {$state == "args"} { |
|
|
|
return -code error "'args' special argument must be the last one" |
|
} |
|
set res [OptNormalizeOne $item] |
|
set state [lindex $res 0] |
|
if {$inflags} { |
|
if {$state == "flags"} { |
|
|
|
lappend flagsprg $res |
|
} else { |
|
|
|
|
|
|
|
lappend program $flagsprg |
|
|
|
lappend program $res |
|
set inflags 0 |
|
set empty 0 |
|
} |
|
} else { |
|
if {$state == "flags"} { |
|
set inflags 1 |
|
|
|
set flagsprg [list [list "P" 1] $res] |
|
} else { |
|
lappend program $res |
|
set empty 0 |
|
} |
|
} |
|
} |
|
if {$inflags} { |
|
if {$empty} { |
|
|
|
|
|
set program $flagsprg |
|
} else { |
|
lappend program $flagsprg |
|
} |
|
} |
|
|
|
set OptDesc($key) $program |
|
|
|
return $key |
|
} |
|
|
|
|
|
|
|
|
|
proc ::tcl::OptKeyDelete {key} { |
|
variable OptDesc |
|
unset OptDesc($key) |
|
} |
|
|
|
|
|
proc OptKeyGetDesc {descKey} { |
|
variable OptDesc |
|
if {![info exists OptDesc($descKey)]} { |
|
return -code error "Unknown option description key \"$descKey\"" |
|
} |
|
set OptDesc($descKey) |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::tcl::OptParse {desc arglist} { |
|
set tempkey [OptKeyRegister $desc] |
|
set ret [catch {uplevel 1 [list ::tcl::OptKeyParse $tempkey $arglist]} res] |
|
OptKeyDelete $tempkey |
|
return -code $ret $res |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::tcl::OptProc {name desc body} { |
|
set namespace [uplevel 1 [list ::namespace current]] |
|
if {[string match "::*" $name] || [string equal $namespace "::"]} { |
|
|
|
set key $name |
|
} else { |
|
|
|
set key "${namespace}::${name}" |
|
} |
|
OptKeyRegister $desc $key |
|
uplevel 1 [list ::proc $name args "set Args \[::tcl::OptKeyParse $key \$args\]\n$body"] |
|
return $key |
|
} |
|
# Check that a argument has been given |
|
# assumes that "OptProc" has been used as it will check in "Args" list |
|
proc ::tcl::OptProcArgGiven {argname} { |
|
upvar Args alist |
|
expr {[lsearch $alist $argname] >=0} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
proc OptInstr {lst} { |
|
lindex $lst 0 |
|
} |
|
|
|
proc OptIsPrg {lst} { |
|
expr {[llength [OptInstr $lst]]>=2} |
|
} |
|
|
|
proc OptIsCounter {item} { |
|
expr {[lindex $item 0]=="P"} |
|
} |
|
|
|
proc OptGetPrgCounter {lst} { |
|
Lget $lst {0 1} |
|
} |
|
|
|
proc OptSetPrgCounter {lstName newValue} { |
|
upvar $lstName lst |
|
set lst [lreplace $lst 0 0 [concat "P" $newValue]] |
|
} |
|
|
|
proc OptSelection {lst} { |
|
set res {} |
|
foreach idx [lrange [lindex $lst 0] 1 end] { |
|
lappend res [Lget $lst $idx] |
|
} |
|
return $res |
|
} |
|
|
|
|
|
proc OptNextDesc {descName} { |
|
uplevel 1 [list Lvarincr $descName {0 1}] |
|
} |
|
|
|
|
|
proc OptCurDesc {descriptions} { |
|
lindex $descriptions [OptGetPrgCounter $descriptions] |
|
} |
|
|
|
|
|
proc OptCurDescFinal {descriptions} { |
|
set item [OptCurDesc $descriptions] |
|
|
|
while {[OptIsPrg $item]} { |
|
set item [OptCurDesc $item] |
|
} |
|
return $item |
|
} |
|
|
|
proc OptCurAddr {descriptions {start {}}} { |
|
set adress [OptGetPrgCounter $descriptions] |
|
lappend start $adress |
|
set item [lindex $descriptions $adress] |
|
if {[OptIsPrg $item]} { |
|
return [OptCurAddr $item $start] |
|
} else { |
|
return $start |
|
} |
|
} |
|
|
|
proc OptCurSetValue {descriptionsName value} { |
|
upvar $descriptionsName descriptions |
|
|
|
set adress [OptCurAddr $descriptions] |
|
|
|
lappend adress 2 |
|
Lvarset descriptions $adress [list 1 $value] |
|
|
|
} |
|
|
|
|
|
proc OptState {item} { |
|
lindex $item 0 |
|
} |
|
|
|
|
|
proc OptCurState {descriptions} { |
|
OptState [OptCurDesc $descriptions] |
|
} |
|
|
|
|
|
|
|
|
|
|
|
proc OptCurrentArg {lst} { |
|
lindex $lst 0 |
|
} |
|
|
|
proc OptNextArg {argsName} { |
|
uplevel 1 [list Lvarpop1 $argsName] |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc OptDoAll {descriptionsName argumentsName} { |
|
upvar $descriptionsName descriptions |
|
upvar $argumentsName arguments |
|
|
|
|
|
|
|
|
|
set state [OptCurState $descriptions] |
|
|
|
while 1 { |
|
set curitem [OptCurDesc $descriptions] |
|
|
|
while {[OptIsPrg $curitem]} { |
|
OptDoAll curitem arguments |
|
|
|
|
|
Lvarset1nc descriptions [OptGetPrgCounter $descriptions]\ |
|
$curitem |
|
OptNextDesc descriptions |
|
set curitem [OptCurDesc $descriptions] |
|
set state [OptCurState $descriptions] |
|
} |
|
|
|
if {[Lempty $state]} { |
|
|
|
break |
|
} |
|
|
|
|
|
|
|
OptDoOne descriptions state arguments |
|
|
|
|
|
|
|
OptNextDesc descriptions |
|
set state [OptCurState $descriptions] |
|
} |
|
} |
|
|
|
|
|
|
|
proc OptDoOne {descriptionsName stateName argumentsName} { |
|
upvar $argumentsName arguments |
|
upvar $descriptionsName descriptions |
|
upvar $stateName state |
|
|
|
|
|
|
|
if {($state == "args")} { |
|
if {![Lempty $arguments]} { |
|
|
|
|
|
OptCurSetValue descriptions $arguments |
|
set arguments {} |
|
} |
|
|
|
return -code break |
|
} |
|
|
|
if {[Lempty $arguments]} { |
|
if {$state == "flags"} { |
|
|
|
|
|
return -code return |
|
} elseif {$state == "optValue"} { |
|
set state next |
|
|
|
return |
|
} else { |
|
return -code error [OptMissingValue $descriptions] |
|
} |
|
} else { |
|
set arg [OptCurrentArg $arguments] |
|
} |
|
|
|
switch $state { |
|
flags { |
|
|
|
|
|
|
|
if {![OptIsFlag $arg]} { |
|
|
|
return -code return |
|
} |
|
|
|
OptNextArg arguments |
|
if {[string equal "--" $arg]} { |
|
|
|
return -code return |
|
} |
|
|
|
set hits [OptHits descriptions $arg] |
|
if {$hits > 1} { |
|
return -code error [OptAmbigous $descriptions $arg] |
|
} elseif {$hits == 0} { |
|
return -code error [OptFlagUsage $descriptions $arg] |
|
} |
|
set item [OptCurDesc $descriptions] |
|
if {[OptNeedValue $item]} { |
|
|
|
set state flagValue |
|
} else { |
|
OptCurSetValue descriptions 1 |
|
} |
|
|
|
return -code continue |
|
} |
|
flagValue - |
|
value { |
|
set item [OptCurDesc $descriptions] |
|
|
|
if {[catch {OptCheckType $arg\ |
|
[OptType $item] [OptTypeArgs $item]} val]} { |
|
return -code error [OptBadValue $item $arg $val] |
|
} |
|
|
|
OptNextArg arguments |
|
|
|
OptCurSetValue descriptions $val |
|
|
|
if {$state == "flagValue"} { |
|
set state flags |
|
return -code continue |
|
} else { |
|
set state next |
|
return |
|
} |
|
} |
|
optValue { |
|
set item [OptCurDesc $descriptions] |
|
|
|
if {![catch {OptCheckType $arg\ |
|
[OptType $item] [OptTypeArgs $item]} val]} { |
|
|
|
|
|
OptNextArg arguments |
|
|
|
OptCurSetValue descriptions $val |
|
} |
|
|
|
set state next |
|
return |
|
} |
|
} |
|
|
|
|
|
return -code error "Bug! unknown state in DoOne \"$state\"\ |
|
(prg counter [OptGetPrgCounter $descriptions]:\ |
|
[OptCurDesc $descriptions])" |
|
} |
|
|
|
|
|
|
|
proc ::tcl::OptKeyParse {descKey arglist} { |
|
|
|
set desc [OptKeyGetDesc $descKey] |
|
|
|
|
|
if {[string equal -nocase "-help" $arglist]} { |
|
return -code error [OptError "Usage information:" $desc 1] |
|
} |
|
|
|
OptDoAll desc arglist |
|
|
|
if {![Lempty $arglist]} { |
|
return -code error [OptTooManyArgs $desc $arglist] |
|
} |
|
|
|
|
|
|
|
OptTreeVars $desc "#[expr {[info level]-1}]" |
|
} |
|
|
|
|
|
proc OptTreeVars {desc level {vnamesLst {}}} { |
|
foreach item $desc { |
|
if {[OptIsCounter $item]} continue |
|
if {[OptIsPrg $item]} { |
|
set vnamesLst [OptTreeVars $item $level $vnamesLst] |
|
} else { |
|
set vname [OptVarName $item] |
|
upvar $level $vname var |
|
if {[OptHasBeenSet $item]} { |
|
|
|
|
|
|
|
|
|
|
|
lappend vnamesLst [OptName $item] |
|
set var [OptValue $item] |
|
} else { |
|
set var [OptDefaultValue $item] |
|
} |
|
} |
|
} |
|
return $vnamesLst |
|
} |
|
|
|
|
|
|
|
|
|
|
|
proc ::tcl::OptCheckType {arg type {typeArgs ""}} { |
|
|
|
|
|
|
|
|
|
switch -exact -- $type { |
|
int { |
|
if {![string is integer -strict $arg]} { |
|
error "not an integer" |
|
} |
|
return $arg |
|
} |
|
float { |
|
return [expr {double($arg)}] |
|
} |
|
script - |
|
list { |
|
|
|
if {[llength $arg]==0 && [OptIsFlag $arg]} { |
|
error "no values with leading -" |
|
} |
|
return $arg |
|
} |
|
boolean { |
|
if {![string is boolean -strict $arg]} { |
|
error "non canonic boolean" |
|
} |
|
|
|
return [expr {$arg ? 1 : 0}] |
|
} |
|
choice { |
|
if {[lsearch -exact $typeArgs $arg] < 0} { |
|
error "invalid choice" |
|
} |
|
return $arg |
|
} |
|
any { |
|
return $arg |
|
} |
|
string - |
|
default { |
|
if {[OptIsFlag $arg]} { |
|
error "no values with leading -" |
|
} |
|
return $arg |
|
} |
|
} |
|
return neverReached |
|
} |
|
|
|
|
|
|
|
|
|
|
|
proc OptHits {descName arg} { |
|
upvar $descName desc |
|
set hits 0 |
|
set hitems {} |
|
set i 1 |
|
|
|
set larg [string tolower $arg] |
|
set len [string length $larg] |
|
set last [expr {$len-1}] |
|
|
|
foreach item [lrange $desc 1 end] { |
|
set flag [OptName $item] |
|
|
|
|
|
set lflag [string tolower $flag] |
|
if {$len == [string length $lflag]} { |
|
if {[string equal $larg $lflag]} { |
|
|
|
OptSetPrgCounter desc $i |
|
return 1 |
|
} |
|
} elseif {[string equal $larg [string range $lflag 0 $last]]} { |
|
lappend hitems $i |
|
incr hits |
|
} |
|
incr i |
|
} |
|
if {$hits} { |
|
OptSetPrgCounter desc $hitems |
|
} |
|
return $hits |
|
} |
|
|
|
|
|
|
|
proc OptName {item} { |
|
lindex $item 1 |
|
} |
|
proc OptHasBeenSet {item} { |
|
Lget $item {2 0} |
|
} |
|
proc OptValue {item} { |
|
Lget $item {2 1} |
|
} |
|
|
|
proc OptIsFlag {name} { |
|
string match "-*" $name |
|
} |
|
proc OptIsOpt {name} { |
|
string match {\?*} $name |
|
} |
|
proc OptVarName {item} { |
|
set name [OptName $item] |
|
if {[OptIsFlag $name]} { |
|
return [string range $name 1 end] |
|
} elseif {[OptIsOpt $name]} { |
|
return [string trim $name "?"] |
|
} else { |
|
return $name |
|
} |
|
} |
|
proc OptType {item} { |
|
lindex $item 3 |
|
} |
|
proc OptTypeArgs {item} { |
|
lindex $item 4 |
|
} |
|
proc OptHelp {item} { |
|
lindex $item 5 |
|
} |
|
proc OptNeedValue {item} { |
|
expr {![string equal [OptType $item] boolflag]} |
|
} |
|
proc OptDefaultValue {item} { |
|
set val [OptTypeArgs $item] |
|
switch -exact -- [OptType $item] { |
|
choice {return [lindex $val 0]} |
|
boolean - |
|
boolflag { |
|
|
|
|
|
if {$val} { |
|
return 1 |
|
} else { |
|
return 0 |
|
} |
|
} |
|
} |
|
return $val |
|
} |
|
|
|
|
|
proc OptOptUsage {item {what ""}} { |
|
return -code error "invalid description format$what: $item\n\ |
|
should be a list of {varname|-flagname ?-type? ?defaultvalue?\ |
|
?helpstring?}" |
|
} |
|
|
|
|
|
|
|
proc OptNewInst {state varname type typeArgs help} { |
|
list $state $varname [list 0 {}] $type $typeArgs $help |
|
|
|
|
|
|
|
} |
|
|
|
|
|
proc OptNormalizeOne {item} { |
|
set lg [Lassign $item varname arg1 arg2 arg3] |
|
|
|
set isflag [OptIsFlag $varname] |
|
set isopt [OptIsOpt $varname] |
|
if {$isflag} { |
|
set state "flags" |
|
} elseif {$isopt} { |
|
set state "optValue" |
|
} elseif {![string equal $varname "args"]} { |
|
set state "value" |
|
} else { |
|
set state "args" |
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch $lg { |
|
1 { |
|
if {$isflag} { |
|
return [OptNewInst $state $varname boolflag false ""] |
|
} else { |
|
return [OptNewInst $state $varname any "" ""] |
|
} |
|
} |
|
2 { |
|
|
|
|
|
set type [OptGuessType $arg1] |
|
if {[string equal $type "string"]} { |
|
if {$isflag} { |
|
set type boolflag |
|
set def false |
|
} else { |
|
set type any |
|
set def "" |
|
} |
|
set help $arg1 |
|
} else { |
|
set help "" |
|
set def $arg1 |
|
} |
|
return [OptNewInst $state $varname $type $def $help] |
|
} |
|
3 { |
|
|
|
|
|
|
|
if {[regexp {^-(.+)$} $arg1 x type]} { |
|
|
|
|
|
|
|
if {$isflag || $isopt || ($type == "choice")} { |
|
return [OptNewInst $state $varname $type $arg2 ""] |
|
} else { |
|
return [OptNewInst $state $varname $type "" $arg2] |
|
} |
|
} else { |
|
return [OptNewInst $state $varname\ |
|
[OptGuessType $arg1] $arg1 $arg2] |
|
} |
|
} |
|
4 { |
|
if {[regexp {^-(.+)$} $arg1 x type]} { |
|
return [OptNewInst $state $varname $type $arg2 $arg3] |
|
} else { |
|
return -code error [OptOptUsage $item] |
|
} |
|
} |
|
default { |
|
return -code error [OptOptUsage $item] |
|
} |
|
} |
|
} |
|
|
|
|
|
proc OptGuessType {arg} { |
|
if { $arg == "true" || $arg == "false" } { |
|
return boolean |
|
} |
|
if {[string is integer -strict $arg]} { |
|
return int |
|
} |
|
if {[string is double -strict $arg]} { |
|
return float |
|
} |
|
return string |
|
} |
|
|
|
|
|
|
|
proc OptAmbigous {desc arg} { |
|
OptError "ambigous option \"$arg\", choose from:" [OptSelection $desc] |
|
} |
|
proc OptFlagUsage {desc arg} { |
|
OptError "bad flag \"$arg\", must be one of" $desc |
|
} |
|
proc OptTooManyArgs {desc arguments} { |
|
OptError "too many arguments (unexpected argument(s): $arguments),\ |
|
usage:"\ |
|
$desc 1 |
|
} |
|
proc OptParamType {item} { |
|
if {[OptIsFlag $item]} { |
|
return "flag" |
|
} else { |
|
return "parameter" |
|
} |
|
} |
|
proc OptBadValue {item arg {err {}}} { |
|
|
|
OptError "bad value \"$arg\" for [OptParamType $item]"\ |
|
[list $item] |
|
} |
|
proc OptMissingValue {descriptions} { |
|
|
|
set item [OptCurDesc $descriptions] |
|
OptError "no value given for [OptParamType $item] \"[OptName $item]\"\ |
|
(use -help for full usage) :"\ |
|
[list $item] |
|
} |
|
|
|
proc ::tcl::OptKeyError {prefix descKey {header 0}} { |
|
OptError $prefix [OptKeyGetDesc $descKey] $header |
|
} |
|
|
|
|
|
proc OptLengths {desc nlName tlName dlName} { |
|
upvar $nlName nl |
|
upvar $tlName tl |
|
upvar $dlName dl |
|
foreach item $desc { |
|
if {[OptIsCounter $item]} continue |
|
if {[OptIsPrg $item]} { |
|
OptLengths $item nl tl dl |
|
} else { |
|
SetMax nl [string length [OptName $item]] |
|
SetMax tl [string length [OptType $item]] |
|
set dv [OptTypeArgs $item] |
|
if {[OptState $item] != "header"} { |
|
set dv "($dv)" |
|
} |
|
set l [string length $dv] |
|
|
|
if {([OptType $item] != "choice") || ($l<=12)} { |
|
SetMax dl $l |
|
} else { |
|
if {![info exists dl]} { |
|
set dl 0 |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
proc OptTree {desc nl tl dl} { |
|
set res "" |
|
foreach item $desc { |
|
if {[OptIsCounter $item]} continue |
|
if {[OptIsPrg $item]} { |
|
append res [OptTree $item $nl $tl $dl] |
|
} else { |
|
set dv [OptTypeArgs $item] |
|
if {[OptState $item] != "header"} { |
|
set dv "($dv)" |
|
} |
|
append res [string trimright [format "\n %-*s %-*s %-*s %s" \ |
|
$nl [OptName $item] $tl [OptType $item] \ |
|
$dl $dv [OptHelp $item]]] |
|
} |
|
} |
|
return $res |
|
} |
|
|
|
|
|
proc ::tcl::OptError {prefix desc {header 0}} { |
|
|
|
if {$header} { |
|
|
|
set h [list [OptNewInst header Var/FlagName Type Value Help]] |
|
lappend h [OptNewInst header ------------ ---- ----- ----] |
|
lappend h [OptNewInst header {(-help} "" "" {gives this help)}] |
|
set desc [concat $h $desc] |
|
} |
|
OptLengths $desc nl tl dl |
|
|
|
return "$prefix[OptTree $desc $nl $tl $dl]" |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::tcl::Lempty {list} { |
|
expr {[llength $list]==0} |
|
} |
|
|
|
|
|
proc ::tcl::Lget {list indexLst} { |
|
if {[llength $indexLst] <= 1} { |
|
return [lindex $list $indexLst] |
|
} |
|
Lget [lindex $list [lindex $indexLst 0]] [lrange $indexLst 1 end] |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc ::tcl::Lvarset {listName indexLst newValue} { |
|
upvar $listName list |
|
if {[llength $indexLst] <= 1} { |
|
Lvarset1nc list $indexLst $newValue |
|
} else { |
|
set idx [lindex $indexLst 0] |
|
set targetList [lindex $list $idx] |
|
|
|
|
|
|
|
|
|
Lvarset targetList [lrange $indexLst 1 end] $newValue |
|
|
|
Lvarset1nc list $idx $targetList |
|
} |
|
} |
|
|
|
|
|
variable emptyList {} |
|
proc ::tcl::Lvarset1 {listName index newValue} { |
|
upvar $listName list |
|
if {$index < 0} {return -code error "invalid negative index"} |
|
set lg [llength $list] |
|
if {$index >= $lg} { |
|
variable emptyList |
|
for {set i $lg} {$i<$index} {incr i} { |
|
lappend list $emptyList |
|
} |
|
lappend list $newValue |
|
} else { |
|
set list [lreplace $list $index $index $newValue] |
|
} |
|
} |
|
|
|
proc ::tcl::Lvarset1nc {listName index newValue} { |
|
upvar $listName list |
|
set list [lreplace $list $index $index $newValue] |
|
} |
|
|
|
|
|
proc ::tcl::Lvarincr {listName indexLst {howMuch 1}} { |
|
upvar $listName list |
|
if {[llength $indexLst] <= 1} { |
|
Lvarincr1 list $indexLst $howMuch |
|
} else { |
|
set idx [lindex $indexLst 0] |
|
set targetList [lindex $list $idx] |
|
|
|
Lvarset1nc list $idx {} |
|
|
|
Lvarincr targetList [lrange $indexLst 1 end] $howMuch |
|
|
|
Lvarset1nc list $idx $targetList |
|
} |
|
} |
|
|
|
proc ::tcl::Lvarincr1 {listName index {howMuch 1}} { |
|
upvar $listName list |
|
set newValue [expr {[lindex $list $index]+$howMuch}] |
|
set list [lreplace $list $index $index $newValue] |
|
return $newValue |
|
} |
|
|
|
|
|
proc ::tcl::Lvarpop1 {listName} { |
|
upvar $listName list |
|
set list [lrange $list 1 end] |
|
} |
|
|
|
|
|
proc ::tcl::Lvarpop {listName} { |
|
upvar $listName list |
|
set el [lindex $list 0] |
|
set list [lrange $list 1 end] |
|
return $el |
|
} |
|
|
|
proc ::tcl::Lassign {list args} { |
|
|
|
set i 0 |
|
set lg [llength $list] |
|
foreach vname $args { |
|
if {$i>=$lg} break |
|
uplevel 1 [list ::set $vname [lindex $list $i]] |
|
incr i |
|
} |
|
return $lg |
|
} |
|
|
|
|
|
|
|
|
|
|
|
proc ::tcl::SetMax {varname value} { |
|
upvar 1 $varname var |
|
if {![info exists var] || $value > $var} { |
|
set var $value |
|
} |
|
} |
|
|
|
|
|
|
|
proc ::tcl::SetMin {varname value} { |
|
upvar 1 $varname var |
|
if {![info exists var] || $value < $var} { |
|
set var $value |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|