proc subcommands {cmd content} {
array set a $content
if [info exists a($cmd)] {
return [uplevel 1 $a($cmd)]
} else {
set cmds [join [lsort [array names a]] ", "] ;#(1)
set cmds [linsert $cmds end-1 or] ;#(2)
return -code error "Bad option \"$cmd\": must be $cmds"
}
}Usage example: proc try {cmd args} {
subcommands $cmd {
foo {puts bar}
bar {puts foo}
args {puts "my args were:$args"}
}
}
try baz
==> Bad option "baz": must be args, bar, or foo(1,2): example of how "shimmering" (changing an object from one to another representation) can help to make compact code: joining the sorted list with ", " (i.e. appending commas to all but the last element) turns it into a string, linserting "or" at the last-but-one position makes it a list again, before the formatting of the error message finally makes it a string. Pure-list or pure-string approaches would be much more clumsy, I guess. The cost in runtime is neglegible for lists of O(10) elements. In production code you may gain performance by avoiding shimmering, but it's not in general a Bad Thing ;-)Arts and crafts of Tcl-Tk programming Category Concept
