Chapter 14. Expression Editor

When the expression editor (expeditor) is enabled as described in Section 2.2, it allows the user to edit expressions entered into the system and move backwards and forwards through a history of entered expressions. This chapter describes a set of parameters that may be used to control various aspects of the expression editor's behavior (Section 14.1), a procedure for binding key sequences to editing commands (Section 14.2), the built-in editing commands (Section 14.3), and mechanisms for creating new editing commands (Section 14.4).

These mechanisms are available through the expression-editor module.

module: expression-editor
libraries: (chezscheme)

The expression-editor module exports a set of bindings for parameters and other procedures that can be used to modify how the expression editor interacts with the user, including the particular keys used to invoke the various editing commands.

Basic use of the expression editor is described in Section 2.2.

Section 14.1. Expression Editor Parameters

global parameter: ee-auto-indent

The value of ee-auto-indent is a boolean value that determines whether the expression editor indents expressions as they are entered. Its default value is #t.

global parameter: ee-standard-indent

The value of ee-standard-indent is a nonnegative fixnum value that determines the amount (in single spaces) by which each expression is indented relative to the enclosing expression, if not aligned otherwise by one of the indenter's other heuristics, when ee-auto-indent is true or when one of the indentation commands is invoked explicitly. It's default value is 2.

global parameter: ee-auto-paren-balance

The value of ee-auto-paren-balance is a boolean value that determines whether the expression editor automatically corrects a close parenthesis or bracket, when typed, to match the corresponding open parenthesis or bracket, if any. Its default value is #t.

global parameter: ee-flash-parens

The value of ee-flash-parens is a boolean value that determines whether the expression editor briefly moves the cursor when an open or close parenthesis or bracket is typed to the matching close or open parenthesis or bracket (if any). Its default value is #t.

global parameter: ee-paren-flash-delay

The value of ee-paren-flash-delay is a nonnegative fixnum value that determines the amount of time (in milliseconds) that the expression editor pauses when the cursor is moved to the matching parenthesis or bracket, if any, when a parenthesis or bracket is entered. The value is ignored if the ee-flash-parens is false. Its default value is 100.

global parameter: ee-default-repeat

The value of ee-default-repeat is a nonnegative fixnum value that determines the number of times the next command is repeated after the ee-command-repeat editing command (bound to Esc-^U by default) is used and not followed by a sequence of digits. It's default value is 4.

global parameter: ee-noisy

The value of ee-noisy is a boolean value that determines whether the expression editor emits a beep (bell) when an error occurs, such as an attempt to find the matching delimiter for a non-delimiter character. Its default value is #f.

global parameter: ee-history-limit

The value of ee-history-limit is a nonnegative fixnum value that determines the number of history entries retained by the expression editor during and across sessions. Only the last (ee-history-limit) entries are retained.

global parameter: ee-common-identifiers

The value of ee-common-identifiers is list of symbols that are considered common enough that they should appear early when one of the incremental identifier-completion editing commands is invoked. Its default value contains a few dozen entries. They are all more than a few characters long (under the theory that users will most likely type short ones out fully) and all would appear later than they likely should when incremental identifier-completion is used.

Section 14.2. Key Binding

Key bindings are established via ee-bind-key. The default key bindings are described in Section 14.3.

procedure: (ee-bind-key key procedure)


returns: unspecified

The ee-bind-key procedure is used to add to or change the set of key bindings recognized by the expression editor.

The key must be a character or string; if it is a string, it must have the following form.

<key-string><graphic>"<key-char>+"

where

<key-char><graphic>\\e (specifying an escape character)
|^x (specifying control-x)
|\\^ (specifying caret)
|\\\\ (specifying back slash)
|plain char (any character other than \ or ^)

Note that each double-backslash in the syntax actually denotes just one backslash in the string.

For example, the key "\\eX" represents the two-character sequence Escape-x, i.e., the "escape" key followed by the (capital) "X" key. Similarly, they key "\\e^X" represents the two-character sequence Escape-Control-x, i.e., the "escape" key followed by Control-X.

Character keys and string keys consisting of a single plain character always represent a single keystroke.

