Facilities within the Command Interpreter
*****************************************

This is a guide to the use of SM variables, the macro processor, the help command, and the history facilities. The vector arithmetic and plotting facilities are described below.  Various examples are scattered throughout the text, to give some guidance on the use of SM's capabilities.

Perhaps the most important thing to know is how to escape from SM. If you have a prompt, simply type QUIT (or q which is a macro defined as DELETE HISTORY QUIT. This will exit SM just the same, but the quit won't appear on your history list, waiting to be playedback accidently. Actually, q will query you before quitting). If you are running some command, try C to get a prompt. Most commands will eventually return control to the keyboard following a C. In addition, the parser is reset, and the input buffer cleared. Sometimes C leaves a } on the buffer if it thinks that it'll help get back to the prompt, which can generate an irrelevant syntax error. Occasionally it can still be confused -- try typing a few characters and maybe a }.

When you have interrupted SM with a C, a macro called error_handler is executed, if it is defined. The one that we provide does things like setting the expansion back to 1, and resetting any window commands that you might have issued, and then prints a message handler... to tell you that it's done its work. If you don't like this, see `private initialisation' in the index for how to get your own handler loaded automatically.

If you make a mistake, and SM notices a syntax error, it'll print a message indicating where you were and which macro you were running. It is possible for the wrong macro to be reported (if SM has finished reading the macro before detecting the error), in which case you'll be told that the error occurred in a macro that called the offender. Setting VERBOSE (see Verbose) to 3 or 4 provides a more direct way of finding the true location of the error.

If you define the variable traceback to be 1 (maybe with the line traceback 1 in your .sm file) you'll get a traceback of what macros were active when the error occurred; the same caveats about the wrong macro being reported apply. In addition, the usual interrupt capabilities of your operating system will work under SM, with a couple of quirks.

Under Unix, in case of emergency, type \, and SM will ask you if you want to return to the prompt, and if you don't it'll offer a core dump, and then exit. As usual, typing Z (from the C-shell) will interrupt the process, which may be restarted later. Under VMS, Z will interrupt SM, and return you to the command interpreter (DCL). Typing CONTINUE will then allow you to restart SM (If you are using VMS, you may prefer to use Y as your interrupt character. A suitable set of key definitions is in a file called maps_vms.dat in the top SM directory. It may be read with the READ EDIT command (see Key Bindings), and this may be done automatically in your startup macro by the variable edit in your .sm file.).

If SM is running in a SPAWNed sub-process, then Z will reATTACH you to its parent. To continue SM, use the DCL ATTACH command. We strongly suggest that you learn how to do this, it makes life much easier -- all you have to do is SPAWN a process from DCL and start SM from there.  Do check with your VMS system manager to ensure that you have the right quotas for SPAWNing (Process limit must be at least 3, because SM will use one for itself and one for hardcopies). An especially simple way to do all this is is to use the command file kept_SM.com in the main SM directory. It'll handle the spawning and attaching for you.

Another fact to bear in mind is that the characters ^, $, and # are special, as ^ is used by the history system, $ introduces a variable, and # starts a comment.  The special meanings of all of these characters except ^ can be turned off by preceding them with a \. To type a ^, use the quote_next character (initially Q or ESC-q) to quote the ^; i.e. type ESC-q. (In fact you can rebind any character to replace ^, see History Editor) A \n is interpreted as a carriage return, and a \ as the last character on a line escapes the newline, so that the line and the one following it are treated as one long line. A \ preceding any other character (except a "; see next paragraph) is simply a \.  This character is used to set font types in the LABEL commands, so it has no special meaning to the command interpreter, which simplifies the entering of strings for LABEL commands.

A further problem is that symbols such as +, -, *, and / are used to separate words, which is what you want for mathematics, but maybe not what you had in mind for filenames. Enclosing a word in double quotes turns off all special meanings except ^; an embedded " may be escaped with a \. Single quotes are used quite differently; enclosing a word in 'single quotes' makes it into a string so '12' is a two-character string and not an integer at all. There are times when this is important; for example if(y == 'yes') tests if the vector y is equal to the string `yes', whereas if('yes' == 'yes') asks whether two identical strings are equal (they are). When you remember that I can legally say set yes='no' you'll appreciate the distinction.

