proc which_alias {cmd} { uplevel 1 [list ::trace add execution $cmd enterstep ::error] catch {uplevel 1 $cmd} res uplevel 1 [list ::trace remove execution $cmd enterstep ::error] return $res }
Below some procs to inspect aliases simliar to info args, a similar proc for info body can be built easily (just use the alias following outlined below and apply info body to the actual target of the alias). Note: Since this procedure was written with the (incorrect) assumption that the interp subcommands will accept any variant of a command name as alias token, it doesn't always work.
# [info args] like proc following an alias recursivly until it reaches # the proc it originates from or cannot determine it. # accounts for default parameters set by interp alias # proc aliasargs {cmd} { set orig $cmd set defaultargs [list] # loop until error or return occurs while {1} { # is it a proc already? if {[string equal [info procs $cmd] $cmd]} { set result [info args $cmd] # strip off the interp set default args return [lrange $result [llength $defaultargs] end] } # is it a built in or extension command we can get no args for? if {![string equal [info commands $cmd] $cmd]} { error "\"$orig\" isn't a procedure" } # catch bogus cmd names if {[lsearch [interp aliases {}] $cmd]==-1} { error "\"$orig\" isn't a procedure or alias or command" } if {[llength [set cmdargs [interp alias {} $cmd]]]>0} { # check if it is aliased in from another interpreter if {[catch {interp target {} $cmd} msg]} { error "Cannot resolve \"$orig\", alias leads to another interpreter." } if {$msg != {} } { error "Not recursing into slave interpreter \"$msg\".\ \"$orig\" could not be resolved." } # check if defaults are set for the alias if {[llength $cmdargs]>1} { set cmd [lindex $cmdargs 0] set defaultargs [concat [lrange $cmdargs 1 end] $defaultargs] } else { set cmd $cmdargs } } } }
As it was discussed in the tcl'ers chatroom there are some complex situations that can arise with alias introspection, especially with cross interp aliases.
- info level, especially with a negative level, may not work as expected
- uplevel and upvar may do unexpected things