The procedure argument should normally be one of the built-in editing commands described below. It is also possible to define new editing commands with ee-string-macro and ee-compose.

Section 14.3. Editing Commands

The editing commands are grouped into sections according to usage. Each is listed along with the default character sequence or sequences by which it may be invoked.

Insertion commands

command: ee-insert-self
key(s): most printing characters

Inserts the entered character into the entry.

command: ee-insert-paren
key(s): (, ), [, ]

Inserts the entered parenthesis or bracket into the entry.

If the parameter ee-auto-paren-balance is true, the editor corrects close delimiters if necessary to balance existing open delimiters, when a matching open delimiter can be found.

If the parameter ee-flash-parens is true, the editor briefly moves the cursor to the matching delimiter, if one can be found, pausing for an amount of time controlled by the parameter ee-paren-flash-delay. If the matching delimiter is not presently displayed, the cursor is flashed to the upper-left or lower-left corner of the displayed portion of the entry, as appropriate.

The behavior of this command is undefined if used for something other than a parenthesis or bracket.

command: ee-newline
key(s): none

Inserts a newline at the cursor position, moves to the next line, and indents that line if the parameter ee-auto-indent is true. Does nothing if the entry is empty. See also ee-newline/accept.

command: ee-open-line
key(s): ^O

Inserts a newline at the cursor position and indents the next line, but does not move to the next line.

command: ee-yank-kill-buffer
key(s): ^Y

Inserts the contents of the kill buffer, which is set by the deletion commands described below.

command: ee-yank-selection
key(s): ^V

Inserts the contents of the window system's current selection or paste buffer. When running in a shell window under X Windows, this command requires that the DISPLAY environment variable be set to the appropriate display.

Cursor movement commands

command: ee-backward-char
key(s): leftarrow, ^B

Moves the cursor left one character.

command: ee-forward-char
key(s): rightarrow, ^F

Moves the cursor right one character.

command: ee-next-line
key(s): downarrow, ^N

Moves the cursor down one line (and to the left if necessary so that the cursor does not sit beyond the last possible position). If the cursor is at the end of the current entry, and the current entry has not been modified, this command behaves like ee-history-fwd.

command: ee-previous-line
key(s): uparrow, ^P

Moves the cursor up one line (and to the left if necessary so that the cursor does not sit beyond the last possible position). If the cursor is at the top of the current entry, and the current entry has not been modified, this command behaves like ee-history-bwd.

command: ee-beginning-of-line
key(s): home, ^A

Moves the cursor to the first character of the current line.

command: ee-end-of-line
key(s): end, ^E

Moves the cursor to the right of the last character of the current line.

command: ee-beginning-of-entry
key(s): escape-<

Moves the cursor to the first character of the entry.

command: ee-end-of-entry
key(s): escape->

Moves the cursor to the right of the last character of the entry.

command: ee-goto-matching-delimiter
key(s): escape-]

Moves the cursor to the matching delimiter. Has no effect if the character under the cursor is not a parenthesis or bracket or if no matching delimiter can be found.

command: ee-flash-matching-delimiter
key(s): ^]

Moves the cursor briefly to the matching delimiter, if one can be found, pausing for an amount of time controlled by the parameter ee-paren-flash-delay. If the matching delimiter is not presently displayed, the cursor is flashed to the upper-left or lower-left corner of the displayed portion of the entry, as appropriate.

command: ee-exchange-point-and-mark
key(s): ^X-^X

Moves the cursor to the mark and leaves the mark at the old cursor position. (The mark can be set with ee-set-mark.)

command: ee-forward-sexp
key(s): escape-^F

Moves the cursor to the start of the next expression.

command: ee-backward-sexp
key(s): escape-^B

Moves the cursor to the start of the preceding expression.

command: ee-forward-word
key(s): escape-f, escape-F

Moves the cursor to the end of the next word.

command: ee-backward-word
key(s): escape-b, escape-B

Moves the cursor to the start of the preceding word.

command: ee-forward-page
key(s): pagedown, ^X-]

Moves the cursor down one screen page.