The characters {} also perform quoting, turning off the special meanings of all characters (including single and double quotes, but not ^). The difference between double quotes and braces is that the latter have grammatical value; they are part of the syntax that SM understands. In most cases you can use angle brackets instead of curly ones if the grammar needs the brackets but you don't want to turn off expansions (see Variables).

SM is case-sensitive. It will accept keywords in either upper or lower case, but this is a special dispensation on its part. If you insist on typing in uppercase say load uppercase when you first start SM, or put the line uppercase 1 in your .sm file. Furthermore keywords may not be abbreviated. This is not a great hardship as it is easy to define macros which make the minimum abbreviation a synonym for the full command. Many such macros are predefined for you when you first use SM; see Libraries for details.  In particular, certain common abbreviations of  commands have been predefined by the SM startup file.

Every time that SM is started, it looks for an environment file called .sm which consists of names of variables and their values. From # to the end of a line is taken to be a comment. A list of directories to be searched in order for .sm files is compiled into SM, it usually consists of the current directory, then your home directory, and then some system directory. The system default can be over-ridden by defining the environment variable SMPATH which is a list of directories separated by single spaces. Each directory on the search path is tried in turn until a file is found containing the desired variable, which allows your choices to take preference over those of the system administrator. In the list of directories . is taken to be the current directory, and ~ is your home directory unless you specified a command line -u name option, in which case it is taken to be name's home directory instead. This means that sm -u name will usually run SM as if you were name. If name is null, then SM won't look for a .sm file in anyones home directory. The default path is equivalent to an SMPATH of

     export SMPATH=". ~ /u/sm/lib/"

(or an equivalent incantation). Note that the directory /u/sm/lib/ ends in a / so that a filename can be directly appended (on a VMS system it would probably end in a : or ]).

An example file would be (the filenames are written in Unix)

     # I'm a comment line
     fonts       /users/sm/fonts.bin
     graphcap    /users/sm/graphcap
     help        /users/sm/help/
     macro       /users/sm/macros/
     name        Robert         # Or alternatively `Dr._Lupton'

The fonts file contains the SM fonts (in a binary form), the graphcap entry is used to define the file used to describe graphics terminals (see Graphcap), help is the directory used by the help command, macro is the default directory where macros reside, and name is what SM will call you (you can put spaces into your name by using underscores, e.g. My_Lord will be referred to as My Lord). You can access entries in the environment file yourself, as described in the section on variables. See the section Libraries to see how entries in the .sm file are used to influence the behaviour of SM, or consult your local expert. You might want to borrow someones .sm file when you first use SM, although you should do fine without one. For more detail, and further special entries, see Environment Variables. The name of the .sm file can be specified on the command line as ``-f name'' or you can ask to use name's .sm file with -u name. VMS users should ensure that SM has been installed as a foreign command to take advantage of these capabilities.

SM then tries to read in any macros in the file default in the directory macro and attempts to execute the macro startup if it exists. If -m filename appears on the command line, this is taken to be the name of another file of macros and these are read, and the eponymous macro is executed (after any pre- or suf- fix has been removed. For instance if you start SM with the command sm -m /home/tst.m, it will first read the file /home/tst.m, and then attempt to execute the macro tst). (Under VMS, SM must have been installed as a foreign command for this to work, and it must not have been linked with the debugger)

