123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- How to customize NMODE
- Alan Snyder
- 24 September 1982
- -------------------------------------------------------------------------------
- This memo explains how to customize NMODE by redefining the effect of input
- keystrokes. NMODE is customized by executing Lisp forms. These forms may be
- executed directly within NMODE (using Lisp-E), or may be stored in an INIT
- file, which is read by NMODE when it first starts up. The name of the INIT
- file read by NMODE is "NMODE.INIT" in the user's home directory.
- There are three concepts that must be understood to customize NMODE: Commands,
- Functions, and Modes.
- 1) Commands. The effect of given keystroke or sequence of keystrokes in
- NMODE is based on a mapping between "commands" and "functions".
- A "command" may be either a single "extended character" or a sequence
- of characters. An extended character is a 9-bit character with
- distinct "Control" and "Meta" bits. Thus "C-M-A" is a single "extended
- character", even though on many terminals you have to use two keystrokes
- to enter it. Extended characters are specified using the macro X-CHAR,
- for example:
- (x-char A) the letter "A" (upper case)
- (x-char C-F) Control-F
- (x-char C-M-Z) Control-Meta-Z
- (x-char CR) Carriage-Return
- (x-char TAB) Tab
- (x-char BACKSPACE) Backspace
- (x-char NEWLINE) Newline
- (x-char RUBOUT) Rubout
- (x-char C-M-RUBOUT) Control-Meta-Rubout
- (The macros described in this section are defined in the load module
- EXTENDED-CHAR.) It is important to note that on most terminals, some Ascii
- control characters are mapped to extended "Control" characters and some aren't.
- Those that aren't are: Backspace, CR, Newline, Tab, and Escape. Even if you
- type "CNTL-I" on the keyboard, you will get "Tab" and not "Control-I". The
- remaining Ascii control characters are mapped to extended "Control" characters,
- thus typing "CNTL-A" on the keyboard gives "Control-A".
- As mentioned above, a command can be a sequence of characters. There are two
- forms: Prefix commands and Extended commands.
- Prefix commands: A prefix command consists of two characters, the first of
- which is a defined "prefix character". In NMODE, there are 3 predefined prefix
- characters: C-X, ESC, and C-]. Prefix commands are specified using the X-CHARS
- macro, for example:
- (x-chars C-X C-F)
- (x-chars ESC A)
- (x-chars C-] E)
- Extended commands: An extended command consists of the character M-X and a
- string. Extended commands are defined using the M-X macro, for example:
- (M-X "Lisp Mode")
- (M-X "Revert File")
- The case of the letters in the string is irrelevant, except to specify how the
- command name will be displayed when "completion" is used by the user. By
- convention, the first letter of each word in an extended command name is
- capitalized.
- 2) Functions. NMODE commands are implemented by PSL functions. By convention,
- most (but not all) PSL functions that implement NMODE commands have names
- ending with "-COMMAND", for example, MOVE-FORWARD-CHARACTER-COMMAND.
- An NMODE command function should take no arguments. The function can perform
- its task using a large number of existing support functions; see PN:BUFFER.SL
- and PN:MOVE-COMMANDS.SL for examples. A command function can determine the
- command argument (given by C-U) by inspecting global variables:
- nmode-command-argument: the numeric value (default: 1)
- nmode-command-argument-given: T if the user specified an argument
- nmode-command-number-given: T if the user typed digits in the argument
- See the files PN:MOVE-COMMANDS.SL, PN:LISP-COMMANDS.SL, and PN:COMMANDS.SL for
- many examples of NMODE command functions.
- 3) Modes. The mapping between commands and functions is dependent on the
- current "mode". Examples of existing modes are "Text Mode", which is the basic
- mode for text editing, "Lisp Mode", which is an extension of "Text Mode" for
- editing and executing Lisp code, and "Dired Mode", which is a specialized mode
- for the Directory Editor Subsystem.
- A mode is defined by a list of Lisp forms which are evaluated to determine the
- state of a Dispatch Table. The Dispatch Table is what is actually used to map
- from commands to functions. Every time the user selects a new buffer, the
- Dispatch Table is cleared and the Lisp forms defining the mode for the new
- buffer are evaluated to fill the Dispatch Table. The forms are evaluated in
- reverse order, so that the first form is evaluated last. Thus, any command
- definitions made by one form supercede those made by forms appearing after it
- in the list.
- Two functions are commonly invoked by mode-defining forms: NMODE-ESTABLISH-MODE
- and NMODE-DEFINE-COMMANDS. NMODE-ESTABLISH-MODE takes one argument, a list of
- mode defining forms, and evaluates those forms. Thus, NMODE-ESTABLISH-MODE can
- be used to define one mode in terms of (as an extension of or a modification
- to) another mode.
- NMODE-DEFINE-COMMANDS takes one argument, a list of pairs, where each pair
- consists of a COMMAND and a FUNCTION. This form of list is called a "command
- list". Command lists are not used directly to map from commands to functions.
- Instead, NMODE-DEFINE-COMMANDS reads the command list it is given and for each
- COMMAND-FUNCTION pair in the command list (in order), it alters the Dispatch
- Table to map the specified COMMAND to the corresponding FUNCTION.
- Note that as a convenience, whenever you define an "upper case" command, the
- corresponding "lower case" command is also defined to map to the same function.
- Thus, if you define C-M-A, you automatically define C-M-a to map to the same
- function. If you want the lower case command to map to a different function,
- you must define the lower case command "after" defining the upper case command.
- The usual technique for modifying one or more existing modes is to modify one
- of the command lists given to NMODE-DEFINE-COMMANDS. The file PN:MODE-DEFS.SL
- contains the definition of most predefined NMODE command lists, as well as the
- definition of most predefined modes. To modify a mode or modes, you must alter
- one or more command lists by adding (or perhaps removing) entries. Command
- lists are manipulated using two functions:
- (add-to-command-list list-name command func)
- (remove-from-command-list list-name command)
- Here are some examples:
- (add-to-command-list
- 'text-command-list (x-char BACKSPACE) 'delete-backward-character-command)
- (add-to-command-list
- 'lisp-command-list (x-char BACKSPACE) 'delete-backward-hacking-tabs-command)
- (remove-from-command-list
- 'read-only-text-command-list (x-char BACKSPACE))
- [The above forms change BACKSPACE from being the same as C-B to being
- the same as RUBOUT.]
- (add-to-command-list
- 'read-only-text-command-list (x-char M-@) 'set-mark-command)
-
- [The above form makes M-@ set the mark.]
- (add-to-command-list
- 'read-only-terminal-command-list (x-chars ESC Y) 'print-buffer-names-command)
-
- [The above form makes Esc-Y print a list of all buffer names. Esc-Y is
- sent by HP264X terminals when the "Display Functions" key is hit.]
- Note that these functions change only the command lists, not the Dispatch Table
- which is actually used to map from commands to functions. To cause the
- Dispatch Table to be updated to reflect any changes in the command lists, you
- must invoke the function NMODE-ESTABLISH-CURRENT-MODE.
|