command: ee-backward-page
key(s): pageup, ^X-[

Moves the cursor up one screen page.

Deletion commands

command: ee-delete-char
key(s): delete

Deletes the character under the cursor.

See also ee-eof/delete-char.

command: ee-backward-delete-char
key(s): backspace (rubout), ^H

Deletes the character to the left of the cursor.

command: ee-delete-line
key(s): ^U

Deletes the contents of the current line, leaving behind an empty line. When used on the first line of a multiline entry of which only the first line is displayed, i.e., immediately after history movement, ee-delete-line deletes the contents of the entire entry, like ee-delete-entry (described below).

command: ee-delete-to-eol
key(s): ^K, escape-K

If the cursor is at the end of a line, joins the line with the next line, otherwise deletes from the cursor position to the end of the line.

command: ee-delete-between-point-and-mark
key(s): ^W

Deletes text between the current cursor position and the mark. (The mark can be set with ee-set-mark.)

command: ee-delete-entry
key(s): ^G

Deletes the contents of the current entry.

command: ee-reset-entry
key(s): ^C

Deletes the contents of the current entry and moves to the end of the history.

command: ee-delete-sexp
key(s): escape-^K, escape-delete

Deletes the expression that starts under the cursor, or if no expression starts under the cursor, deletes up to the next expression.

command: ee-backward-delete-sexp
key(s): escape-backspace (escape-rubout), escape-^H

Deletes the expression to the left of the cursor.

Identifier/filename completion commands

These commands perform either identifier or filename completion. Identifier completion is performed outside of a string constant, and filename completion is performed within a string constant. (In determining whether the cursor is within a string constant, the expression editor looks only at the current line and so can be fooled by string constants that span multiple lines.)

command: ee-id-completion
key(s): none

Inserts the common prefix of possible completions of the identifier or filename immediately to the left of the cursor. Identifier completion is based on the identifiers defined in the interaction environment. When there is exactly one possible completion, the common prefix is the completion. This command has no effect if no filename or identifier prefix is immediately the left of the cursor or if the possible completions have no common prefix. If run twice in succession, a list of possible completions is displayed.

See also ee-id-completion/indent.

command: ee-next-id-completion
key(s): ^R

Inserts one of the possible completions of the identifier or filename immediately to the left of the cursor. Identifier completion is based on the identifiers defined in the interaction environment. If run twice or more in succession, this command cycles through all of the possible completions. The order is determined by the following heuristics: appearing first are identifiers whose names appear in the list value of the parameter ee-common-identifiers; appearing second are identifiers bound in the interaction environment but not bound in the scheme-environment (i.e., identifiers defined by the user), and appearing last are those in the scheme environment. Within the set of matches appearing in the ee-common-identifiers list, those listed earliest are shown first; the order is alphabetical within the other two sets.

See also ee-next-id-completion/indent.

History movement commands

The expression editor maintains a history of entries during each session. It also saves the history across sessions unless this behavior is disabled via the command-line argument "--eehistory off."

When moving from one history entry to another, only the first line of each multi-line entry is displayed. The redisplay command (which ^L is bound to by default) can be used to display the entire entry. It is also possible to move down one line at a time to expose just part of the rest of the entry.

command: ee-history-bwd
key(s): escape-uparrow, escape-^P

Moves to the preceding history entry if the current entry is empty or has not been modified; otherwise, has no effect.

See also ee-previous-line.

command: ee-history-fwd
key(s): escape-downarrow, escape-^N

Moves to the next history entry if the current entry is empty or has not been modified; otherwise, has no effect.

See also ee-next-line.

command: ee-history-bwd-prefix
key(s): escape-p

Moves to the closest previous history entry, if any, that starts with the sequence of characters that makes up the current entry. May be used multiple times to search for same prefix.

command: ee-history-fwd-prefix
key(s): escape-n

Moves to the closest following history entry, if any, that starts with the sequence of characters that makes up the current entry. May be used multiple times to search for same prefix.

command: ee-history-bwd-contains
key(s): escape-P

Moves to the closest previous history entry, if any, that contains within it the sequence of characters that makes up the current entry. May be used multiple times to search for same content.

command: ee-history-fwd-contains
key(s): escape-N

Moves to the closest following history entry, if any, that contains within it the sequence of characters that makes up the current entry. May be used multiple times to search for same content.

Indentation commands

command: ee-indent
key(s): escape-tab

Re-indents the current line.

See also ee-next-id-completion/indent.

command: ee-indent-all
key(s): escape-q, escape-Q, escape-^Q

Re-indents each line of the entire entry.

Miscellaneous commands

command: ee-accept
key(s): ^J

Causes the expression editor to invoke the Scheme reader on the contents of the entry. If the read is successful, the expression is returned to the waiter; otherwise, an error message is printed, the entry redisplayed, and the cursor left (if possible) at the start of the invalid subform.

See also ee-newline/accept.

command: ee-eof
key(s): none

Causes end-of-file to be returned from the expression editor, which in turn causes the waiter to exit. Ignored unless entry is empty.

See also ee-eof/delete-char.

command: ee-redisplay
key(s): ^L

Redisplays the current expression. If run twice in succession, clears the screen and redisplays the expression at the top of the screen.

command: ee-suspend-process
key(s): ^Z

Suspends the current process in shells that support job control.

command: ee-set-mark
key(s): ^@, ^space

Sets the mark to the current cursor position.

command: ee-command-repeat
key(s): escape-^U

Repeats the next command n times. If the next character typed is a digit, n is determined by reading up the sequence of the digits typed and treating it as a decimal number. Otherwise, n is the value of the parameter ee-default-repeat.

Combination commands

command: ee-newline/accept
key(s): enter, ^M

Behaves like ee-accept if run at the end (not including whitespace) of an entry that starts with a balanced expression; otherwise, behaves like ee-newline.

command: ee-id-completion/indent
key(s): tab

Behaves like ee-id-completion if an identifier (outside a string constant) or filename (within a string constant) appears just to the left of the cursor and the last character of that identifier or filename was just entered; otherwise, behaves like ee-indent.

If an existing identifier or filename, i.e., not one just typed, appears to the left of the cursor, the first use of this command behaves like ee-newline, the second consecutive use behaves like ee-id-completion, and the third behaves like a second consecutive use of ee-id-completion.

command: ee-next-id-completion/indent
key(s): none

Behaves like ee-next-id-completion if an identifier (outside a string constant) or filename (within a string constant) appears just to the left of the cursor and the last character of that identifier or identifier was just entered; otherwise, behaves like ee-indent.

command: ee-eof/delete-char
key(s): ^D

Behaves like ee-delete-char if the entry is nonempty; otherwise, behaves like ee-eof. If the entry is nonempty and this command is run twice or more in succession, it does nothing once the entry becomes empty. This is to prevent accidental exit from the waiter in cases where the command is run repeatedly (perhaps with the help of a keyboard's auto-repeat feature) to delete all of the characters in an entry.

Section 14.4. Creating New Editing Commands

procedure: (ee-string-macro string)


returns: a new editing command

The new editing command produced inserts string before the current cursor position.

Two string macros are predefined:

(ee-string-macro "(define ")   escape-d
(ee-string-macro "(lambda ")   escape-l

procedure: (ee-compose ecmd ...)


returns: a new editing command

Each ecmd must be an editing command.

The new editing command runs each of the editing commands ecmd ... in sequence.

For example, the following expression binds ^X-p to an editing command that behaves like ee-history-bwd-prefix but leaves the cursor at the end of the expression rather than at the end of the first line, causing the entire entry to be displayed.

(let ()
  (import expression-editor)
  (ee-bind-key "^Xp"
    (ee-compose ee-history-bwd ee-end-of-entry)))

A command such as ee-id-completion that performs a different action when run twice in succession will not recognize that it has been run twice in succession if run as part of a composite command.

Chez Scheme Version 9 User's Guide
Copyright © 2023 Cisco Systems, Inc.
Licensed under the Apache License Version 2.0 (full copyright notice.).
Revised October 2023 for Chez Scheme Version 9.6.4
about this book