Anything left on the command line is treated as if it had been typed at the prompt, for example sm restore vital.save will start by RESTORing from the file vital.save (see RESTORE if you want to know what this means). The -m option is not really a good way to personalise SM. The startup macro discussed under `useful macros', which is run every time that you start SM, looks for a directory macro2 in your .sm file, and if it is there reads a file default from it, and executes the macro startup2 which it expects to find there. On case-insensitive operating systems, such as VMS, you may need to quote the command line to prevent it being translated to upper case. SM then attempts to read a set of history commands from a file in the current working directory, passes control to the input routine and issues a prompt. The file is given by the entry hist_file in your .sm file, and if it isn't present then no history will be remembered.

You are then able to type commands, as many as will fit on one line (Occasionally a <CR> is required by SM, so putting two commands on one line will give a syntax error. The cause is the way that the grammar is written (see Command Internals), the fix is either to use two lines, or else to put an explicit carriage return at the appropriate point with a \n), and use the features described below.

You can use a combination of these features to run SM in `batch' mode. If you had a history file that you just wanted to run, then you could start SM, say playback, and quit. You could have a macro called batch in batch.m that did just that, and say sm -m batch.m to execute it. In fact, you don't even need your own macro as one is pre-defined for you so sm batch is sufficient. You could write your own macros along this lines to do more complex tasks. A more convenient alternative (under unix) would be sm -S < history_file where the -S is explained in the next paragraph.

For completeness, we should mention the other command line flags, -h, -l logfile, -n, -q, -s, -S, -v#, and -V. The -h prints a summary of command line options, if you specify a logfile with -l everything that you type at the keyboard is copied into the logfile (except editing commands). When you start SM it usually runs a macro startup; -n prevents this. The -s (for `stupid', or `silent' or `suppress') flag disables the command line editor (although the history list is still saved, so commands like playback will work), -q suppresses the initial `Hello' message, and -S is like -s but it also suppresses the prompt and stops SM from intercepting c. You can get the same effect as -s from inside SM with the command TERMTYPE none. If you are reading from a file or pipe SM behaves as if you had invoked it with the -S flag. This is useful if SM is being run from inside another programme, via a pipe (VMS: mailbox), or on a very stupid terminal. If you want to set a particular value of verbose, use -v for example -v-3 is equivalent to the VERBOSE -3 command given interactively. If you want to know SM's version string without starting SM, you can use the -V flag.

String Variables
****************

Some SM users seem to be confused by variables and vectors; if you are one of these, the section on quoting (see Quoting) might help.

SM maintains a set of variables which are defined with one of the statements

     DEFINE name value

or

     DEFINE name { value_list }

or

     DEFINE name ( expression )

where name must consist of digits, letters and `_' (but must not start with a digit), and may be a keyword.

Value may be a word or a number. Value_list has no such restrictions and may contain many words. Note that due to the presence of the {}, variables are not expanded (i.e. replaced by their value) in value_list, whereas they are in value. In fact, the list can be delimited by <> rather than {}; see DEFINE for details.

The expression in DEFINE variable ( expr ) should be a scalar; if it is not, the first element of the vector will be used and you will be warned, if VERBOSE (see Verbose) is one or greater. Sometimes you just want to evaluate an expression and treat the answer as a string; in this case use the special vector form $(expr) which is replaced by the value of the expression --- for example echo e is $(exp(1)). Expressions are further discussed under `Vectors and Arithmetic'.

There are a number of special variables whose value is always the current value of some internal SM variable such as the current position or the point type. The variable ``date'' is also special and expands to give the current time and date, --- try typing echo $date. You can freeze these variables at their current value by saying define name | (see below).

Each time SM reads $name it replaces it by its value, considered as a character string. For example,

     DEFINE hi hello
     WRITE STANDARD $hi

will print hello. This expansion is done before even the lowest level of lex analysis, so if a command is attempting to read a value it is possible to give it the name of a SM variable. An example would be the XLABEL command, which writes a string as the x-axis label of a graph,

     DEFINE name Aelfred

     XLABEL My name is $name

will invoke the XLABEL command, and write My name is Aelfred below the x-axis. (Incidentally, DEFINE Aelfred Aethelstan YLABEL $$name will write Aethelstan as the y-axis label, which can be handy in macros. The use of the double $$ indicates to SM to do a double translation, as it first expands to $Aelfred which then expands to Aethelstan).

