HELP HISTORY John Williams, Jan 1988 CONTENTS - (Use g to access required sections) 1 Introduction 2 *history-max* 3 Special History Commands 4 Referring to History Events 5 Examining the History 6 Editing and Re-Doing Commands 7 Command Expansion 8 Extending the HISTORY Module ----------------------------------------------------------------------- 1 Introduction ----------------------------------------------------------------------- This file documents the HISTORY module, which provides a simple history facility for recording commands entered to the Lisp top-level loop. It is loosely based on the Unix C-shell history mechanism. To load the HISTORY module, do (require :history) This modifies the Lisp top-level loop so that for each form evaluated, a history event is created. This event comprises the form itself (termed the command), and a list of the values it produced (termed the results). Events are labelled by a unique numeric integer value (its index). Note: The functions and variables defined by the HISTORY module are all external symbols of the Poplog package. ----------------------------------------------------------------------- 2 *history-max* ----------------------------------------------------------------------- The maximum number of events stored at any one time is controlled by the variable *history-max*. Its initial value is 20. There is no limit if the value is nil. Setting *history-max* to 0 disables the history ----------------------------------------------------------------------- 3 Special History Commands ----------------------------------------------------------------------- The HISTORY module defines four special top-level commands: :history Displays a backtrace of recorded history events :show index Displays event referenced by index :fix index Allows editing of event referenced by index :redo index Re-evaluates command referenced by index If index is omitted, the most recent event is processed. ----------------------------------------------------------------------- 4 Referring to History Events ----------------------------------------------------------------------- Events may be referenced in four different ways: 1. An integer, n, > 0 Refers to the event numbered n. 2. An integer, n, < 0 Refers to the n'th most recent event, i.e. -1 means the last event. 3. A string, s Searches back to the most recent event whose leftmost symbol starts with s. (case-sensitive). 4. Any other object, x Searches back to the most recent event whose leftmost atom is eq to x. ----------------------------------------------------------------------- 5 Examining the History ----------------------------------------------------------------------- To illustrate, consider the following three events: == (set '*print-array* nil) NIL == (setq vec #(a b c)) # == (elt vec 0) A Now examine the history: == :history 1: (SET '*PRINT-ARRAY* ()) 2: (SETQ VEC #) 3: (ELT VEC 0) Examine the first event. There are three ways this could be done: :show 1 :show -3 :show set However, :show "SET" would refer to command 2, not command 1. This is what :show actually looks like: == :show 1 1: (SET '*PRINT-ARRAY* ()) => NIL The first line of output is the command, the second (starting with =>) is its results. Forms are added to the history before they are evaluated, so that commands are accessible during break points should they cause an error. ----------------------------------------------------------------------- 6 Editing and Re-Doing Commands ----------------------------------------------------------------------- To re-evaluate a given history command, use :redo. For example: == :redo set 1: (SET '*PRINT-ARRAY* ()) NIL Notice that the specified command is displayed prior to execution. The command :fix may be used to edit commands before re-doing them: == :fix set "(SET '*PRINT-ARRAY* ())" Old: () New: T "(SET '*PRINT-ARRAY* T)" Eval? (y/n) y T == vec #(A B C) Commands are treated as text strings (i.e. they are converted to strings via the function prin1-to-string). The user is prompted for a sub-string to be replaced (Old:), and string to replace it with (New:). The strings are read using the function read-line; typing will result in the :fix being abandoned. After substitution, the user is given the option of re-evaluating the edited command. If this is not taken, the user has the option of replacing another sub-string of the command, or abandoning the :fix operation. ----------------------------------------------------------------------- 7 Command Expansion ----------------------------------------------------------------------- The macro character ! may be used to substitute history commands into expressions read by the Lisp reader. For example: == (defun fac (x) (if (zerop x) 1 (* (fac (1- x)) x))) FAC == (fac 50) 30414093201713378043612608166064768844377641568960512000000000000 == (integer-length !fac) 215 == :history 1: (DEFUN FAC (X) (IF (ZEROP X) 1 (* (FAC (1- X)) X))) 2: (FAC 50) 3: (INTEGER-LENGTH (FAC 50)) Note: this facility is not available if the character ! has already been defined as a read macro. ----------------------------------------------------------------------- 8 Extending the HISTORY Module ----------------------------------------------------------------------- Programmers wishing to create their own history-based tools may find the following function useful. (history-data index) [function] Returns three values associated with the history event specified by index: the command, a list of its results, and its numeric index. If index does not label any particular event, each value returned is nil. history-data is used in the HISTORY module to implement the ! reader macro: (set-macro-character #\! #'(lambda (stream char) (values (history-data (read stream t t t)))))) Note that history-data is an external symbol of the Poplog package. --- C.all/lisp/help/history --- Copyright University of Sussex 1988. All rights reserved.