I use this proc to parse a proc's args and allow any parameter to be specified as a switch JBR.
To redefine proc so that all future procs are "procargs" enabled:
procargs proc
To "procargs" enable an existing proc
procargs existingprocname
To define a proc with "procargs" enabeled
procargs procname { parameters } { body }
I also use it as a replacement for getopt and friends. I write the main function of the scripted command as a proc and then eval that proc at the bottom of the file with $argv.
procargs main { parameter list here } { ... } eval main $argv
Here is the procargs proc:
interp alias {} _proc {} proc proc _procargs { __name __params __args } { set __nargs [llength $__args] set __npars [llength $__params] # Set the defaults # foreach __par $__params { set __param [lindex $__par 0] set __value [lindex $__par 1] if { ![string compare $__par args] } { set __acat 1 break } upvar $__param $__param set $__param $__value lappend __paramnames $__param } # Set the args # set __p 0 set __eoo 0 for { set __i 0 } { $__i < $__nargs } { incr __i } { set __arg [lindex $__args $__i] if { $__eoo } { set __pnum $__p incr __p } else { switch -regexp -- $__arg { ^$ - ^-[0-9.]+$ - ^[^-].*$ { set __pnum $__p incr __p } default { if { ![string compare $__arg "--"] } { set __eoo 1 continue } set __pnum [lsearch $__paramnames [string range $__arg 1 end]] if { $__pnum < 0 } { error "$__name: no option $__arg: must be one of: $__paramname" } set __arg [lindex $__args [incr __i]] } } } set __param [lindex $__paramnames $__pnum] set $__param $__arg } } proc procargs { args } { _procargs procargs { name params body } $args if { ![string compare $name proc] } { rename _proc {} rename proc _proc rename procargs proc return } if { [llength [info commands $name]] && ![string compare $body {}] } { set args [info args $name] set body [info body $name] # rebuild params # foreach arg $args { if { [info default $name $arg value] } { lappend params "$arg $value" } else { lappend params "$arg" } } } _proc $name { args } "_procargs $name [list $params] \$args; $body" }
AMG: Another option is to use [dict with]. Replace the argument list with args, and insert the command dict with args {} before the rest of the proc body script. Now the procedure is called with an even number of arguments, the first, third, fifth, etc. of which are the names of the arguments, followed by the values of the arguments. Here's the example from Named arguments:
proc myproc {args} { dict with args {} puts "$left=$right" } myproc left 2+2 right 4
RFox 8/3/2012 added a missing double quote at the end of the error command.