A variable can be deleted by DEFINE name DELETE so for example the macro

     MACRO undef 1 { DEFINE $1 DELETE }

invoked as

     undef name

will undefine the variable name (see the section on macros if you are confused).

There are also three special values, :, |, and ?. The command define name : means `get the value of name from the environment file'. If this fails, and if the variable is all uppercase, SM will then try to use the value of an environment (VMS: logical) variable of the same name. Using define name ? means `read the value of name from the keyboard'. You can specify a prompt to be used, see DEFINE for details. The form with | has changed a little with version 2.1.1. The variables that you can use with | have not changed, but their usage has slightly. They are all defined for you when SM starts and each is always correct, tracking the current value of the corresponding internal variable. For example, try echo $angle angle 45 echo $angle. If you now say define angle |, $angle will cease to track the internal value and will remain fixed (the same effect can be achieved with define angle 45). When you say define angle delete it will once more track the internal value. Your old code will continue to work, but in many cases it is possible to remove the explicit definition with |. This special sort of variable will not be SAVEd, and will not show up if you list the currently defined variables. A list of the | variables is given in the section on DEFINE.

So using the example .sm environment file listed in the previous section of the manual, DEFINE name : will define name to be Robert, DEFINE angle | will give the last value set by the ANGLE command, and DEFINE datafile ? will ask you for the value of `datafile', which can be useful in macros. For example,

     DEFINE noise ? { Ring bell? } IF('$noise' != 'n') { bell }

will execute the macro bell if you type anything but n in reply to the question `Ring bell?'.

When writing macros, it is also sometimes useful to know if a variable has been defined. The variable $?name has the value 1 if name is defined, otherwise it is 0. For instance, there is a line

     define term : if($?term) { termtype $term }

in the startup file, to set a termtype if present in the environment file.

There are also commands to read the values of variables from data files defined with the DATA command.

DEFINE name READ i
     or

DEFINE name READ i j

will set name to be the i'th line of the file (or the j'th word of the i'th line). An example is given in the section on `useful macros'. You can read variables from the headers of binary files (specified with the IMAGE command) using DEFINE name IMAGE, although this is only supported for a limited class of file_type's (see 2-D Graphics).

All currently defined variables may be listed with

     LIST DEFINE [ begin end ]

where the optional begin and end define the range of variables (alphabetically) to be listed. You might prefer to use the macro lsv which won't appear on your history list.

Variables are usually not expanded within double quotes or { }. If for some reason you need to force expansion within double quotes, it can be done with $!name. The macro `load' discussed under useful macros gives an example of this mechanism. If you need to expand a variable, with no questions asked (and even within {}), use $!!name.

Sometimes you may want to terminate a variable name where SM doesn't want to, and this can be done with a trick involving double quotes. Say you are writing a macro to find all the stars redder than B-V = 1.0 in a set of data vectors, and you want to rename them with a trailing ``_red'', so star goes to star_red. So you write a foreach loop,

     FOREACH x ( U B V R I J K ) { SET $x_red = $x IF(B-V >1)}

Well, that won't work because SM thinks that you are referring to a previously defined variable named x_red, so it will complain that x_red is not defined. But if you write it as $x""_red the "" separate the x from the _red until $x is expanded, and then disappear, and all is well. When a variable is read, SM skips over all whitespace before the definition, and this can cause problems if you hit C in the middle, as the rest of the command will be thrown away. If you ever hit a C, and can't get a prompt, try typing any non-whitespace character.

Variables are string-variables, and are not primarily designed for doing arithmetic (that's what vectors are for). This is a common source of confusion so let's consider some examples (at the risk of anticipating some later sections of the manual).

     DEFINE a 12

defines a variable a which consists of the two characters `1' and `2', and which can be used anywhere --- for example xlabel $a. What about vectors? Consider

     SET x=10

which defines a single-element vector whose value is ten, ready to be used in expressions such as

     SET y=$a + x*12

