| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | package require Tcl 8.5- |
| | |
| | |
| | package provide opt 0.4.9 |
| |
|
| | 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 children"} |
| | {-nestedloading2 -boolean true "OK to load into nested children"} |
| | {-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 {$arg ni $typeArgs} { |
| | 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 |
| | } |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | } |
| |
|