1.3 Script Files
In the examples so far, you have entered Tcl commands interactively to tclsh or wish. You can also place commands into script files and invoke the script files just like shell scripts. To do this for the "Hello, world!" example, place the following text in a file named hello.tcl:
#!/usr/local/bin/wish button .b -text "Hello, world!" -command exit pack .b
You can execute this script by invoking the wish interpreter and passing the script file name as a command-line argument:
wish hello.tcl
This causes wish to display the same window as shown in Figure 1.1 and wait for you to interact with it. In this case you will not be able to type commands interactively to wish; all you can do is click on the button.
1.3.1 Executable Scripts on Unix and Mac OS X
The script just shown is the same as the one you typed earlier except for the first line. As far as wish is concerned, this line is a comment, but on Unix systems if you make the file executable (for example, by executing chmod +x hello.tcl in your shell), you can then invoke the file directly by typing hello.tcl to your shell. (This requires the directory containing your hello.tcl script to be listed in your PATH environment variable.) When you do this, the system invokes wish, passing it the file as a script to interpret.
As written, this script works as an executable script only if wish is installed in /usr/local/bin, although you could still run it by invoking wish with the script file name as a command-line argument. If wish has been installed somewhere else, you need to change the first line to reflect its location on your system. Some systems misbehave in confusing ways if the first line of the script file is longer than 32 characters, so beware if the full path name of the wish binary is longer than 27 characters.
To work around these limitations, a common technique for scripts on Unix has been to start script files with the following three lines:
#!/bin/sh # Tcl ignores the next line but 'sh' doesn't exec wish "$0" "$@"
or the more arcane but more robust version:
#!/bin/sh # Tcl ignores the next line but 'sh' doesn't exec wish "$0" ${1+"$@"}
In most modern Unix implementations, though, the following will work correctly, as long as wish appears in one of the directories in your PATH environment variable:
#!/usr/bin/env wish
1.3.2 Executable Scripts on Windows
On Windows, you can use the standard system tools to associate the wish interpreter with a file extension (.tcl by convention) so that double-clicking on the icon for a Tcl/Tk script automatically invokes the wish interpreter, passing it the name of the file as a script to interpret. Most Windows installers for Tcl/Tk automatically create this association for you. wish is typically selected as the default association because most Windows-based Tcl/Tk programs are GUI-based. However, if the majority of your Tcl scripts don't use Tk commands, you could change the default association to invoke tclsh.
If you plan to distribute your scripts on multiple platforms, you should include the appropriate #! header as discussed in the previous section for Unix executable scripts so that they can be directly executable on Unix systems. On the other hand, Windows doesn't follow the #! convention, and the #! line is treated as a comment by the wish interpreter, so the net effect is that the line is ignored when the script is run on a Windows system.
1.3.3 Executing Scripts in an Interactive Interpreter
In practice, users of Tk applications rarely type Tcl commands; they interact with the applications using the mouse and keyboard in the usual ways you would expect for graphical applications. Tcl works behind the scenes where users don't normally see it. The hello.tcl script behaves just the same as an application that has been coded in C with a GUI toolkit and compiled into a binary executable file.
During debugging, though, it is common for application developers to type Tcl commands interactively. For example, you could test the hello.tcl script by starting wish interactively (type wish to your shell instead of hello.tcl). Then enter the following Tcl command:
source hello.tcl
source is a Tcl command that takes a file name as an argument. It reads the file and evaluates it as a Tcl script. This generates the same user interface as if you had invoked hello.tcl directly from your shell, but you can now enter Tcl commands interactively, too. For example, you could edit the script file to change the -command option to
-command "puts Good-bye!; exit"
then enter the following commands interactively to wish without restarting the program:
destroy .b source hello.tcl
The first command deletes the existing button, and the second command re-creates the button with the new -command option. Now when you click on the button, the puts command prints a message on standard output before wish exits.