Note that the $a is still just the two characters `1' and `0', but in this context that is interpreted as the number ten. So what does

     DEFINE y $a+x*12

do? Well, actually it results in a syntax error (the `+' ends a word), so try

     DEFINE y <$a+x*12>

This defines the variable y as the string `10+x*12', it doesn't evaluate the expression. You can evaluate the expression if you want with

     DEFINE y ( $a+x*12 )

which defines y as the string `130'. Incidently, you can sometimes get away without an explicit variable with the syntax $($a+x*12) which also expands to the string `130'.

The fact that variables are simply strings can be used to build complex commands; consider for example the macro

     readem          # read multiple lines columns with names in row 1
                     READ ROW names 1.s
                     DEFINE rc <$(names[(0)]) 1>
                     DO i=2,DIMEN(names) {
                             DEFINE rc <$rc $(names[($i - 1)]) $i>
                     }
                     LINES 2 0
                     READ < $rc >

which reads the names of a set of columns from line 1, builds a command to read the data in the variable rc, and then reads all the data in one command. You could of course loop through names reading each column in turn, but this should be a good deal faster.

By default variables are global, so if you have a variable $i, and a macro that you call also uses a variable $i, the macro will change the value that you so carefully defined. To avoid this, it is possible to force variables (and also vectors) to be local, using a command like DEFINE i LOCAL; in this case the variable $i will softly and suddenly disappear when you leave the current macro (and therefore you cannot make variables local at the topmost level, i.e. at the command prompt). In fact, such variables aren't strictly local, they have what's called nested scope, as they are visible from any macros that you may call --- they simply do not propagate backwards up the call stack. You are free to make a variable local in any (or all) macros, there's no restriction on how deep such local declarations may be nested.

Command History
***************

It is often very useful to be able to repeat a command, or perhaps correct a mistake in what you have just typed. Ways of doing this are usually referred to as `history', and SM has two distinct mechanisms. One is very similar to that of the Unix C-Shell, and the other allows you to edit commands using a syntax similar to the popular editor `emacs', or a generalisation of the DCL history under VMS. If you are not familiar with Unix, emacs, or VMS don't despair; a description of the commands and how to invoke them follows in this document. Both of these mechanisms are implemented by the routine which reads input lines. As each line is sent to the parser, it is copied onto a history list. This list may be printed with HISTORY, and the commands may be re-used by referring to them by number, as ^nn, or by a unique abbreviation, as ^abbrev. In addition, the last command may be repeated by using ^^ and the last word of the last command by ^$. (^^ and ^$ really do get back the last command typed, even if it isn't on the history list. If you want the last remembered command, use up-arrow or ^P) These symbols are expanded as soon as they are recognised (see examples, or experiment), and are then available for modification by the editor. Sometimes a ^string will retrieve a command beginning string, but not the one that you want. Version 2.1.1 no longer supports the use of ^TAB to search for the next-most-recent command beginning string, but you can use the search commands (R and S) instead. Some people really don't want ^ to be their history character, either because they're used to something else (such as !), or because they want to type lots of real ^s (e.g. you are using TeX-style strings); if this describes you, rebind them -- see the next section. If you are considering the history list as a sort of programme to be repeated you may think that HISTORY lists the commands in the wrong order; if so use HISTORY -.

For example, if I type:

     PROMPT @
     echo I like SM
     HISTORY

SM will set the prompt to be @, replace the macro echo by its value WRITE STANDARD and print

     I like SM

and then

     3   HISTORY
     2   echo I like SM
     1   PROMPT @

(The actual numbers will be different, depending on what other commands you have executed, and also because SM may have read a history file. In that case there'll be many more commands on the list, but no matter.) If I then type

     ^2 <CR>

(that is ^2 not control-2) the screen will look like

     @ echo I like SM
     I like SM

as if I had just typed it in (@ is the prompt) . Typing

     ^^ (Yes, ^$ ) <CR>

will now result in SM printing (truthfully)

     I like SM (Yes, SM )

It is possible to delete commands from the history buffer with the DELETE command. If the command is given with zero, one, or two arguments, then the specified range is deleted (but their numbers are not re-used). If no arguments are given, the last command on the buffer is deleted, and its number is released to be re-used. In other words, the command DELETE will delete first itself, and then the previous command from the history list. The command DELETE HISTORY only removes itself from the history list, and several of the common commands are defined as macros which use it, for instance dev is defined as DELETE HISTORY DEVICE. This means that the command will not appear on the history list, to confuse you when you do a playback. But if you now innocently use dev in a macro, that macro won't appear on the list either. Still worse, if you use dev twice in one macro, the previous command will be deleted as well which could be quite confusing. You can also delete lines of history using ESC-D as described shortly.

The numbering is consecutive, starting at zero. Each command retains its number until you use a HISTORY command to list the remembered commands, in which case they are all renumbered, and it is these new numbers that are listed.

By default only 80 lines are remembered, and as you continue typing earlier ones fall off the list.

Because the history buffer is also used to compose complex commands, this limit can be aggravating. You may be able to defeat this by putting many commands on each line (you may have to use \n to terminate label commands explicitly) or by writing macros. Alternatively you can define a longer history buffer when you start SM by including an entry history in your environment file

which gives the number of commands to be remembered. If you set history to be 0 the history list is made infinitely long. Incidently, it is the total number of commands that matters, not the range of history numbers present.

This limit on the number of history lines isn't enforced while writing a macro onto the history list (using WRITE HISTORY). You can use this fact to write a sneaky macro that extends your history; type HELP extend_history if you are interested.

Some people seem to like their history editors to remember where they were, so that after they retrieve and execute a command the next P or up-arrow will retrieve the command one further back on the history list (that is, if you have just retrieved command number 123 and executed it as command number 234, then P will get you command number 124; you can execute it as command number 235). If this describes you, define the variable remember_history_line, which you can either do directly, or by putting a line remember_history_line   1 in your .sm file.

The editor allows you to modify commands, either as you type them or as you retrieve them from the history list. The various editing commands may be bound to keys of your choosing, but the default bindings are given in this list of possible commands:

A
     Go to start of line.

B
     Go back one character. (Equivalent to left-arrow ).

C
     Interrupt (as usual).

D
     Delete character under cursor.

E
     Go to end of line.

F
     Go forward one character. (Equivalent to right-arrow ).

H
     Identical to ? (DEL). Delete character to left of cursor.

I (TAB)
     Insert spaces up to the next tab stop. By default a tab is taken to be 8 characters wide, but this may be changed by specifying tabsize in your .sm file.

J (LF)
     Equivalent to M.

K
     Delete to end of line. The deleted string is stored, and may be restored using Y, repeatedly if so desired.

L
     Redraw the current line.

M (CR)
     Send line to be executed. Some terminals seem to replace M with a linefeed (J), thereby making it impossible to make SM obey you. We therefore make @ equivalent to M for emergency use. (This is control-space on many terminals).

N
     Get the next command on the history list, if it exists (see P). (Equivalent to down-arrow ).

O
     Execute the previous command on the history list. Equivalent to PEM.

P
     Get the previous command on the history list, if it exists (see N).(Equivalent to up-arrow ).

Q
     Quote next character; Turn off any special significance to the editor. Q is often used by the terminal, so we have defined [-q (that is escape followed by q) as an alternative.

R
     Search backwards (reversed) for a string; the opposite of S. The `string' can actually be any regular expression (see the manual entry for APROPOS). If you specify a zero-length string (i.e. simply hit carriage return) the previous search string will be reused.

S
     Search forward for a string; the opposite of R. S is often used by the terminal, so we have defined [-s (that is escape followed by s) as an alternative.

T
     Toggle insert/overwrite. By default, characters are inserted before the cursor. If overwrite is set, they replace the character under the cursor. Note that ESC-u will not correctly restore words deleted with ESC-d in overwrite mode.

U
     Delete from the cursor to the start of the line.

V
     Go forward 5 lines.

W
     Delete the previous word. Identical to ESC-h

Y
     Insert the string most recently deleted with K after the cursor.

Z
     Return to the operating system, without killing SM. (Under VMS, if you are running SM in a spawned subprocess Z will attach you to DCL. Otherwise, SM returns you to DCL.)

? (DEL)
     Equivalent to H.

ESC-D
     Delete this line and remove it from the history list. Note that this is different from just clearing a line with (e.g.) U, which only erases a copy of the line.

ESC-<
     Go to the first line of a macro, or the oldest history command.

ESC->
     Go to the last line of a macro, or the most recent history command.

ESC-g
     Go to a given line of a macro, or a given history command. You'll be prompted for the line number, if you change your mind you can get out with DEL or H.

ESC-q
     Quote the next character, turning off any special significance to the editor. Identical to Q.

ESC-s
     Search forward for a string. Identical to S.

ESC-v
     The opposite of V, go back 5 lines.

ESC-y
     Like Y, except that it gets older deletions, cycling back through a collection of (currently 5) deleted lines.

Some ESC-letter combinations are available which operate upon complete words. A word is defined as a whitespace delimited string, so 2.998e8 is a perfectly good word. In addition, it is possible to undelete words that have been deleted with an ESC-d or ESC-h.

ESC-b
     Go to the start of the previous word.

ESC-d
     Delete to the beginning of the next word.

ESC-f
     Go to the beginning of the next word.

ESC-h
     Delete back to the beginning of the current word. The same as W.

ESC-u
     Restore the last word deleted, putting it before the cursor. Further ESC-u's will restore more words. When no more are available, the bell is rung.

Any printing character is inserted before the cursor (unless overwrite has been set with T ). Illegal characters ring the terminal bell. If you insert a non-printing character on a line, the cursor may get confused.

If ever you are stuck at the command interpreter, and you want to send a signal to the operating system (e.g. a Y to DCL), but SM is catching the key and using it for its own purposes, the easiest thing to do is to define a macro such as MACRO aa {aa} , and then run it. While it is running (i.e. until you type C) keys should have their usual functions.

Changing Key-Bindings
*********************

As mentioned above, it is possible to redefine the meanings of keys to the history (and macro) editor. The command EDIT keyword key-sequence will make typing that sequence of keys correspond to the command keyword. For example, to make R redraw the current line, you could say EDIT refresh R. The keyword can be any in the list below, or any single character. Each character in the key-sequence can be a single character, c, or \nnn where nnn is an octal number. Alternatively, READ EDIT filename will read a file specifying the new bindings which has two lines of header, followed by pairs of keyword key-sequence. Lines starting with a # are comments. An example is the file for VMS users given below.

A problem can come up with multiple-key sequences. Imagine that you have bound some function to XA, for example

             EDIT end_of_line ^X^A

then what happens when you try it? SM sees the X and uses its default binding, exit_editor, and then sees a A and goes to the start of the line, which wasn't the desired effect. The solution is to tell SM that X is not a legal key, in which case it will either ring the terminal bell (if there are no key-sequences starting with an X), or wait for the next key. In short,

             EDIT illegal ^X
             EDIT end_of_line ^X^A

should work.

On a somewhat similar topic, the KEY (see Key) command may be used to define a key to generate a string. See the end of the section on macros for how this works.

All the current key definitions may be listed using LIST EDIT, including the KEY definitions. The names of operators, and their default bindings, are given in the following table:

A
     start_of_line

B
     previous_char

C

D
     delete_char

E
     end_of_line

F
     next_char

G
     illegal

H, DEL
     delete_previous_char

I
     tab

J
     carriage_return

K
     kill_to_end

L
     refresh

M, @
     carriage_return

N
     next_line

O
     insert_line_above

P
     previous_line

Q, ESC-q
     quote_next

R
     search_reverse

S
     search_forward

T
     toggle_overwrite

U
     delete_to_start

V
     scroll_forward

W, ESC-h
     delete_previous_word

X
     exit_editor

Y
     yank_buffer

Z
     attach_to_shell

ESC-<
     first_line

ESC->
     last_line

\034
     escape

ESC-b
     previous_word

ESC-d
     delete_next_word

ESC-f
     next_word

ESC-g
     goto_line

ESC-u
     undelete_word

ESC-v
     scroll_back

ESC-y
     yank_previous_buffer

ESC-D
     delete_from_history

^
     history_char

A simple example of a bindings file for a hardened VMS user might be

     # This is a set of DCL-ish key maps for SM
     # name   key
     toggle_overwrite        ^A
     start_of_line           ^H
     delete_previous_word    ^J
     yank_buffer             ^R
     search_reverse          ^[r
     attach_to_shell         ^Y

Note that that's the two characters ^ and A not control-A. It could just as well have been written \001. We need a new character for yank_buffer now that Y is otherwise engaged, and I have chosen R (which means that I can't use R to search backwards, so I chose ESC-r for that). You should be warned that some terminal protocols map M to J, so this use of J could render you unable to issue commands. As mentioned above, in an emergency @ can be used instead of M.

When SM is started, or whenever the TERMTYPE command is used to change terminals, the arrow keys are bound to the commands previous_line, ext_line, previous_char, and ext_char. For terminals such as a Televideo-912, which uses characters such as K for arrow motion, these can supersede the previous meanings (in this case kill_to_end); The only fix is to use the EDIT or READ EDIT command to get what you want, probably within a macro.

If you want to use ' as your history character instead of ^ you need to say edit history_char ` edit ^ ^. If you try to use a character special to SM such as ! this won't work (you'll get a syntax error) and you'll have to use the next alternative, namely put the commands into a file and say read edit filename, for example:

     # Change the history character
     # name   key
     history_char   !
     ^              ^

Because this particular change is so common, it's possible to specify that ` be your history character simply by including a line history_char   ` in your .sm file (or you can choose your own character. Choosing 0 has the effect of using the default, ^).

SM needs to know something about the terminal that you are using, so as to run the history/macro editor. This is entirely separate from the problem of describing the terminal's graphics. It will try to discover what sort of terminal you're on by using the value of term from your .sm file, or failing that the value of the environment variable TERM (Unix) or the logical variable TERM (VMS). A term entry of selanar -21 is equivalent to a TERMTYPE selanar -21 command. You can also use the TERMTYPE command directly. SM then uses the terminal type specified to look up its properties in the termcap database (see Termcap). You can also use TERMTYPE to specify the size of the screen, or to turn off SM's idea of where the cursor is. On some terminals, you can only send a cursor to an absolute position and this is chosen to be the bottom of the screen. This is not what you want for, e.g., a VT240 as it will lead to your graph scrolling off the screen. The use of a negative screen size to TERMTYPE will disable this cursor motion, but will also make editing lines slower. If a line of your graph is being deleted when the SM prompt appears, you may need to use TERMTYPE dumb or TERMTYPE none.

Talking to the Operating System
*******************************

Any line from ! to the newline is passed to your shell (DCL under VMS, the Bourne shell under unix. If you set the variable SHELL in either your .sm file or the environment it will be used instead; the former takes priority). (The first of these commands in a SM session may be rather slow under VMS, as we have to spawn a subprocess.) For example, !ls or !directory will list the current directory. The return code from the command is available in the variable $exit_status, on unix systems it will be 0 for success, for weirder systems you should look in the system manual for the return value of the C function system. $exit_status is one of the variables that can be set with DEFINE exit_status |.

It is also possible to change the directory that SM uses to look for data or macro files with the CHDIR command - for instance CHDIR "../more_data" (Unfortunately, this is currently not available to VMS users). If a directory name starts with `~', CHDIR replaces the  `~' with your home directory. This is the only place that `~' is treated specially, for instance it is not interpreted by the DATA command. Because directory names often contain mathematical characters such as [ or /, it is wise to quote the directory, or use the macro cd which quotes it for you.