{Begin SubSec Programmer's Assistant Commands} {Title Programmer's Assistant Commands} {Text {note need many examples!!!!} The programmer's assistant recognizes a number of commands, which usually refer to past events on the history list. These commands are treated specially; for example, they may not be put on the history list. Note: If the user defines a function by the same name as a p.a. command, a warning message is printed to remind him that the p.a. command interpretation will take precedence for type-in. {index *PRIMARY* Event specifications} All programmer's assistant commands use the same conventions and syntax for indicating which event or events on the history list the command refers to, even though different commands may be concerned with different aspects of the corresponding event(s), e.g., side-effects, value, input, etc. Therefore, before discussing the various p.a. commands, the following section describes the types of event specifications currently implemented. {Begin SubSec Event Specification} {Title Event Specification} {Text {Tag EventAddress} {index *PRIMARY* Event addresses} An event address identifies one event on the history list. It consists of a sequence of "commands" for moving an imaginary cursor up or down the history list, much in the manner of the arguments to the {breakcom @} break command (see {PageRef BreakCom @}). The event identified is the one "under" the imaginary cursor when there are no more commands. (If any command fails, an error is generated and the history command is aborted.) For example, the event address {lisp 42} refers to the event with event number 42, {lisp 42 FOO} refers to the first event (searching back from event 42) whose input contains the word {lisp FOO}, and {lisp 42 FOO -1} refers to the event preceeding that event. Usually, an event address will contain only one or two commands. Most of the event address commands perform searches for events which satisfy some condition. Unless the {lisp ←} command is given (see below), this search always goes backwards through the history list, from the most recent event specified to the oldest. Note that each search skips the current event. For example, if {lisp FOO} refers to event {arg N}, {lisp FOO FIE} will refer to some event before event {arg N}, even if there is a {lisp FIE} in event {arg N}. {index Event addresses} The event address commands are interpreted as follows: {Begin LabeledList event address commands} {Name {arg N} (an integer)} {Text If {arg N} is the first command in an event address, refers to the event with event number {arg N}.{index event numbers} Otherwise, refers to the event {arg N} events forward (in direction of increasing event number). If {arg N} is negative, it always refers to the event -{arg N} events backwards. For example, {lisp -1} refers to the previous event, {lisp 42} refers to event number 42 (if the first command in an event address), and {lisp 42 3} refers to the event with event number 45. } {Name {lisp ←{arg LITATOM}}} {Text Specifies the last event with an {fn APPLY}-format input whose {it function} matches {arg LITATOM}. Note: There must not be a space between {lisp ←} and {arg LITATOM}. } {Name {lisp ←}} {Text {index ← (in event address)}Specifies that the next search is to go forward instead of backward. If given as the first event address command, the next search begins with last (oldest) event on the history list. } {Name {lisp F}} {Text {index F (in event address)}Specifies that the next object in the event address is to be searched for, regardless of what it is. For example, {lisp F -2} looks for an event containing {lisp -2}. } {Name {lisp =}} {Text {index = (in event address)}Specifies that the next object (presumably a pattern) is to be matched against the {it values} of events, instead of the inputs. } {Name {lisp \}} {Text {index \ (in event address)}Specifies the event last located. {note by a previous event address?? example!} } {Name {lisp SUCHTHAT {arg PRED}}} {Text {index SUCHTHAT (in event address)}Specifies an event for which the function {arg PRED} returns true. {arg PRED} should be a function of two arguments, the input portion of the event, and the event itself. See {PageRef Tag HistoryListFormat} for a discussion of the format of events on the history list. } {Name {arg PAT}} {Text Any other event address command specifies an event whose input contains an expression that matches {arg PAT} as described in {PageRef Tag EditPattern}. The matching is performed by the function {fn HISTORYMATCH} ({PageRef Fn HISTORYMATCH}), which is initially defined to call {fn EDITFINDP} but can be advised or redefined for specialized applications. } {End LabeledList event address commands} Note: Symbols used below of the form {arg EventAddress{sub i}} refer to event addresses, described above. Since an event address may contain multiple words, the event address is parsed by searching for the words which delimit it. For example, in {lisp FROM {arg EventAddress{sub 1}} THRU {arg EventAddress{sub 2}}}, the symbol {arg EventAddress{sub 1}} corresponds to all words between {lisp FROM} and {lisp THRU} in the event specification, and {arg EventAddress{sub 2}} to all words from {lisp THRU} to the end of the event specification. {Begin LabeledList event specifications} {Name {lisp FROM {arg EventAddress{sub 1}} THRU {arg EventAddress{sub 2}}}{index FROM (in event specification)}} {Name {lisp {arg EventAddress{sub 1}} THRU {arg EventAddress{sub 2}}}{index THRU (in event specification)}} {Item Specifies the sequence of events from the event with address {arg EventAddress{sub 1}} through the event with address {arg EventAddress{sub 2}}. For example, {lisp FROM 47 THRU 49} specifies events 47, 48, and 49. {arg EventAddress{sub 1}} can be more recent than {arg EventAddress{sub 2}}. For example, {lisp FROM 49 THRU 47} specifies events 49, 48, and 47 (note reversal of order). } {Name {lisp FROM {arg EventAddress{sub 1}} TO {arg EventAddress{sub 2}}}{index TO (in event specification)}} {Name {lisp {arg EventAddress{sub 1}} TO {arg EventAddress{sub 2}}}} {Item Same as {lisp THRU} but does not include event {arg EventAddress{sub 2}}. } {Name {lisp FROM {arg EventAddress{sub 1}}}} {Item {index FROM (in event specification)}Same as {lisp FROM {arg EventAddress{sub 1}} THRU -1}. For example, if the current event is number 53, then {lisp FROM 49} specifies events 49, 50, 51, and 52. } {Name {lisp THRU {arg EventAddress{sub 2}}}} {Item {index THRU (in event specification)}Same as {lisp FROM -1 THRU {arg EventAddress{sub 2}}}. For example, if the current event is number 53, then {lisp THRU 49} specifies events 52, 51, 50, and 49 (note reversal of order). } {Name {lisp TO {arg EventAddress{sub 2}}}} {Item {index TO (in event specification)}Same as {lisp FROM -1 TO {arg EventAddress{sub 2}}}. } {Name {lisp ALL {arg EventAddress{sub 1}}}} {Item {index ALL (in event specification)}Specifies all events satisfying {lisp {arg EventAddress{sub 1}}}. For example, {lisp ALL LOAD}, {lisp ALL SUCHTHAT FOO}. } {Name empty} {Item If nothing is specified, it is the same as specifying {lisp -1}. Note: In the special case that the last event was an {lisp UNDO}{index UNDO PACom}, it is the same as specifying {lisp -2}. For example, if the user types {lisp (NCONC FOO FIE)}, he can then type {lisp UNDO}, followed by {lisp USE NCONC1}. } {Name {lisp {arg EventSpec{sub 1}} AND {arg EventSpec{sub 2}} AND {ellipsis} AND {arg EventSpec{sub N}}}{index AND (in event specification)}} {Name } {Item Each of the {arg EventSpec{sub i}} is an event specification. The lists of events are concatenated. For example, {lisp FROM 30 THRU 32 AND 35 THRU 37} is the same as {lisp 30 AND 31 AND 32 AND 35 AND 36 AND 37}. } {Name {lisp @ {arg LITATOM}}} {Text If {arg LITATOM} is the name of a command defined via the {pacom NAME} command ({PageRef PACom NAME}), specifies the event(s) defining {arg LITATOM}. } {Name {lisp @@ {arg EventSpec}}} {Item {index *PRIMARY* @@ (in event specification)}{arg EventSpec} is an event specification interpreted as above, but with respect to the archived history list (see the {lisp ARCHIVE} command, {PageRef PAcom ARCHIVE}). } {End LabeledList event specifications} If no events can be found that satisfy the event specification, spelling correction{index spelling correction} on each word in the event specification is performed using {var LISPXFINDSPLST}{index LISPXFINDSPLST Var} as the spelling list.{index spelling lists} For example, {lisp REDO 3 THRUU 6} will work correctly. If the event specification still fails to specify any events after spelling correction, an error is generated. }{End SubSec Event Specification} {Begin SubSec Commands} {Title Commands} {Text All programmer's assistant commands can be input as list forms, or as lines (see {PageRef Fn READLINE}). For example, typing {lisp REDO 5{cr}} and {lisp (REDO 5)} are equivalent. {arg EventSpec} is used to denote an event specification. Unless specified otherwise, omitting {arg EventSpec} is the same as specifying {arg EventSpec}={lisp -1}. For example, {lisp REDO} and {lisp REDO -1} are the same. {index *PRIMARY* REDO PACom} {Def {Type PACom} {Name REDO} {Args EventSpec} {Noparens} {Text Redoes the event or events specified by {arg EventSpec}. For example, {lisp REDO FROM -3} redoes the last three events. }} {Def {Type PACom} {Name REDO} {Args EventSpec N {lisp TIMES}} {Noparens} {Text {index TIMES (use with REDO)}Redoes the event or events specified by {arg EventSpec} {arg N} times. For example, {lisp REDO 10 TIMES} redoes the last event ten times. }} {Def {Type PACom} {Name REDO} {Args EventSpec {lisp WHILE} FORM} {Noparens} {Text {index WHILE (use with REDO)}Redoes the specified events as long as the value of {arg FORM} is true. {arg FORM} is evaluated before each iteration so if its initial value is {lisp NIL}, nothing will happen. }} {Def {Type PACom} {Name REDO} {Args EventSpec {lisp UNTIL} FORM} {Noparens} {Text {index UNTIL (use with REDO)}Same as {lisp REDO {arg EventSpec} WHILE (NOT {arg FORM})}. }} {Def {Type PACom} {Name REPEAT} {Args EventSpec} {Noparens} {Text Same as {lisp REDO {arg EventSpec} WHILE T}. The event(s) are repeated until an error occurs, or the user types control-E or control-D. }} {Def {Type PACom} {Name REPEAT} {Args EventSpec {lisp WHILE} FORM} {Noparens} } {Def {Type PACom} {Name REPEAT} {Args EventSpec {lisp UNTIL} FORM} {Noparens} {Text Same as {lisp REDO}. }} For all history commands that perform multiple repetitions, the variable {var REDOCNT}{index REDOCNT Var} is initialized to 0 and incremented each iteration. If the event terminates gracefully, i.e., is not aborted by an error or control-D, the number of iterations is printed. {Def {Type PACom} {Name RETRY} {Args EventSpec} {Noparens} {Text Similar to {pacom REDO} except sets {index HELPCLOCK Var}{var HELPCLOCK} ({PageRef Var HELPCLOCK}) so that any errors that occur while executing {arg EventSpec} will cause breaks. }} {Def {Type PACom} {Name USE} {Args EXPRS {lisp FOR} ARGS {lisp IN} EventSpec} {Noparens} {Text {index *PRIMARY* USE PACom}{index FOR (in USE command)}{index IN (in USE command)}Substitutes {arg EXPRS} for {arg ARGS} in {arg EventSpec}, and redoes the result. Substitution is done by {index ESUBST FN}{fn ESUBST} ({PageRef Fn ESUBST}), and is carried out as described below. {arg EXPRS} and {arg ARGS} can include non-atomic members. For example, {lisp USE LOG (MINUS X) FOR ANTILOG X IN -2 AND -1} will substitute {lisp LOG} for every occurrence of {lisp ANTILOG} in the previous two events, and substitute {lisp (MINUS X)} for every occurrence of {lisp X}, and reexecute them. Note that these substitutions do not change the information saved about these events on the history list. Any expression to be substituted can be preceded by a {lisp !}{index ! (in PA commands)}, meaning that the expression is to be substituted as a {it segment}, e.g., {lisp LIST(A B C)} followed by {lisp USE ! (X Y Z) FOR B} will produce {lisp LIST(A X Y Z C)}, and {lisp USE ! NIL FOR B} will produce {lisp LIST(A C)}. If {lisp IN {arg EventSpec}} is omitted, the first member of {arg ARGS} is used for {arg EventSpec}. For example, {lisp USE PUTD FOR @UTD} is equivalent to {lisp USE PUTD FOR @UTD IN F @UTD}. The {lisp F} is inserted to handle correctly the case where the first member of {arg ARGS} could be interpreted as an event address command. }} {Def {Type PACom} {Name USE} {Args EXPRS {lisp IN} EventSpec} {Noparens} {Text {index IN (in USE command)}If {arg ARGS} are omitted, and the event referred to was itself a {pacom USE} command, the arguments and expression substituted into are the same as for the indicated {pacom USE} command. In effect, this {pacom USE} command is thus a continuation of the previous {index USE PACom}{pacom USE} command. For example, following {lisp USE X FOR Y IN 50}, typing {lisp USE Z IN -1} is equivalent to {lisp USE Z FOR Y IN 50}. If {arg ARGS} are omitted and the event referred to was {it not} a {pacom USE} command, substitution is for the "operator" in that command. For example {lisp ARGLIST(FF)} followed by {lisp USE CALLS IN -1} is equivalent to {lisp USE CALLS FOR ARGLIST IN -1}. If {lisp IN {arg EventSpec}} is omitted, it is the same as specifying {lisp IN -1}. }} {Def {Type PACom} {Name USE} {Args EXPRS{sub 1} {lisp FOR} ARGS{sub 1} {lisp AND} {ellipsis} {lisp AND} EXPRS{sub N} {lisp FOR} ARGS{sub N} {lisp IN} EventSpec} {Noparens} {Text {index AND (in USE command)}More general form of {lisp USE} command. See description of the substitution algorithm below. Note: The {pacom USE} command is parsed by a small finite state parser to distinguish the expressions and arguments. For example, {lisp USE FOR FOR AND AND AND FOR FOR} will be parsed correctly. }} Every {pacom USE} command involves three pieces of information: the expressions to be substituted, the arguments to be substituted for, and an event specification, which defines the input expression in which the substitution takes place. If the {pacom USE} command has the same number of expressions as arguments, the substitution procedure is straightforward. For example, {lisp USE X Y FOR U V} means substitute {lisp X} for {lisp U} and {lisp Y} for {lisp V}, and is equivalent to {lisp USE X FOR U AND Y FOR V}. However, the {pacom USE} command also permits distributive substitutions, for substituting several expressions for the same argument. For example, {lisp USE A B C FOR X} means first substitute {lisp A} for {lisp X} then substitute {lisp B} for {lisp X} (in a new copy of the expression), then substitute {lisp C} for {lisp X}. The effect is the same as three separate {pacom USE}{index *PRIMARY* USE PACom} commands. Similarly, {lisp USE A B C FOR D AND X Y Z FOR W} is equivalent to {lisp USE A FOR D AND X FOR W}, followed by {lisp USE B FOR D AND Y FOR W}, followed by {lisp USE C FOR D AND Z FOR W}. {lisp USE A B C FOR D AND X FOR Y} also corresponds to three substitions, the first with {lisp A} for {lisp D} and {lisp X} for {lisp Y}, the second with {lisp B} for {lisp D}, and {lisp X} for {lisp Y}, and the third with {lisp C} for {lisp D}, and again {lisp X} for {lisp Y}. However, {lisp USE A B C FOR D AND X Y FOR Z} is ambiguous and will cause an error. Essentially, the {pacom USE} command operates by proceeding from left to right handling each "{lisp AND}" separately. Whenever the number of expressions exceeds the number of expressions available, multiple {pacom USE} expressions are generated. Thus {lisp USE A B C D FOR E F} means substitute {lisp A} for {lisp E} at the same time as substituting {lisp B} for {lisp F}, then in another copy of the indicated expression, substitute {lisp C} for {lisp E} and {lisp D} for {lisp F}. Note that this is also equivalent to {lisp USE A C FOR E AND B D FOR F}. Note: Parsing the {lisp USE} command gets more complicated when one of the arguments and one of the expressions are the same, e.g., {lisp USE X Y FOR Y X}, or {lisp USE X FOR Y AND Y FOR X}. This situation is noticed when parsing the command, and handled correctly. {Def {Type PACom} {Name ...} {Args VARS} {Noparens} {Text Similar to {pacom USE} except substitutes for the (first) {it operand}. For example, {lisp EXPRP(FOO)} followed by {lisp ... FIE FUM} is equivalent to {lisp USE FIE FUM FOR FOO}. }} {index *PRIMARY* $ (escape) PACom} {index *PRIMARY* Escape ($) PACom} Note: In the following discussion, {lisp $} is used to represent the character "escape," since this is how this character is echoed. {Def {Type PACom} {Name $} {Args X {lisp FOR} Y {lisp IN} EventSpec} {Noparens} {Text {pacom $} (escape) is a special form of the {pacom USE} command for conveniently specifying {it character} substitutions in litatoms or strings. In addition, it has a number of useful properties in connection with events that involve errors (see below). Equivalent to {lisp USE ${arg X}$ FOR ${arg Y}$ IN {arg EventSpec}}, which will do a character substitution of the characters in {arg X} for the characters in {arg Y}. For example, if the user types {lisp MOVD(FOO FOOSAVE T)}, he can then type {lisp $ FIE FOR FOO IN MOVD} to perform {lisp MOVD(FIE FIESAVE T)}. Note that {lisp USE FIE FOR FOO} would perform {lisp MOVD(FIE FOOSAVE T)}. }} {Def {Type PACom} {Name $} {Args Y X {lisp IN} EventSpec} {Noparens} } {Def {Type PACom} {Name $} {Args Y {lisp TO} X {lisp IN} EventSpec} {Noparens} } {Def {Type PACom} {Name $} {Args Y {lisp =} X {lisp IN} EventSpec} {Noparens} } {Def {Type PACom} {Name $} {Args Y {lisp ->} X {lisp IN} EventSpec} {Noparens} {Text Abbreviated forms of the {pacom $} (escape) command: the same as {lisp $ {arg X} FOR {arg Y} IN {arg EventSpec}}, which changes {arg Y}s to {arg X}s. }} {pacom $} does event location the same as the {pacom USE} command, i.e., if {lisp IN {arg EventSpec}} is not specified, {pacom $} searches for {arg Y}. However, unlike {pacom USE}, {pacom $} can only be used to specify one substitution at a time. After {pacom $} finds the event, it looks to see if an error was involved in that event, and if the indicated character substitution can be performed in the object of the error message, called the offender. If so, {pacom $} assumes the substitution refers to the offender, performs the indicated character substitution in the offender only, and then substitutes the result for the original offender throughout the event. For example, suppose the user types {lisp (PRETTYDEF FOOFNS 'FOO FOOOVARS)} causing a {lisp U.B.A. FOOOVARS} error message. The user can now type {lisp $ OO O}, which will change {lisp FOOOVARS} to {lisp FOOVARS}, but {it not} change {lisp FOOFNS} or {lisp FOO}. If an error did occur in the specified event, the user can also omit specifying the object of the substitution, {arg Y}, in which case the offender itself is used. Thus, the user could have corrected the above example by simply typing {lisp $ FOOVARS}. Since {fn ESUBST} is used for performing the substitution (see {PageRef Fn ESUBST}), {pacom $} can be used in {arg X} to refer to the characters in {arg Y}. For example, if the user types {lisp LOAD(PRSTRUC PROP)}, causing the error {lisp FILE NOT FOUND PRSTRUC}, he can request the file to be loaded from {lisp LISP}'s directory by simply typing {lisp $ <LISP>$}. This is equivalent to performing {lisp (R PRSTRUC <LISP>$)} on the event, and therefore replaces {lisp PRSTRUC} by {lisp <LISP>PRSTRUC}. Note that {pacom $} never {it searches} for an error. Thus, if the user types {lisp LOAD(PRSTRUC PROP)} causing a {lisp FILE NOT FOUND} error, types {lisp CLOSEALL()}, and {it then} types {lisp $ <LISP>$}, {fn LISPX} will complain that there is no error in {lisp CLOSEALL()}. In this case, the user would have to type {lisp $ <LISP>$ IN LOAD}, or {lisp $ PRS <LISP>PRS} (which would cause a search for {lisp PRS}). Note also that {pacom $} operates on {it input}, not on programs. If the user types {lisp FOO()}, and within the call to {lisp FOO} gets a {lisp U.D.F. CONDD} error, he {it cannot} repair this by {lisp $ COND}. {fn LISPX} will type {lisp CONDD NOT FOUND IN FOO()}. {Def {Type PACom} {Name FIX} {Args EventSpec} {Noparens} {Text Envokes the default program editor (Dedit or the teletype editor) on a copy of the input(s) for {arg EventSpec}. Whenever the user exits via {editcom OK}, the result is unread and reexecuted exactly as with {pacom REDO}. }} {pacom FIX} is provided for those cases when the modifications to the input(s) are not simple substitutions of the type that can be specified by {pacom USE}. For example, if the default editor is the teletype editor, then: {lispcode ←(DEFINEQ FOO (LAMBDA (X) (FIXSPELL SPELLINGS2 X 70] INCORRECT DEFINING FORM FOO ←FIX EDIT *P (DEFINEQ FOO (LAMBDA & &)) *(LI 2) *P (DEFINEQ (FOO &)) *OK (FOO) ←} The user can also specify the edit command(s) to {index LISPX FN}{fn LISPX}, by typing {lisp -} followed by the command(s) after the event specification, e.g., {lisp FIX - (LI 2)}. In this case, the editor will not type {lisp EDIT}, or wait for an {lisp OK} after executing the commands. Note: {pacom FIX} calls the editor on the "input sequence" of an event, adjusting the editor so it is initially editing the expression typed. However, the entire input sequence is being edited, so it is possible to give editor commands that examine this structure further. For more information on the format of an event's input, see {PageRef Tag HistoryListFormat}. {Def {Type PACom} {Name ??} {Args EventSpec} {Noparens} {Text Prints the specified events from the history list. If {arg EventSpec} is omitted, {pacom ??} prints the entire history list, beginning with most recent events. Otherwise {pacom ??} prints only those events specified in {arg EventSpec} (in the order specified). For example, {lisp ?? -1}, {lisp ?? 10 THRU 15}, etc. For each event specified, {pacom ??} prints the event number, the prompt, the input line(s), and the value(s). If the event input was a p.a. command that "unread" some other input lines, the p.a. command is printed without a preceding prompt, to show that they are not stored as the input, and the input lines are printed with prompts. Events are initially stored on the history list with their value field equal to the character "bell" (control-G){index bell (in history event)}{index control-G (in history list)}. Thefore, if an operation fails to complete for any reason, e.g., causes an error, is aborted, etc., {pacom ??} will print a bell as its "value". {pacom ??} commands are not entered on the history list, and so do not affect relative {index event numbers}event numbers. In other words, an event specification of {lisp -1} typed following a {pacom ??} command will refer to the event immediately preceding the {pacom ??} command. {pacom ??} is implemented via the function {fn PRINTHISTORY},{index PRINTHISTORY FN} {PageRef Fn PRINTHISTORY}, which can also be called directly by the user. Printing is performed via the function {fn SHOWPRIN2}{index SHOWPRIN2 FN} ({PageRef Fn SHOWPRIN2}), so that if the value of {var SYSPRETTYFLG}={lisp T},{index SYSPRETTYFLG Var} events will be prettyprinted. }} {Def {Type PACom} {Name UNDO} {Args EventSpec} {Noparens} {Text {index *PRIMARY* UNDO PACom}Undoes the side effects of the specified events. For each event undone, {pacom UNDO} prints a message: {lisp RPLACA undone}, {lisp REDO undone} etc.{index undone (Printed by System)} If nothing is undone because nothing was saved, {pacom UNDO} types {lisp nothing saved}.{index nothing saved (Printed by System)} If nothing was undone because the event(s) were already undone, {pacom UNDO} types {lisp already undone}.{index *PRIMARY* already undone (Printed by System)} If {arg EventSpec} is not given, {pacom UNDO} searches back for the last event that contained side effects, was not undone, and itself was not an {pacom UNDO} command. Note that the user can undo {pacom UNDO} commands themselves by specifying the corresponding event address, e.g., {lisp UNDO -7} or {lisp UNDO UNDO}. }} In order to restore all pointers correctly, the user should {lisp UNDO} events in the reverse order from which they were executed. For example, to undo all the side effects of the last five events, perform {lisp UNDO THRU -5}, {it not} {lisp UNDO FROM -5}.{index undoing out of order} Undoing out of order may have unforseen effects if the operations are {it dependent}. For example, if the user performed {lisp (NCONC1 FOO FIE)}, followed by {lisp (NCONC1 FOO FUM)}, and then undoes the {lisp (NCONC1 FOO FIE)}, he will also have undone the {lisp (NCONC1 FOO FUM)}. If he then undoes the {lisp (NCONC1 FOO FUM)}, he will cause the {lisp FIE} to reappear, by virtue of restoring {lisp FOO} to its state before the execution of {lisp (NCONC1 FOO FUM)}. For more details, see {PageRef Tag UndoingOutOfOrder}. {Tag UndoingDWIM} {index *PRIMARY* Undoing DWIM corrections} {Def {Type PACom} {Name UNDO} {Args EventSpec {lisp :} X{sub 1} {ellipsis} X{sub N}} {Noparens} {Text Each {arg X{sub i}} is a pattern that is matched to a message printed by DWIM in the event(s) specified by {arg EventSpec}. The side effects of the corresponding DWIM corrections, and only those side effects, are undone. For example, if DWIM printed the message {lisp PRINTT [IN FOO] -> PRINT}, then {lisp UNDO : PRINTT} or {lisp UNDO : PRINT} would undo the correction. Some portions of the messages printed by DWIM are strings, e.g., the message {lisp FOO UNSAVED} is printed by printing {lisp FOO} and then {lisp " UNSAVED"}. Therefore, if the user types {lisp UNDO : UNSAVED}, the DWIM correction will not be found. He should instead type {lisp UNDO : FOO} or {lisp UNDO : $UNSAVED$} (<esc>{lisp UNSAVED}<esc>, see R command in editor, {PageRef EditCom R}). }} {note DWIM pacom flushed} {Def {Type PACom} {Name NAME} {Args LITATOM EventSpec} {Noparens} {Text {index *PRIMARY* NAME PACom}Saves the event(s) (including side effects) specified by {arg EventSpec} on the property list of {arg LITATOM} (under the property {index HISTORY Prop}{prop HISTORY}). For example, {lisp NAME FOO 10 THRU 15}. {lisp NAME} commands are undoable. Events saved on a litatom can be retrieved with the event specification {lisp @ {arg LITATOM}}. For example, {lisp ?? @ FOO}, {lisp REDO @ FOO}, etc. Commands defined by {pacom NAME} can also be typed in directly as though they were built-in commands, e.g., {lisp FOO{CRsymbol}} is equivalent to {lisp REDO @ FOO}. However, if {lisp FOO} is the name of a variable, it would be evaluated, i.e., {lisp FOO{CRsymbol}} would return the value of {lisp FOO}. }} Commands defined by {pacom NAME} can also be defined to take arguments: {Def {Type PACom} {Name NAME} {Args LITATOM {lisp (}ARG{sub 1} {ellipsis} ARG{sub N}{lisp ) :} EventSpec} {Noparens} } {Def {Type PACom} {Name NAME} {Args LITATOM ARG{sub 1} {ellipsis} ARG{sub N} {lisp :} EventSpec} {Noparens} {Text The arguments {arg ARG{sub i}} are interpreted the same as the arguments for a {pacom USE} command. When {arg LITATOM} is invoked, the argument values are substituted for {arg ARG{sub 1}} {ellipsis} {arg ARG{sub N}} using the same substitution algorithm as for {pacom USE}. {lisp NAME FOO {arg EventSpec}} is equivalent to {lisp NAME FOO : {arg EventSpec}}. In either case, if {lisp FOO} is invoked {it with} arguments, an error is generated. }} For example, following the event {lisp (PUTD 'FOO (COPY (GETPROP 'FIE 'EXPR)))}, the user types {lisp NAME MOVE FOO FIE : PUTD}. Then typing {lisp MOVE TEST1 TEST2} would cause {lisp (PUTD 'TEST1 (COPY (GETPROP 'TEST2 'EXPR)))} to be executed, i.e., would be equivalent to typing {lisp USE TEST1 TEST2 FOR FOO FIE IN MOVE}. Typing {lisp MOVE A B C D} would cause two {lisp PUTD}'s to be executed. Note that {lisp !}'s and {lisp $}'s can also be employed the same as with {pacom USE}. For example, if following {lispcode ←PREPINDEX(<MANUAL>14LISP.XGP) ←FIXFILE(<MANUAL>14LISP.XGPIDX)} the user performed {lisp NAME FOO $14$ : -2 AND -1}, then {lisp FOO $15$} would perform the indicated two operations with {lisp 14} replaced by {lisp 15}. {Def {Type PACom} {Name RETRIEVE} {Args LITATOM} {Noparens} {Text Retrieves and reenters on the history list the events named by {arg LITATOM}. Causes an error if {arg LITATOM} was not named by a {pacom NAME} command. }} For example, if the user performs {lisp NAME FOO 10 THRU 15}, and at some time later types {lisp RETRIEVE FOO}, 6 {it new} events will be recorded on the history list (whether or not the corresponding events have been forgotten yet). Note that {pacom RETRIEVE} does {it not} reexecute the events, it simply retrieves them. The user can then {pacom REDO}, {pacom UNDO}, {pacom FIX}, etc. any or all of these events. Note that the user can combine the effects of a {pacom RETRIEVE} and a subsequent history command in a single operation, e.g., {lisp REDO FOO} is equivalent to {lisp RETRIEVE FOO}, followed by an appropriate {pacom REDO}. Actually, {lisp REDO FOO} is better than {pacom RETRIEVE} followed by {pacom REDO} since in the latter case, the corresponding events would be entered on the history list {it twice}, once for the {pacom RETRIEVE} and once for the {pacom REDO}. Note that {lisp UNDO FOO} and {lisp ?? FOO} are permitted. {Def {Type PACom} {Name BEFORE} {Args LITATOM} {Noparens} {Text Undoes the effects of the events named by {arg LITATOM}. }} {Def {Type PACom} {Name AFTER} {Args LITATOM} {Noparens} {Text Undoes a {lisp BEFORE {arg LITATOM}}. }} {pacom BEFORE} and {pacom AFTER} provide a convenient way of flipping back and forth between two states, namely the state {it before} a specified event or events were executed, and that state {it after} execution. For example, if the user has a complex data structure which he wants to be able to interrogate before and after certain modifications, he can execute the modifications, name the corresponding events with the {index NAME PACom}{pacom NAME} command, and then can turn these modifications off and on via {pacom BEFORE} or {pacom AFTER} commands. Both {pacom BEFORE} and {pacom AFTER} are no-ops if the {arg LITATOM} was already in the corresponding state; both generate errors if {arg LITATOM} was not named by a {pacom NAME} command. The alternative to {pacom BEFORE} and {pacom AFTER} for repeated switching back and forth involves typing {pacom UNDO}, {pacom UNDO} of the {pacom UNDO}, {pacom UNDO} of that etc. At each stage, the user would have to locate the correct event to undo, and furthermore would run the risk of that event being "forgotten" if he did not switch at least once per time-slice. Note: Since {pacom UNDO}, {pacom NAME}, {pacom RETRIEVE}, {pacom BEFORE}, and {pacom AFTER} are recorded as inputs they can be referenced by {pacom REDO}, {pacom USE}, etc. in the normal way. However, the user must again remember that the context in which the command is reexecuted is different than the original context. For example, if the user types {lisp NAME FOO DEFINEQ THRU COMPILE}, then types {lisp ... FIE}, the input that will be reread will be {lisp NAME FIE DEFINEQ THRU COMPILE} as was intended, but both {lisp DEFINEQ} and {lisp COMPILE}, will refer to the most recent event containing those atoms, namely the event consisting of {lisp NAME FOO DEFINEQ THRU COMPILE}. {Def {Type PACom} {Name ARCHIVE} {Args EventSpec} {Noparens} {Text Records the events specified by {arg EventSpec} on a permanent "archived" history list, {index ARCHIVELST Var}{var ARCHIVELST} ({PageRef Var ARCHIVELST}). This history list can be referenced by preceding a standard event specification with {index @@ (in event specification)}{lisp @@} (see {PageRef (in event specification) @@}). For example, {lisp ?? @@} prints the archived history list, {lisp REDO @@ -1} will recover the corresponding event from the archived history list and redo it, etc. The user can also provide for automatic archiving of selected events by appropriately defining {index ARCHIVEFN Var}{var ARCHIVEFN} ({PageRef Var ARCHIVEFN}), or by putting the history list property {index *ARCHIVE* (History list property)}{prop *ARCHIVE*}, with value {lisp T}, on the event ({PageRef (History list property) *ARCHIVE*}). Events that are referenced by history commands are automatically marked for archiving in this fashion. }} {Def {Type PACom} {Name FORGET} {Args EventSpec} {Noparens} {Text Permanently erases the record of the side effects for the events specified by {arg EventSpec}. If {arg EventSpec} is omitted, forgets side effects for entire history list. {pacom FORGET} is provided for users with space problems. For example, if the user has just performed {fn SET}s, {fn RPLACA}s, {fn RPLACD}s, {fn PUTD}, {fn REMPROP}s, etc. to release storage, the old pointers would not be garbage collected until the corresponding events age sufficiently to drop off the end of the history list and be forgotten. {pacom FORGET} can be used to force immediate forgetting (of the side-effects only). {pacom FORGET} is not undoable (obviously). }} {Def {Type PACom} {Name REMEMBER} {Args EventSpec} {Noparens} {Text Instructs the file package to "remember" the events specified by {arg EventSpec}. These events will be marked as changed objects of file package type {lisp EXPRESSIONS},{index EXPRESSIONS (File Package Type)} which can be written out via the file package command {filecom P}. For example, after the user types: {lispcode ←MOVD?(DELFILE /DELFILE) DELFILE ←REMEMBER -1 (MOVD? (QUOTE DELFILE) (QUOTE /DELFILE)) ←} If the user calls {fn FILES?}, {fn MAKEFILES}, or {fn CLEANUP}, the command {lisp (P (MOVD? (QUOTE DELFILE) (QUOTE /DELFILE)))} will be constructed by the file package and added to the filecoms indicated by the user, unless the user has already explicitly added the corresponding expression to some {filecom P} command himself. Note that "remembering" an event like {lisp (PUTPROP 'FOO 'CLISPTYPE {arg EXPRESSION})} will {it not} result in a {lisp (PROP CLISPTYPE FOO)} command, because this will save the current (at the time of the {fn MAKEFILE}) value for the {prop CLISPTYPE} property, which may or may not be {arg EXPRESSION}. Thus, even if there is a {filecom PROP} command which saves the {prop CLISPTYPE} property for {lisp FOO} in some {lisp {arg FILE}COMS}, remembering this event will still require a {lisp (P (PUTPROP 'FOO 'CLISPTYPE {arg EXPRESSION}))} command to appear. }} {Def {Type PACom} {Name PL} {Args LITATOM} {Noparens} {Text "Print Property List." Prints out the property list of {arg LITATOM} in a nice format, with {fn PRINTLEVEL} reset to {lisp (2 . 3)}. For example, {lispcode ←PL + CLISPTYPE: 12 ACCESSFNS: (PLUS IPLUS FPLUS)} {pacom PL} is implemented via the function {fn PRINTPROPS}.{index PRINTPROPS FN} {note this is the only reference in old manual to PRINTPROPS. flush??} }} {Def {Type PACom} {Name PB} {Args LITATOM} {Noparens} {Text "Print Bindings." Prints the value of {arg LITATOM} with {fn PRINTLEVEL} reset to {lisp (2 . 3)}. If {arg LITATOM} is not bound, does not attempt spelling correction or generate an error. {pacom PB} is implemented via the function {fn PRINTBINDINGS}{index PRINTBINDINGS FN}. {pacom PB} is also a break command ({PageRef BreakCom PB}). As a break command, it ascends the stack and, for each frame in which {arg LITATOM} is bound, prints the frame name and value of {arg LITATOM}. If typed in to the programmer's assistant when not at the top level, e.g. in the editor, etc., {pacom PB} will also ascend the stack as it does with a break. However, as a programmer's assistant command, it is primarily used to examine the top level value of a variable that may or may not be bound, or to examine a variable whose value is a large list. }} {Def {Type PACom} {Name ;} {Args FORM} {Noparens} {Text Allows the user to type a line of text without having the programmer's assistant process it. Useful when linked to other users, or to annotate a dribble file ({PageRef Term Dribble Files}). }} {Def {Type PACom} {Name SHH} {Args FORM} {Noparens} {Text Allows the user to evaluate an expression without having the programmer's assistant process it or record it on a history list. Useful when one wants to bypass a programmer's assistant command or to keep the evaluation off the history list. }} {Def {Type PACom} {Name TYPE-AHEAD} {Text A command that allows the user to type-ahead an indefinite number of inputs. }} {indexx {Name Escape-GO} {Type TYPE-AHEAD command} {Info *PRIMARY*} {Text Escape-GO ({lisp $GO})} } {indexx {Name $GO} {Type TYPE-AHEAD command} {Info *PRIMARY*} {Text {lisp $GO} (escape-GO)} } {indexx {Name GO} {Type TYPE-AHEAD command} {Text {lisp $GO} (escape-GO)} } {indexx {Name Escape-Q} {Type TYPE-AHEAD command} {Info *PRIMARY*} {Text Escape-Q ({lisp $Q})} } {indexx {Name $Q} {Type TYPE-AHEAD command} {Info *PRIMARY*} {Text {lisp $Q} (escape-Q)} } {indexx {Name Q} {Type TYPE-AHEAD command} {Text {lisp $Q} (escape-Q)} } {indexx {Name Escape-STOP} {Type TYPE-AHEAD command} {Info *PRIMARY*} {Text Escape-STOP ({lisp $STOP})} } {indexx {Name $STOP} {Type TYPE-AHEAD command} {Info *PRIMARY*} {Text {lisp $STOP} (escape-STOP)} } {indexx {Name STOP} {Type TYPE-AHEAD command} {Text {lisp $STOP} (escape-STOP)} } The assistant responds to {pacom TYPE-AHEAD} with a prompt character of {lisp >}. The user can now type in an indefinite number of lines of input, under {fn ERRORSET} protection. The input lines are saved and unread when the user exits the type-ahead loop with the command {lisp $GO} (escape-{lisp GO}). While in the type-ahead loop, {lisp ??} can be used to print the type-ahead, {lisp FIX} to edit the type-ahead, and {lisp $Q} (escape-{lisp Q}) to erase the last input (may be used repeatedly). The {pacom TYPE-AHEAD}{index TYPE-AHEAD PACom} command may be aborted by {lisp $STOP} (escape-{lisp STOP}); control-E{index Control-E (Interrupt Character)} simply aborts the current line of input. For example: {lispcode ←TYPE-AHEAD >SYSOUT(TEM) >MAKEFILE(EDIT) >BRECOMPILE((EDIT WEDIT)) >F >$Q \\F >$Q \\BRECOMPILE >LOAD(WEDIT PROP) >BRECOMPILE((EDIT WEDIT)) >F >MAKEFILE(BREAK) >LISTFILES(EDIT BREAK) >SYSOUT(CURRENT) >LOGOUT] >?? >SYSOUT(TEM) >MAKEFILE(EDIT) >LOAD(WEDIT PROP) >BRECOMPILE((EDIT WEDIT)) >F >MAKEFILE(BREAK) >LISTFILES(EDIT BREAK) >SYSOUT(CURRENT) >LOGOUT] >FIX EDIT *(R BRECOMPILE BCOMPL) *P ((LOGOUT) (SYSOUT &) (LISTFILES &) (MAKEFILE &) (F) (BCOMPL &) (LOAD &) (MAKEFILE &) (SYSOUT &)) *(DELETE LOAD) *OK >$GO} Note that type-ahead can be addressed to the compiler, since it uses {fn LISPXREAD}{index LISPXREAD FN} for input. Type-ahead can also be directed to the editor, but type-ahead to the editor and to {index LISPX FN}{fn LISPX} cannot be intermixed. {note $BUFS pacom flushed} The following are some useful functions and variables: {FnDef {FnName VALUEOF} {FnArgs LINE} {Type NOSPREAD NLAMBDA} {Text An nlambda function for obtaining the value of a particular event, e.g., {lisp (VALUEOF -1)}, {lisp (VALUEOF ←FOO -2)}. The value of an event consisting of several operations is a list of the values for each of the individual operations. {index *PRIMARY* Bell (in history event)} {index *PRIMARY* Control-G (in history list)} Note: The value field of a history entry is initialized to bell (control-G). Thus a value of bell indicates that the corresponding operation did not complete, i.e., was aborted or caused an error (or else it returned bell). Note: Although the input for {index VALUEOF FN}{fn VALUEOF} is entered on the history list before {fn VALUEOF} is called, {lisp (VALUEOF -1)} still refers to the value of the expression immediately before the {fn VALUEOF} input, because {fn VALUEOF} effectively backs the history list up one entry when it retrieves the specified event. Similarly, {lisp (VALUEOF FOO)} will find the first event before this one that contains a {lisp FOO}. }} {VarDef {Name IT} {Text The value of the variable {var IT} is always the value of the last event executed, i.e. {lisp (VALUEOF -1)}. For example, {lispcode ←(SQRT 2) 1.414214 ←(SQRT IT) 1.189207} If the last event was a multiple event, e.g. {lisp REDO -3 THRU -1}, {var IT} is set to value of the last of these events. Following a {pacom ??} command, {var IT} is set to value of the last event printed. In other words, in all cases, {var IT} is set to the last value printed on the terminal. }} }{End SubSec Commands} {Begin SubSec P.A. Commands Applied to P.A. Commands} {Title P.A. Commands Applied to P.A. Commands} {Text {index *PRIMARY* Programmer's assistant commands applied to P.A. commands} Programmer's assistant commands that unread expressions, such as {pacom REDO}, {pacom USE}, etc. do not appear in the input portion of events, although they are stored elsewhere in the event. They do not interfere with or affect the searching operations of event specifications. As a result, p.a. commands themselves cannot be recovered for execution in the normal way. For example, if the user types {lisp USE A B C FOR D} and follows this with {lisp USE E FOR D}, he will not produce the effect of {lisp USE A B C FOR {lisp E}}, but instead will simply cause {lisp E} to be substituted for {lisp D} in the last event containing a {lisp D}. To produce the desired effect, the user should type {lisp USE D FOR E IN USE}. The appearance of the word {lisp REDO}, {lisp USE} or {lisp FIX} in an event address specifies a search for the corresponding programmer's assistant command. It also specifies that the text of the programmer's assistant command itself be treated as though it were the input. However, the user must remember that the {it context} in which a history command is reexecuted is that of the current history, not the original context. For example, if the user types {lisp USE FOO FOR FIE IN -1}, and then later types {lisp REDO USE}, the {lisp -1} will refer to the event before the {lisp REDO}, not before the {lisp USE}. {index *PRIMARY* Programmer's assistant commands that fail} The one exception to the statement that programmer's assistant commands "do not interfere with or affect the searching operations of event specifications" occurs when a p.a. command fails to produce any input. For example, suppose the user types {lisp USE LOG FOR ANTILOG AND ANTILOG FOR LOGG}, mispelling the second {lisp LOG}. This will cause an error, {lisp LOGG ?}. Since the {pacom USE} command did not produce any input, the user can repair it by typing {lisp USE LOG FOR LOGG}, without having to specify {lisp IN USE}. This latter {pacom USE} command will invoke a search for {lisp LOGG}, which {it will} find the bad {lisp USE} command. The programmer's assistant then performs the indicated substitution, and unreads {lisp USE LOG FOR ANTILOG AND ANTILOG FOR LOG}. In turn, this {pacom USE} command invokes a search for {lisp ANTILOG}, which, because it was not typed in but reread, ignores the bad {pacom USE} command which was found by the earlier search for {lisp LOGG}, and which is still on the history list. In other words, p.a. commands that fail to produce input are visible to searches arising from event specifications{index Event specifications} typed in by the user, but not to secondary event specifications. In addition, if the most recent event is a history command which failed to produce input, a secondary event specification will effectively back up the history list one event so that relative event numbers for that event specification{index Event specifications} will not count the bad p.a. command. For example, suppose the user types {lisp USE LOG FOR ANTILOG AND ANTILOG FOR LOGG IN -2 AND -1}, and after the p.a. types {lisp LOGG ?}, the user types {lisp USE LOG FOR LOGG}. He thus causes the command {lisp USE LOG FOR ANTILOG AND ANTILOG FOR LOG IN -2 AND -1} to be constructed and unread. In the normal case, {lisp -1} would refer to the last event, i.e., the "bad" {pacom USE} command, and {lisp -2} to the event before it. However, in this case, {lisp -1} refers to the event before the bad {pacom USE} command, and the {lisp -2} to the event before that. In short, the caveat above that "the user must remember that the context in which a history command is reexecuted is that of the current history, not the original context" does not apply if the correction is performed immediately. {note this explanation is too hairy. I wonder whether real people ever even use this feature.} }{End SubSec P.A. Commands Applied to P.A. Commands} }{End SubSec Programmer's Assistant Commands}