A '''command''' is a sequence of '''[word]s''' in a [script] evaluated by an [interpreter]. ** See Also ** [Dodekalogue]: The rules of Tcl. [Tcl Commands%|%Tcl commands]: [Command prefix%|%command prefix]: [Command variety%|%command variety]: ** Description ** When an [interpreter] encounters a command, it finds the [routine] associated with the command and calls it with the arguments given in the command. The first in a command is the name of the command, and the remaining words are arguments. Many things that have dedicated syntax in other languages are just commands in Tcl. Examples include [control structure%|%control structures], like `[if]`, `[while]`, and `[for]`, declarations like `[global]`, `[proc]`, and `[variable]`. Even `[return]` is just another command. The names of all commands available from the current [namespace] are returned by ====== info commands ====== They may have come from several sources: * [C]-implemented commands * Tcl-implemented [proc%|%procs], listed in `[info procs]` * Aliases for other commands, listed in `[interp aliases] {}` * [Tk] [widget%|%widgets] use their pathname as command; you can test whether a string is a widget command with `[winfo exists] $name` * [image%|%images] also use their name as command name, listed in `[image names]` * [object orientation%|%object] systems like [incr Tcl] also use object names in the command position The following proc returns the type of a command, or an empty string if the name is not a command: ====== proc command'type2 name { foreach {result condition} { unsourced {[info commands $name] eq {} && [info exists ::auto_index($name)]} {} {[info command $name] eq {}} proc {[info procs $name] eq $name} alias {[lsearch [interp aliases {}] $name] >= 0} image {[lsearch [image names] $name] >= 0} widget {[winfo exists $name]} command 1 } {if $condition {return $result}} } ;# RS ====== To introspect commands in other than the current namespace, walk the tree with `[namespace children]`. `[info procs]` and `[info commands]` behave differently. As the above piece of code demonstrates, there are independent uses for the two. ---- [Cameron Laird] pointed out: The succinct `command'type2` definition is slightly nonrobust in the face of, for example, ====== proc tcl* args {} ====== It's far from alone in that minor weakness, of course And there is a way to fix this: while [[info proc]] gets disturbed by the asterisk (and returns a number of proc names that start with ''tcl''), other subcommands like [[info args]] don't do glob matching, so replacing the "proc" case above with ======none proc {![catch {info args $name}]} ====== fixes the problem. Thank you! ([RS]) CL responds with a couple of observations: 1. This is minor stuff. There are applications in production that have far bigger robustness problems, yet have been satisfying end-users for years. I can't even bring myself to call this a problem--it's more of a footnote. 2. On the other hand, it interests and entertains me how often programs admit minor transformations that are strictly superior in the sense that they're as readable and succinct, while being "more correct" (satisfying over a wider input space, for example). I salute Richard for so quickly finding such a transformation in this case. ---- [LV] 2008-06-26: `command'type2` has a requirement that [Tk] be loaded before you use it. Judious use of `[catch]` probably could handle the issue... [Lars H]: Another problem is that alias names aren't normalized — `[interp alias]` faithfully records exactly the string used when creating the alias, but the `$name` used for the command can be very different. For example, if you do ====== foreach ns {:: bar ::baz} { interp alias {} ${ns}::foo {} ::foopkg::dispatch $ns {some more data} } ====== then `[interp aliases]` will faithfully `[return]` ====== ::::foo bar::foo ::baz::foo ====== and it is ''only'' these strings you can use with `[interp alias]` if you want to look up what the alias points to. ---- [SS] 2006-06-30: [schlenk] just produced this procedure to check if a given command exists, it is in theory trivial but in pratice to get it right is not too simple, so maybe it's a good idea to put the proc here: ====== proc cmd_exists cmd { string equal {} [namespace eval :: [list namespace which $cmd]] } ====== This above checks if the command is fully qualified basically (callable from the global namespace with the given name), and could be used for a callback. If you just want to see the fully qualified name, use a simple [namespace which]. ---- Can't you just use `[info]`? ====== $ tclsh % info command info info % info command nonsense % ====== [schlenk]: Not if you have funny command names that are glob patterns like a proc named `*` or `info*`, as info command does not have an -exact switch. [LV]: well, technically you can: ====== $ tclsh % proc info* {args} {return} % info command info* info info* % info command {info*} info info* ====== However, the info command returns _all_ the matching names in this case, so you have to be ready to deal with that. That's a bit annoying. [Lars H]: It is perfectly possible to do an exact search by escaping all glob metacharacters in the string, e.g. ====== proc cmd_exists_2 {cmd} { llength [info commands [string map {\\ \\\\ * \\* ? \\? [ \\[ ] \\]} $cmd]] } ====== Then whether this would be any faster than the `[namespace which]` form is another matter... I suspect it could be that they don't do exactly the same thing when it comes to not-fully-qualified names, and that depending on the problem one might want one or the other. [escargo] 2005-07-01: Maybe there is some argument for making '''all''' the commands that use `[glob]` matching by default also accept `-exact` (and maybe even `-regexp`). Using `[glob]` matching by default is a convenience, but more specific behavior should be allowed. Making commands more uniform (by ensuring uniform matching behavior) seems like it would make the language more regular and easier to understand. [Lars H]: Well, that sounds like a short summary of [TIP] [http://tip.tcl.tk/246.html%|%246]. [NEM]: You can always use either: ====== expr {$cmd in [info commands]} lsearch -exact [info commands] $cmd ====== ---- [DKF] 2012-10-20: I'm working on a project to [List of Tcl commands by bytecode status%|%identify] what commands ''should'' be bytecode-compiled (and what are and aren't). ** Page Authors ** [Richard Suchenwirth]: [PYK]: <> Glossary