|Read more about this book|
(For more resources on TCL, see here.)
So, you’ve installed Tcl, written some scripts, and now you’re ready to get a deeper understanding of Tcl and all that it has to offer. So, why are we starting with the shell when it is the most basic tool in the Tcl toolbox?
When I started using Tcl I needed to rapidly deliver a Graphical User Interface (GUI) to display a video from the IP-based network cameras. The solution had to run on Windows and Linux and it could not be browser-based due to the end user’s security concerns. The client needed it quickly and our sales team had, as usual, committed to a delivery date without speaking to the developer in advance. So, with the requirement document in hand, I researched the open source tools available at the time and Tcl/Tk was the only language that met the challenge.
The original solution quickly evolved into a full-featured IP Video Security system with the ability to record and display historic video as well as providing the ability to attach to live video feeds from the cameras. Next search capabilities were added to review the stored video and a method to navigate to specific dates and times. The final version included configuring advanced recording settings such as resolution, color levels, frame rate, and variable speed playback. All was accomplished with Tcl.
Due to the time constraints, I was not able get a full appreciation of the capabilities of the shell. I saw it as a basic tool to interact with the interpreter to run commands and access the file system. When I had the time, I returned to the shell and realized just how valuable a tool it is and the many capabilities I had failed to make use of.
When used to its fullest, the shell provides much more that an interface to the Tcl interpreter, especially in the early stages of the development process. Need to isolate and test a procedure in a program? Need a quick debugging tool? Need real-time notification of the values stored in a variable? The Tcl shell is the place to go.
Since then, I have learned countless uses for the shell that would not only have sped up the development process, but also saved me several headaches in debugging the GUI and video collection. I relied on numerous dialog boxes to pop up values or turned to writing debugging information to error logs. While this was an excellent way to get what I needed, I could have minimized the overhead in terms of coding by simply relying on the shell to display the desired information in the early stages.
While dialog windows and error logs are irreplaceable, I now add in quick debugging by using the commands the shell has to offer. If something isn’t proceeding as expected, I drop in a command to write to standard out and voila! I have my answer. The shell continues to provide me with a reliable method to isolate issues with a minimum investment of time.
The Tcl shell
The Tcl Shell (Tclsh) provides an interface to the Tcl interpreter that accepts commands from both standard input and text files. Much like the Windows Command Line or Linux Terminal, the Tcl shell allows a developer to rapidly invoke a command and observe the return value or error messages in standard output. The shell differs based on the Operating System in use. For the Unix/Linux systems, this is the standard terminal console; while on a Windows system, the shell is launched separately via an executable.
If invoked with no arguments, the shell interface runs interactively, accepting commands from the native command line. The input line is demarked with a percent sign (%) with the prompt located at the start position. If the shell is invoked from the command line (Windows DOS or Unix/Linux terminal) and arguments are passed, the interpreter will accept the first as the filename to be read. Any additional arguments are processed as variables. The shell will run until the exit command is invoked or until it has reached the end of the text file.
When invoked with arguments, the shell sets several Tcl variables that may be accessed within your program, much like the C family of languages. These variables are:
|argc||This variable contains the number of arguments passed in with the exception of the script file name.
A value of 0 is returned if no arguments were passed in.
|argv||This variable contains a Tcl List with elements detailing the arguments passed in.
An empty string is returned if no arguments were provided.
|argv0||This variable contains the filename (if specified) or the name used to invoke the Tcl shell.|
|TCL_interactive||This variable contains a ‘1’ if Tclsh is running in interactive mode, otherwise a ‘0’ is contained.|
|env||The env variable is maintained automatically, as an array in Tcl and is created at startup to hold the environment variables on your system.|
Writing to the Tcl console
The following recipe illustrates a basic command invocation. In this example, we will use the puts command to output a “Hello World” message to the console.
To complete the following example, launch your Tcl Shell as appropriate, based on your operating platform. For example, on Windows, you would launch the executable contained in the Tcl installation location within the bin directory, while on a Unix/Linux installation, you would enter TCLsh at the command line, provided this is the executable name for your particular system. To check the name, locate the executable in the bin directory of your installation.
How to do it…
Enter the following command:
% puts "Hello World"
How it works…
As you can see, the puts command writes what it was passed as an argument to standard out. Although this is a basic “Hello World” recipe, you can easily see how this ‘simple’ command can be used for rapid tracking of the location within a procedure, where a problem may have arisen. Add in variable values and some error handling and you can rapidly isolate issues and correct them without the additional efforts of creating a Dialog Window or writing to an error log.
The expr command is used to evaluate mathematical expressions. This command can address everything from simple addition and subtraction to advanced computations, such as sine and cosine. This eliminates the need to make system calls to perform advanced mathematical functions. The expr command evaluates the input and arguments, and returns an integer or floating-point value.
A Tcl expression consists of a combination of operators, operands, and parenthetical containers (parenthesis, braces, or brackets). There are no strict typing requirements, so any white space is stripped by the command automatically. Tcl supports non-numeric and string comparisons as well as Tcl-specific operators.
Tcl expr operands
Tcl operands are treated as integers, where feasible. They may be specified as decimal, binary (first two characters must be 0b), hexadecimal (first two characters must be 0x), or octal (first two characters must be 0o). Care should be taken when passing integers with a leading 0, for example 08, as the interpreter would evaluate 08 as an illegal octal value. If no integer formats are included, the command will evaluate the operand as a floating-point numeric value. For scientific notations, the character e (or E) is inserted as appropriate. If no numeric interpretation is feasible, the value will be evaluated as a string. In this case, the value must be enclosed within double quotes or braces. Please note that not all operands are accepted by all operators. To avoid inadvertent variable substitution, it is always best to enclose the operands within braces. For example, take a look at the following:
- expr 1+1*3 will return a value of 4.
- expr (1+1)*3 will return a value of 6.
Operands may be presented in any of the following:
|Numeric||Integer and floating-point values may be passed directly to the command.|
|Boolean||All standard Boolean values (true, false, yes, no, 0, or 1) are supported.|
|Tcl variable||All referenced variables (in Tcl, a variable is referenced using the $ notation, for example, myVariable is a named variable, whereas $myVariable is the referenced variable).|
|Strings (in double quotes)||Strings contained within double quotes may be passed with no need to include backslash, variable, or command substitution, as these are handled automatically.|
|Strings (in braces)||Strings contained within braces will be used with no substitution.|
|Tcl commands||Tcl commands must be enclosed within square braces.
The command will be executed and the mathematical function is performed on the return value.
|Named functions||Functions, such as sine, cosine, and so on.|
Tcl supports a subset of the C programming language math operators and treats them in the same manner and precedence. If a named function (such as sine) is encountered, expr automatically makes a call to the mathfunc namespace to minimize the syntax required to obtain the value.
Tcl expr operators may be specified as noted in the following table, in the descending order of precedence:
|– + ~ !||Unary minus, unary plus, bitwise NOT and logical NOT.
Cannot be applied to string operands.
Bit-wise NOT may be applied to only integers.
Numeric operands only.
|*/ %||Multiply, divide, and remainder.
Numeric operands only.
|+ –||Add and subtract.
Numeric operands only.
|<< >>||Left shift and right shift.
Integer operands only.
A right shift always propagates the sign bit.
|< > <= >=||Boolean Less, Boolean Greater, Boolean Less Than or Equal To, Boolean Greater Than or Equal To (A value of 1 is returned if the condition is true, otherwise a 0 is returned).
If utilized for strings, string comparison will be applied.
|== !=||Boolean Equal and Boolean Not Equal (A value of 1 is returned if the condition is true, otherwise a 0 is returned).|
|eq ne||Boolean String Equal and Boolean String Not Equal (A value of 1 is returned if the condition is true, otherwise a 0 is returned).
Any operand provided will be interpreted as a string.
|in ni||List Containment and Negated List Containment (A value of 1 is returned if the condition is true, otherwise a 0 is returned).
The first operand is treated as a string value, the second as a list.
|^||Bitwise Exclusive OR
|&&||Logical AND (a value of 1 is returned if both operands are 0, otherwise a 1 is returned).
Boolean and numeric (integer and floating-point) operands only.
|x?y:z||If-then-else (if x evaluates to non-zero, then the return is the value of y, otherwise the value of z is returned).
The x operand must have a Boolean or a numeric value.