Linux
by Rick McMullin
IN THIS CHAPTER
- What Is Tcl?
- What Is Tk?
- The Tcl Language
- The Tk Language Extensions
This chapter introduces the Tcl programming language and its most popular extension,
Tk. This chapter covers the following topics:
- What Tcl is
- What Tk is
- The Tcl language
- The Tk language extensions
By the end of this chapter, you should understand what Tcl and Tk are, and also
how to write simple applications using Tcl and Tk.
Tcl stands for Tool Command Language. (It is pronounced "tickle.") It
is a scripting language similar to the shell scripting languages introduced in Chapter
13, "Shell Programming." Tcl can be used to quickly write text-based application
programs.
Tcl was developed by John Ousterhout, then of the University of California at
Berkeley. Tcl is an interpreted language and therefore has the usual advantages and
disadvantages of all interpreted languages. The key disadvantage of interpreted languages
is that they execute much slower than compiled languages. The biggest advantage of
interpreted languages is that developing applications using them is usually much
faster than using compiled languages. This is because you don't have to wait for
code to compile and can see any changes you make to the code almost instantly.
Tcl has a core set of built-in functions that provide the basic features of its
programming language. The true power of Tcl, however, is that it is easily extendible.
Application programmers can add functions to Tcl and can even imbed the Tcl function
library directly into their applications. This gives programmers the power to include
an interpretive scripting language directly in their own application without having
to do any of the work of developing the language. This means that you can provide
users of your application with all the commands that exist within Tcl and also any
that you create and add to the Tcl library.
Invoking Tcl commands is done by starting up the Tcl shell, called tclsh
(or on some systems, tcl). Once you have started tclsh, you can
type Tcl commands directly into it. Straying slightly from the "hello world"
example that you find in almost every introductory language text, the following example
shows you how to write Hello there instead to the screen:
puts stdout "Hello there"
This command contains three separate words. The first word in the command is the
actual command name, puts. The puts command is an abbreviation
for put string; it simply writes something to the device that is specified in the
second word of the command. In this case the second word tells puts to write
to the standard output device, which is typically the screen. The third word in the
puts command is "Hello there". The quotation marks tell
Tcl to interpret everything contained within them as a single word.
-
NOTE: The default output
device is stdout (standard output, usually the screen), so if you intend
to write something to stdout using the puts command, the second
argument is optional.
Even though this is a very simple example, it illustrates the basic command syntax
of the Tcl language. There are obviously many more commands contained within Tcl,
but the basic syntax of all Tcl commands is the same:
command parameter1 parameter2 ...
The command can be any of the built-in Tcl commands, or it can be a user-defined
extension to the Tcl command set in the form of a Tcl procedure. In either case,
the fundamental syntax remains unchanged.
Tk, which was also developed by Ousterhout, is a graphical user interface extension
to Tcl. Tk is based on the X Window system and allows application developers to develop
X Window-based applications much faster than they could using other X Window toolkits,
such as Motif or OPEN LOOK.
Like Tcl, Tk also has a shell that enables you to enter commands to be interpreted.
The Tk shell is a superset of the Tcl command shell. This means that anything you
can do in the Tcl command shell you can also do in the Tk command shell. The big
difference between the two is that the Tk command shell was designed to enable you
to build X Window front ends to your applications.
The Tk command shell is called wish, which stands for windowing shell.
You must be running X Window when you invoke wish. This is because when
wish is invoked, it brings up a window to display the results of any of
the graphical commands it interprets. When you invoke wish, a window should
appear on your screen.
Now that you have seen what the Tk environment looks like, let's try enhancing
the earlier "Hello there" example by displaying Hello there in
a button in the wish window. To accomplish this, you must first ensure that
wish has been started. This is easily done by typing the following command
into an Xterm window:
wish
This command brings up the wish window and also executes the Tk interpreter
in the Xterm window. You can now type Tcl or Tk commands directly in the Xterm window.
These are the commands necessary to print Hello there in a button in the
wish window:
button .b -text "Hello there." -command exit
pack .b
Notice how the syntax of the command on the first line is essentially the same
as the syntax of the puts command. It contains the command name followed
by a number of arguments. The first argument is the name you are giving to the new
button. The rest of the arguments passed to the button command are slightly
different from the arguments you saw in the Tcl version of the "Hello there"
example. These arguments each consist of two parts. The first part tells Tk what
the argument name is, and the second part tells Tk the value of the argument.
The second argument has the name text, and the value of the argument
is the string you want to display in the button. The third argument has the name
command and is used to specify the command that you want to execute when
that button is pushed. In this example, you do not really want anything to happen
if the button is pushed, so you just tell wish to exit from the current
script.
The button command created a button widget that you called .b.
To get the button to show up in the wish window, you must tell Tk to display
the button. This is done by the pack command.
In this example, the pack command has only one argument: the name of
the button that you created in the first command. When the pack command
is executed, a button with the string Hello there displayed in it appears
in the wish window.
Two things about this example are worth discussing in more detail. The first is
why you called the button .b instead of b, bob, or button1.
The significance is not the actual text in the button name (this in fact could be
bob or button1), but the period (.) preceding the name
of the button.
The period notation is used to represent the widget hierarchy. Each widget is
contained in another widget. The root widget, or the highest level widget, is contained
in the wish window and is called . (this is analogous to the Linux
directory structure, in which each directory has an owner or a parent directory and
the root or highest level directory is named /). Each time you create a
new widget, you must tell Tk which widget the new widget should be contained in.
In the "Hello there" example, the container specified for the button widget
was ., the root widget.
The second item of interest is the resizing of the wish window that occurs
after you enter the pack command. The wish window shrinks down
to a size that is just large enough to hold the button you created. Tk causes the
wish window to default to a size just large enough to hold whatever it has
in it. Many commands can be used to change this behavior and customize how things
are displayed on the screen. You will see some of these commands later in this chapter.
Now that you have seen examples of both Tcl and Tk in action, it is appropriate
to take a step back and look at the underlying Tcl language in more detail. Tcl contains
a rich set of programming commands that support all the features found in most high-level
languages. This section discusses many of these features and gives examples that
explain how to use them.
Like the UNIX shell programming languages, Tcl supports the concept of variables.
Variables are temporary storage places used to hold information that will be needed
by a program at some later point in time. In Tcl, variable names can consist of any
combination of printable characters.
Typically, variable names are meaningful names that describe the information being
stored in them. For example, a variable that is being used to hold the monthly sales
of a product might have one of the following names:
Monthly_sales
"Monthly sales"
-
NOTE: Quotation marks
cause Tcl to ignore the whitespace characters (spaces and tabs) in the variable name
and treat it as one word. This is discussed in the "Quotes" section of
this chapter.
The value that is placed into a variable can also be any combination of printable
characters. Possible values for the Monthly_sales variable are
"40,000"
40000
"refer to table 3"
The Tcl set command is used to assign values to variables. The set
command can pass either one or two arguments. When two arguments are passed to the
set command, the first one is treated as the variable name and the second
is the value to assign to that variable.
When the set command is used with only one argument, Tcl expects the
argument to be the name of a variable, and the set command returns the value
of that variable. The following command assigns the value of 40000 to the variable
Monthlysales and then echoes the value to the screen:
set Monthlysales 40000
To print the value of the Monthlysales variable to the screen, you would
type
set Monthlysales
All values that are assigned to variables are stored as character strings. If
you defined a variable to be equal to the integer 40, as in the following command
set num 40
the value 40 would be represented as the character string 40, not as
an integer.
So far you have seen how to set variables and how to display their values to the
screen, but you have not seen how they are used with commands other than the set
command. To use the value of a variable in another command, you must precede the
variable name with an unquoted dollar sign ($). This tells Tcl to expect a variable
name and to substitute the value of that variable for the variable name. The following
example shows a simple use of variable substitution:
set Monthlysales 40000
expr $Monthlysales * 12
The first command assigns the value of 40000 to the variable Monthlysales.
The expr command is used to perform mathematical evaluations of expressions.
In this case it takes the value of the variable Monthlysales and multiplies
it by 12.
Command substitution provides a way of substituting the result of a Tcl command
(or commands) into an argument of another command. The syntax for command substitution
is to include the commands that are being substituted in square brackets, as follows:
set Monthlysales 40000
set Yearlyforecast [ expr Monthlysales * 12 ]
The first command once again sets the variable Monthlysales to the value
of 40000. The second command makes use of command substitution to set the value of
Yearlyforecast equal to the result of the command in the square braces.
In this example the substitute consisted of only one command. Tcl allows the substitute
to consist of any valid Tcl script, meaning that it can contain any number of Tcl
commands.
Often you want to use commands containing special characters that you don't want
Tcl to interpret. By quoting these characters, you hide the special characters from
the Tcl interpreter.
Three kinds of quoting can be used in Tcl scripts. The first is quoting with double
quotation marks (""). This kind of quoting is used to hide whitespace
characters and command separators from the Tcl interpreter.
Whenever you have two or more words that you want Tcl to treat as a single word,
you can do so by surrounding the words with quotation marks. A good example of this
type of quoting is when you want to create variable names that contain more than
one word, or you want to assign a value that contains more than one word to a variable,
as follows:
set "Monthly sales" 40000
set Heading1 "Description of item"
The second kind of quoting uses the backslash character (\). This type
of quoting can hide any single character from the interpreter. This form of quoting
is most commonly used to hide special characters, such as $, from the Tcl
interpreter. The following example illustrates the need for backslash quoting:
set Header1 "The cost is \$3.50"
In this example the Header1 variable is being assigned the value The
cost is $3.50. The quotation marks are necessary to hide the fact that there
are four separate words contained in the character string. The backslash in this
command tells the Tcl interpreter to treat the $ as a regular character
instead of the variable substitution character. If the backslash was not used in
the command, the interpreter would attempt to substitute the variable named 3.50
into the command. This would result in an error, because there is no variable with
that name defined.
The third type of quoting available in Tcl uses curly braces ({}). This
quoting is more powerful than quoting using quotation marks or backslashes. Quoting
using braces hides not only whitespace and command separators from the Tcl interpreter
but also any other kind of special character. This type of quoting can be used to
eliminate the need for backslash quoting in character strings. The example used for
backslash quoting could be written using brace quotation as follows:
set Header1 {The cost is $3.50}
The most important use of curly brace quoting is to defer the evaluation of special
characters. This means that special characters are not processed immediately by the
Tcl interpreter but are instead passed to a command that processes the special characters
on its own. An example of when deferred evaluation is used is in the while
command:
set count 0
while {$count < 3} {
puts "count equals $count"
set count [expr $count + 1]
}
The while command has to evaluate both of its arguments each time it
iterates through the loop. It is therefore necessary for the interpreter to ignore
the special characters in both of these arguments and leave the evaluation of these
characters up to the while command.
Now that you have all the language basics out of the way, you can move on to some
of the more advanced Tcl commands.
The if command, just like in other languages, evaluates an expression
and, based on the results of the expression, executes a set of commands. This is
the syntax of the if command:
if {expr} {commands}
The if command expects two arguments. The first argument is an expression
that is used to determine whether to execute the commands contained in the second
argument. The expression argument is typically an expression that evaluates to either
True or False. For example:
$i < 10
$num = 2
-
NOTE: Tcl treats any
expression that evaluates to zero to be False and any expression that evaluates to
a non-zero value to be True.
Expressions such as the following, although valid, do not make much sense in the
context of an if command:
$i + $b
10 * 3
The second argument to the if command is a Tcl script, which can contain
any number of Tcl commands. This script is executed if the expression contained in
the first argument evaluates to True.
The if commands can have one or more elseif commands and one
else command associated with them. The syntax for these commands is shown
here:
if {expr} {
commands }
elseif {expr} {
commands }
elseif {expr} {
commands }
else {
commands }
The commands associated with the first if or elseif whose expression
evaluates to True are executed. If none of these expressions evaluate to True, the
commands associated with the else command are executed.
-
WARNING: The open curly
brace must occur on the same line as the word that precedes it. This is because new
lines are treated as command separators. If you entered an if command where
the if {expr} portion of the command appeared on one line and the
rest was on the next line, it would be treated as two separate commands.
The for command in Tcl provides a way of implementing for loops.
Tcl for loops are very similar to for loops in other languages,
such as C. The for command expects four arguments. The first argument is
a script that is used to initialize the counter. The second argument is an expression
that is evaluated each time through the loop to determine whether to continue. The
third argument is used to define the increment to be used on the counter. The fourth
argument is the set of commands to be executed each time through the loop.
for { set i 0} {$i < 10} {incr i 1} {
puts [expr 2 * $i]
}
The preceding loop executes ten times. The counter i is initially set
to 0. The for loop executes while i is less than 10, and the value
of i is increased by 1 each time through the loop. The command that is executed
each time through the loop is the puts command. This evaluates 2 x i
each time through the loop and prints the result to the screen. The output that results
from running this command is listed here:
0
2
4
6
8
10
12
14
16
18
The while command is used to implement while loops in Tcl. while
loops are very similar to for loops. The only real difference between them
is that the for loop provides more enhanced features for controlling entrance
and exit criteria for the loop. The syntax for the while loop is shown in
the following example:
set i 0
while {$i < 10} {
puts [expr 2 * $i]
set i [expr $i + 1]
}
This while loop performs the same function as the example that was presented
in the section describing the for loop. It calculates 2 x i each
time through the loop and prints the result to the screen. Notice that in this example
you have to handle incrementing the counter yourself. With the for loop,
the counter incrementing was taken care of by the for command.
The switch command provides the same function as an if statement
that has multiple elseif clauses associated with it. The switch
command compares a value (this value is usually stored in a variable) with any number
of patterns, and if it finds a match it executes the Tcl code associated with the
matching pattern.
switch $thing {
car {puts "thing is a car"}
truck {puts "thing is a truck"}
default {puts "I don't know what this thing is"}
}
-
NOTE: The Tcl switch
command is equivalent to the case statement found in Pascal and some other
languages.
This switch command compares the value that is stored in the thing
variable (which must be set prior to these statements, of course) with the string
car and the string truck to see if it matches either of them. If
the value of the thing variable is equal to car, then thing
is a car is displayed on the screen. If the value of the thing variable
is equal to truck, then thing is a truck is displayed on the screen.
If neither of these cases are true, the default clause is executed and I don't
know what this thing is displays on the screen.
-
TIP: Whenever you need
to check to see if a variable is equal to one of a number of values, you should use
a switch command instead of an if command with multiple elseif
clauses. This makes your code much easier to read and understand.
It is always a good idea to include comments in any Tcl code you write--or code
you write in any other language, for that matter. This becomes especially important
if any of the following situations is possible:
- Someone else needs to look at or maintain your code.
- Your programs get large.
- You won't be looking at code that you have written for long periods of time after
you write it.
Chances are that at least one of these situations will come up with Tcl code you
have written.
Comments cannot be placed in the middle of a command. They must occur between
commands. The pound sign (#) is used to inform Tcl to expect a comment.
# This is a valid comment
set a 1 ; # This is a valid comment
set a 1 # This is an invalid comment
The third comment shown here is invalid because it occurs in the middle of a command.
-
NOTE: Recall that Tcl
interprets everything up to a newline character or a semicolon to be part of the
command.
Earlier in this chapter, a simple example of Tk displayed Hello there
in a button in the wish window. Tk is much more powerful than that example
showed. Along with the button widget are many other widgets provided by Tk. These
include menus, scrollbars, and list boxes. This section gives you an overview of
some of the other Tk widgets and gives short examples explaining how these widgets
can be used.
Frame widgets are containers for other widgets. They do not have any interesting
behavior like the other Tk widgets. The only visible properties of frame widgets
that you can set are their color and their border appearance. You can give three
different border appearances to a frame widget: flat, raised, and sunken. You can
experiment with the different frame widgets to see how they look.
The flat border frame widget is not too exciting. It looks exactly the same as
the default wish window (because the default border appearance is flat).
Button widgets are used to get specific input from a user. A button can be turned
on or activated by the user of a Tk program by moving the mouse pointer over the
button and then pressing the left mouse button. Tk provides the following three kinds
of button widgets:
- Button
- Check button
- Radio button
The button widget is used to initiate some specific actions. The button usually
has a name such as "Load file" that describes the action that results if
you press the button.
Check button widgets are used to allow users of a program to turn program options
on or off. When the check button is shaded the program option is on, and when the
check button is not shaded the program option is off.
Radio buttons are similar to check buttons except that they are defined in groups,
where only one member of a group of radio buttons is allowed to be on at one time.
This means that if one radio button in a group of radio buttons is on, none of the
other radio buttons in that group can be turned on. When the radio button is shaded
it is on, and when the radio button is not shaded it is off.
Menu widgets are used to implement pull-down menus, cascading menus, and pop-up
menus. A menu is a top-level widget that contains a set of menu entries that have
values or commands associated with them. Five kinds of entries can be used in menus:
- Cascade entries display a submenu when the mouse pointer passes over them. The
cascade entry is similar in function to the menu button widget.
- Command entries invoke a Tcl script when activated. The command entry is similar
to the button widget in function.
- Check button entries toggle a program option between on and off. When the check
button is shaded the option is on, and when the check button is not shaded it is
off. The check button entry is similar in function to the check button widget.
- Radio button entries toggle a program option. The difference between the radio
button entry and the check button entry is that radio buttons are typically defined
in groups, with the restriction that only one of the radio buttons in the group can
be active at once. The radio button entry is similar in function to the radio button
widget.
- Separator entries display a horizontal line in the menu. This is used for appearance
purposes only. There is no behavior associated with a separator entry.
The main difference between the menu entries and the button widgets is that the
button widgets can exist by themselves, but the menu entries must exist within the
context of a menu widget.
Menu button widgets are similar to button widgets. The only real difference between
the two is that when menu buttons are invoked they bring up menus instead of executing
Tcl scripts as button widgets would. The menu button name usually describes the types
of menu entries contained in the menu that the menu button activates. This means
that you should find menu entries that perform some kind of file operations contained
within the File menu.
You can activate a menu by moving the mouse pointer to the menu button widget
and pressing the left mouse button. This activates the menu associated with the menu
button and displays the menu entries that are contained in that menu to the screen.
You can now move the mouse pointer down through the list of menu entries and select
the one you want.
The File menu contains two command entries (the Open entry and Quit entry), one
cascade entry (the Save As entry), and one separator entry. The menu that comes up
as a result of clicking the mouse pointer on the Save As cascade entry contains three
command entries: the Text entry, the Ver 1 file entry, and the Ver 2 file entry.
The list box widget enables users of a Tk application to select items from a list
of one or more items. If the number of items to be displayed in the list box is larger
than the number of lines in the list box, you can attach scrollbars to make the extra
items accessible.
Scrollbar widgets are used to control what is displayed in other widgets. Scrollbar
widgets are attached to other widgets to allow users to scroll up and down through
the information contained in the widget. You typically put scrollbars on any widget
that is designed to contain an arbitrary number of lines of information (such as
a list box) or on widgets that contain more lines of information than the widget
can display, given its size.
This chapter started off by introducing Tcl and the Tk tool kit and describing
the uses of both. Although this chapter contained a lot of information, it barely
scratched the surface of the programming tools provided by Tcl and the Tk tool kit.
Tcl has many more programming features than were described in this book. Some
of the most notable are arrays, lists, and procedures.
Not all of the Tk widgets were described here, either. Some of the widgets that
were not described are canvasses, scales, labels, messages, and textedit
widgets.
Tk is just one example of an extension to Tcl. There are many other extensions
available that extend the behavior of Tcl in different ways. Some of these extensions
are listed here:
- Ak: An audio extension for Tcl, Ak provides numerous commands for sound recording
and playback.
- XF: This is an interactive graphical user interface developer for Tk.
- Tcl-DP: This is a Tcl extension that helps programmers develop distributed applications
using Tcl.
If you would like to learn more about Tcl and Tk, a good place to start is the
manual pages for Tcl, Tk, and any of the specific commands you want information about.
There are also a few books available that are devoted to Tcl and Tk programming.
Contact
reference@developer.com with questions or comments.
Copyright 1998
EarthWeb Inc., All rights reserved.
PLEASE READ THE ACCEPTABLE USAGE STATEMENT.
Copyright 1998 Macmillan Computer Publishing. All rights reserved.