Related page:
Below are some specific rules governing the syntax of names. Please follow the rules exactly, since they make it possible to determine certain properties of a variable just from its name.
# CountNum is a private variable set CountNum 0 # The function addWindow is public proc addWindow {} {... # newWindow is a public interface in the spectcl namespace proc spectcl::newWindow {} {...
set numWindows 0
proc foo::Bar {arrayName} { upvar 1 $arrayName array ... }
proc log::eval {logScript} { if {$Log::logOn} { set result [catch {eval $logScript} msg] ...
before being a valid script should have names ending in Cmd.
foreach scrollCmd $listScrollCmds { eval $scrollCmd $args }
This section describes several low-level syntactic rules for writing Tcl code. These rules help to ensure that all of the Tcl code looks the same, and they prohibit a few confusing coding constructs.
Each level of indentation should be four spaces. There are ways to set 4-space indents in all of the most common editors. Be sure that your editor really uses four spaces for the indent, rather than just displaying tabs as four spaces wide; if you use the latter approach then the indents will appear eight spaces wide in other editors.
Comments that document code should occupy full lines, rather than being tacked onto the ends of lines containing code. The reason for this is that side-by-side comments are hard to see, particularly if neighboring statements are long enough to overlap the side-by-side comments. Also it is easy to place comments in a place that could cause errors. Comments must have exactly the structure shown in Figure 3, with a blank line above and below the comment. The leading blank line can be omitted if the comment is at the beginning of a block, as is the case in the second comment in Figure 3. Each comment should be indented to the same level as the surrounding code. Use proper English in comments: write complete sentences, capitalize the first word of each sentence, and so on.
# If we are running on the Macintosh platform then we can # assume that the sources are located in the resource fork # of our application, and we do not need to search for them. if {$tcl_platform(platform) == “macintosh”} { return } foreach dir $dirList { # If the source succeds then we are done. if {![catch {source [file join $dir file.tcl]}]} { break } }
Figure 3. Comments in code have the form shown above, using full lines, with lined-up hash marks, the comment takes at least a full line, and blank separator lines around each comment (except that the leading blank line can be omitted if the comment is at the beginning of a code block).
You should use continuation lines to make sure that no single line exceeds 80 characters in length. Continuation lines should be indented 8 spaces so that they won’t be confused with an immediately-following nested block. Pick clean places to break your lines for continuation, so that the continuation doesn’t obscure the structure of the statement. For example, if a procedure call requires continuation lines, try to avoid situations where a single argument spans multiple lines. If the test for an if or while command spans lines, try to make each line have the same nesting level of parentheses and/or brackets if possible. I try to start each continuation line with an operator such as *, &&, or ||; this makes it clear that the line is a continuation, since a new statement would never start with such an operator.
You should only have one Tcl command per line on the page. Do not use the semi-colon character to place multiple commands on the same line. This makes the code easier to read and helps with debugging.
Open curly braces can not appear on lines by themselves in Tcl. Instead, they should be placed at the end of the preceding line. Close curly braces are indented to the same level as the outer code, i.e., four spaces less than the statements they enclose. However, you should always use curly braces rather than some other list generating mechanism that will work in the Tcl language. This will help make code more readable, will avoid unwanted side effects, and in many cases will generate faster code with the Tcl compiler. Control structures should always use curly braces, even if there is only one statement in the block. Thus you shouldn’t write code like
if {$tcl_platform(platform) == "unix"} return
but rather
if {$tcl_platform(platform) == "unix"} { return }
This approach makes code less dense, but it avoids potential mistakes like unwanted Tcl substitutions. It also makes it easier to set breakpoints in a debugger, since it guarantees that each statement is on a separate line and can be named individually.
Use parentheses around each subexpression in an expression to make it absolutely clear what is the evaluation order of the expression (a reader of your code should not need to remember Tcl’s precedence rules). For example, don’t type
if {$x > 22 && $y <= 47} ...
Instead, type this:
if {($x > 22) && ($y <= 47)} ...
You should always explicitly use the return statement to return values from a Tcl procedure. By default Tcl will return the value of the last Tcl statement executed in a Tcl procedure as the return value of the procedure which often leads to confusion as to where the result is coming from. In addition, you should use a return statement with no argument for procedures whose results are ignored. Supplying this return will actually speed up your application with the new Tcl compiler. For example, don’t write code like this:
proc foo {x y} { if {$x < 0} { incr x } else { expr $x + $y } }
But rather, type this:
proc foo {x y} { if {$x < 0} { return [incr x] } else { return [expr $x + $y] } }
For Tcl procedures that have no return value a single return statement with no arguments is placed at the end of the procedure.
The switch statement should be formatted as below. Always use the – option to avoid having the string be confused with an option. This can happen when the string is user generated. Comments can be added on the same line as the pattern to comment the pattern case. The comments for each case should line up on the same tab stop and must be within the braces. Note that this is an exception to the standard commenting conventions.
switch -regexp -- $string { plus - add { # Do add task ... } subtract { # Do subtract case ... } default { ... } }
Never use the then word of an if statement. It is syntactic sugar that really isn’t that useful. However, the else word should always be used as it does impart some semantic information and it is more like the C language. Here is an example:
if {$x < 0} { ... } elseif {$x == 0} { ... } else { ... }
bind all <Shift-F1> {console show} set LabelText "Hello" set Message "Hello World!" pack [button .b -text $LabelText -command onButtonClick] proc onButtonClick {} { puts "Start of Reaction to Buttonclick" tk_messageBox -parent . -message $::Message puts "End of Reaction to Buttonclick" }
% info vars tcl_rcFileName tcl_version argv0 argv tcl_interactive tk_library tk_version LabelText auto_path errorCode tk_strictMotif errorInfo auto_index env tcl_patchLevel Message argc tk_patchLevel tcl_library tcl_platform% % winfo ch . .b # Replacement of the message of a modal window % set Message Hallo World! % set Message "Hello Tcl User!" Hello Tcl User! # Now press the Button "Hello" # and see that the new message # is displayed on the button of # the modal window # Replacement on the callback function # for a buttonclick: % proc onButtonClick {} { puts "New Start of Reaction to Buttonclick" tk_messageBox -parent . -message $::Message puts "New End of Reaction to Buttonclick" } # Now press the Button "Hello" # and see that by the buttonclick # now new messages are displayed # in the console window % proc e {} {uplevel #0 [clipboard get]} # Now mark the Tcl command "winfo ch .", # copy it with CTRL-C to the keyboard # and execute the command "e" # By this, the contents of the clipboard # is executed as Tcl command % e .b % proc i {} {puts $::errorInfo} # Now cause an error by an invalid command % abc invalid command name "abc" # So you can replay the last error, # by calling the "i" procedure % i invalid command name "abc" while executing "abc"