namespace unknown overrides
::unknown for a given namespace.
Synopsis edit
-
- namespace unknown ?script?
Attributes edit
- from Tcl version
- 8.5
Documentation edit
- TIP 181
See Also edit
- Locally-scoped command aliases are fun!
- Use namespace unknown to look up commands in a list of dictionaries.
NEM 2006-11-13: Here is an updated version of
let unknown know that makes use of the
8.5 features
namespace unknown and
apply. While (much) longer than the original version, each "known" snippet can have its own parameters, with all the usual forms accepted by
proc (i.e., defaults,
args). Wrapping of new functionality is essentially completely transparent, and each new known thing executes as an independent proc, without adding new command names. You can delegate to the next unknown handler by calling
next (or returning a
continue exception). Without arguments,
next will invoke the next handler with the original command line, otherwise it will pass the rewritten form.
proc know {params body} {
set ns [uplevel 1 { namespace current }]
set old [namespace eval $ns { namespace unknown }]
set new [list $params $body $ns]
namespace eval $ns [list namespace unknown [list ::known $new $old]]
}
proc known {handler old args} {
set rc [catch { uplevel 1 [linsert $args 0 ::apply $handler] } result]
if {$rc == 4} {
# continue - invoke next handler
if {[llength $result] == 0} {
uplevel 1 $old $args
} else {
uplevel 1 $old $result
}
} else {
return -code $rc $result
}
}
proc next args { return -code continue -level 2 $args }
Examples of use:
# expand leading word
know {cmd args} {
if {[llength $cmd] > 1} { uplevel 1 $cmd $args } else { next }
}
# numeric ranges
proc range {from to} {
set ret [list]
while {$from <= $to} { lappend ret $from; incr from }
return $ret
}
know args {
if {[regexp {^([0-9]+)\.\.([0-9]+)$} $args -> from to]} {
range $from $to
} else { next }
}
rwm 2010-03-12: The above code will not correctly return error codes from the 'known' function. (IMHO: I note that the 8.5 catch/error/return and the new unknown are not well explained especially return -options) I made the following changes to correct it:
old --> set rc [catch { uplevel 1 [linsert $args 0 ::apply $handler] } result]
new --> set rc [catch { uplevel 1 [linsert $args 0 ::apply $handler] } result opts]
...
old --> return -code $rc $result
new --> return -options $opts $result