Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 13.  Reflection and Debugging

Interactive Command History

The Tcl shell programs keep a log of the commands that you type by using a history facility. The log is controlled and accessed via the history command. The history facility uses the term event to mean an entry in its history log. The events are just commands, and they have an event ID that is their index in the log. You can also specify an event with a negative index that counts backwards from the end of the log. Event -1 is the previous event. Table 13-5 summarizes the Tcl history command. In the table, event defaults to -1.

In practice you will want to take advantage of the ability to abbreviate the history options and even the name of the history command itself. For the command, you need to type a unique prefix, and this depends on what other commands are already defined. For the options, there are unique one-letter abbreviations for all of them. For example, you could reuse the last word of the previous command with [hist w $]. This works because a $ that is not followed by alphanumerics or an open brace is treated as a literal $.

Several of the history operations update the history list. They remove the actual history command and replace it with the command that resulted from the history operation. The event and redo operations all behave in this manner. This makes perfect sense because you would rather have the actual command in the history, instead of the history command used to retrieve the command.

Table 13-5. The history command.
historyShort for history info with no count.
history add command ?exec?Adds the command to the history list. If exec is specified, then execute the command.
history change new ?event?Changes the command specified by event to new in the command history.
history event ?event?Returns the command specified by event.
history info ?count?Returns a formatted history list of the last count commands, or of all commands.
history keep countLimits the history to the last count commands.
history nextidReturns the number of the next event.
history redo ?event?Repeats the specified command.

History Syntax

Some extra syntax is supported when running interactively to make the history facility more convenient to use. Table 13-6 shows the special history syntax supported by tclsh and wish.

Table 13-6. Special history syntax.
!!Repeats the previous command.
!nRepeats command number n.If n is negative it counts backward from the current command. The previous command is event -1.
!prefixRepeats the last command that begins with prefix.
!patternRepeats the last command that matches pattern.
^old^newGlobally replaces old with new in the last command.

The next example shows how some of the history operations work:

Example 13-10 Interactive history usage.
% set a 5
% set a [expr $a+7]
% history
   1 set a 5
   2 set a [expr $a+7]
   3 history
% !2
% !!
% ^7^13
% !h
   1 set a 5
   2 set a [expr $a+7]
   3 history
   4 set a [expr $a+7]
   5 set a [expr $a+7]
   6 set a [expr $a+13]
   7 history

A Comparison to C Shell History Syntax

The history syntax shown in the previous example is simpler than the history syntax provided by the C shell. Not all of the history operations are supported with special syntax. The substitutions (using ^old^new) are performed globally on the previous command. This is different from the quick-history of the C shell. Instead, it is like the !:gs/old/new/ history command. So, for example, if the example had included ^a^b in an attempt to set b to 39, an error would have occurred because the command would have used b before it was defined:

set b [expr $b+7]

If you want to improve the history syntax, you will need to modify the unknown command, which is where it is implemented. This command is discussed in more detail in Chapter 12. Here is the code from the unknown command that implements the extra history syntax. The main limitation in comparison with the C shell history syntax is that the ! substitutions are performed only when ! is at the beginning of the command:

Example 13-11 Implementing special history syntax.
# Excerpts from the standard unknown command
# uplevel is used to run the command in the right context
if {$name == "!!"}{
   set newcmd [history event]
} elseif {[regexp {^!(.+)$}$name dummy event]}{
   set newcmd [history event $event]
} elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$}$name x old new]}{
   set newcmd [history event -1]
   catch {regsub -all -- $old $newcmd $new newcmd}
if {[info exists newcmd]}{
   history change $newcmd 0
   return [uplevel $newcmd]

      Previous section   Next section