Simple mechanism to dispatch [proc]s corresponding to given commands and subcommands. Commands and subcommands can be abbreviated. Command 'help errorlevel' is mapped to a procedure '.help.errorlevel', e.g. 'he err' does the job, too. ====== # Example proc .help {} { } proc .help.errorlevel {} { } proc dispatch {allowed cmdwords} { if {[llength $cmdwords] == 0} { puts stderr "command missing!" puts stderr "Possible commands are:" lmap l $allowed {puts stderr [lindex $l 0]} exit 250 } foreach word $cmdwords { set cmdword [lsearch -glob -nocase -index 0 -inline $allowed $word*] if {[llength $cmdword]} { append p . [lindex $cmdword 0]; # expanded command name set allowed [lindex $cmdword 1]; # subcommands } else { puts stderr "Unknown (sub-)command: $word" puts stderr "Possible (sub-)commands are:" lmap l $allowed {puts stderr [lindex $l 0]} exit 250 } } if {[catch {tailcall $p} rc]} { puts stderr "cmd '$cmdwords' noch implemented yet!" exit 250 } } # Give the list of allowed commands and subcommands, and the current commandwords. The format of the list is: # each element of the list is one command # each element can in turn be a list; element #1 of the list is the command itself, element #2 is a list of possible subcommands # and so on dispatch { {help {errorlevel inifile examples}} list } $argv ====== All that's to do to implement a new command is to add it to the list given to dispatch and implement the corresponding proc. I found that simpler than [namespace ensemble] which confuses me still. ---- Later I found out that [tailcall] should not be [catch]ed... Also, I want to be able to store some kind of description alongside commands (didn't make use of them, though). So the above snippet turnded into the following [dict]ionary based variant. In addition, each [tailcall] gets its subcommands, if any, as an arg so it's possible to show some help about the available subcommands from within the handler. ====== proc dispatch {allowed cmdwords} { foreach word $cmdwords { puts ">nextword: $word" set key [lindex [dict keys $allowed $word*] 0]; # unfortunally we have no -nocase here if {[string length $key]} { set val [dict get $allowed $key] append p . $key set allowed [dict get [dict merge {subcommands {}} $val] subcommands] } else { puts "unknown (sub)command: $word"; return } } tailcall $p $allowed; } # Dictionary mit erlaubten Kommandos, Hilfen und Subkommandos # - jedes Kommando ist ein Dictioary Eintrag: # Schlüsselname := Kommandoname # Schlüsselwert := ein weiteres Dictionary, kann leer sein oder folgende Einträge enthalten: # info "hilfetext" # subcommands "wieder ein dictionary wie hier beschrieben" # dispatch { cmd1 {info "Erläuterung zum cmd1"} cmd2 {info "Erläuterung zum cmd2" subcommands { subcmd21 {info "Erläuterung zum subcmd21"} subcmd22 {info "Erläuterung zum subcmd22"} } } cmd4 {} cmd5 { info "Hilfe zum cmd5" subcommands { subCmd51 { info "Hilfe zum SubCmd51" subcommands { SubSubCmd511 {} } } subCmd52 { info "Hilfe zum SubCmd52" subcommands { SubSubCmd521 {info "Hilfe zum SubSubCmd521" subcommands { SubSubSubCmd5211 {info "Hilfe zum SubSubSubCmd5211"} } } } } } } } $argv ====== <>Enter Category Here