[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1 Programming Jade

This chapter of the manual is a full guide to Jade’s Lisp programming language, including documentation for most of the built-in functions.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1 Introduction

As you have probably gathered by now, Jade is largely controlled by its built in programming language: a dialect of Lisp containing many extensions (non-standard data types and functions) to make it suitable for controlling an editor. Through this language Jade can be customised and extended.

I have attempted to make the “standard” portion of the language (i.e. anything a normal Lisp would have; not related to editing) as compatible with GNU Emacs Lisp as possible. In some areas this rule doesn’t apply, there will usually be a good reason for this. A few functions have been inspired by Common Lisp.

The areas of the language which control the editor are not compatible with Emacs; some functions may be similar but since the two editors are fundamentally different I have not attempted to conform with the Emacs API.

All programs written using only the information in this manual should be compatible with future revisions of Jade.

This following sections explain some of the most important Lisp concepts and the conventions I’ve used in this manual.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1.1 nil and t

The two boolean values in Lisp are the symbols nil (FALSE) and t (TRUE). Both these symbols always evaluate to themselves (so they do not have to be quoted), any attempt to change their values is an error.

All of the conditional instructions regard anything which is not nil as being TRUE (i.e. not-FALSE). The actual symbol t should be used where a TRUE boolean value must be explicitly stated to increase the clarity of the code.

This is not the end of the story; nil actually has another meaning: it represents the empty list. This is a consequence of how lists are constructed in Lisp, a list of zero elements is stored as the symbol nil.

To the Lisp system itself there is absolutely no difference between () (the notation for a list with zero elements) and nil (the symbol nil). When writing code however, the list notation is usually used when the programmer regards the value as a list and the nil notation when its value as a boolean is to be emphasised.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1.2 The Lisp Reader

Lisp programs and functions are stored internally as normal Lisp data objects, the Lisp Reader is the process used to translate textual descriptions of Lisp objects into the data structures used to represent the objects.

The Lisp Reader is the collection of internal functions accessed by the read Lisp function. It reads a character at a time from an input stream until it has parsed a whole Lisp object.

See section Data Types.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1.3 Notation

Wherever an example of evaluating a Lisp form is shown it will be formatted like this,

(+ 1 2)
    ⇒ 3

The glyph ‘’ is used to show the computed value of a form.

When two forms are shown as being exactly equivalent to one another the glyph ‘’ is used, for example,

(car some-variable) ≡ (nth 0 some-variable)

Evaluating some forms result in an error being signalled, this is denoted by the ‘error-->’ glyph.

(read-file "/tmp/foo")
    error--> File error: No such file or directory, /tmp/foo

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1.4 Descriptions

The simplest type of descriptions are the descriptions of variables (see section Variables), they look something like,

Variable: grains-of-sand

This imaginary variable contains the number of grains of sand in a one-mile long stretch of an averagely sandy beach.

Hooks (see section Hooks) are also described in this format, the only difference is that ‘Variable:’ is replaced by ‘Hook:’.

Functions (see section Functions) and macros (see section Macros) have more complex descriptions; as well as the name of the thing being described, they also have a list of arguments which the thing will accept. Each argument in the list is named and may be referred to in the body of the description.

Two ‘special’ arguments may be used, ‘&optional’ and &rest. They have the same meaning as when used in the lambda-list of a function definition (see section Lambda Expressions), that is ‘&optional’ means that all further arguments are optional, and ‘&rest’ means that zero or more argument values are coalesced into a list to be used as the value of the following argument.

An example function definition follows.

Function: useless-function first &optional second &rest tail

This function returns a list consisting of the values second (when undefined the number 42 is used), all the items in the list tail and first.

(useless-function 'foo 'bar 'xyz 20)
    ⇒ (bar xyz 20 foo)

(useless-function '50)
    ⇒ (42 50)

Macros and commands (see section Commands) are defined in the same way with ‘Macro:’ or ‘Command:’ replacing ‘Function:’.

Special forms (see section Special Forms) are described similarly to functions except that the argument list is formatted differently since special forms are, by definition, more flexible in how they treat their arguments. Optional values are enclosed in square brackets (‘[optional-arg]’) and three dots (‘repeated-arg’) indicate where zero or more arguments are allowed.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2 Data Types

The way that data values are represented in Lisp is fundamentally different to more “conventional” languages such as C or Pascal: in Lisp each piece of data (a Lisp Object) has two basic attributes, the actual data and a tag value defining the type of the object. This means that type checking is performed on the actual data itself, not on the “variable” holding the data.

All Lisp objects are a member of one of the primitive types; these are types built into the Lisp system and can represent things like strings, integers, cons cells, vectors, etc…

More complex types of object can be constructed from these primitive types, for example a vector of three elements could be regarded as a type triple if necessary. In general, each separate type provides a predicate function which returns t when applied to an object of its type.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2.1 Types Summary

Each separate data type is documented in its own section, this is a just a table of the more common types.

Integer

32-bit signed integers. See section Numbers.

Cons cell

An object containing two other Lisp objects. See section Cons Cells.

List

A sequence of objects, in Lisp lists are not primitive types, instead they are made by chaining together Cons cells. See section Lists.

Vector

A one-dimensional array of objects. See section Vectors.

String

A vector of characters. See section Strings.

Array

An ordered sequence of objects which can be accessed in constant time, either a vector or a string. See section Sequences.

Sequence

An ordered sequence of objects, either a list or an array. See section Sequences.

Symbol

A symbol is a named object; they are used to provide named variables and functions. See section Symbols.

File

A link to a file in the operating system’s filing system, allows access to the file as a stream. See section Files.

Stream

Serial data sinks and sources. See section Streams.

Void

No type, only used in symbols to represent an unset function or variable value.

Buffer

A “space” in which text can be edited, buffers may be displayed in a window and hence edited by the user. See section Buffers.

Window

A physical window in the underlying window-system, used for input and output.

Position

A pair of integers, used to represent the coordinates of a character in a buffer. See section Positions.

Mark

A position in a specified file, this file may either be a buffer in memory or a named file. See section Marks.

Process

An object through which processes may be created and controlled. See section Processes.

Glyph Table

A lookup-table which is used to map characters in a buffer to the sequence of glyphs they are rendered as. See section Glyph Tables.

Keymap

A set of key-sequence-to-command mappings; when installed in a buffer it controls how the editor reacts to all input from the user. See section Keymaps.

Event

An (input-) event from a window.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2.2 Read Syntax

As previously noted the Lisp reader translates textual descriptions of Lisp objects into the object they describe (source files are simply descriptions of objects). However, not all data types can be created in this way: in fact the only types which can are integers, strings, symbols, cons cells (or lists) and vectors, all others have to be created by calling functions.

Note that comments in a Lisp program are introduced by the semi-colon character (‘;’). Whenever the Lisp reader encounters a semi-colon where it’s looking for the read syntax of a new Lisp object it will discard the rest of the line of input. See section Comment Styles.

The read syntax of an object is the string which when given to the reader as input will produce the object. The read syntax of each type of object is documented in that type’s main section of this manual but here is a small taste of how to write each type.

Integers

An integer is simply the number written in either decimal, octal (when the number is preceded by ‘0’) or hexadecimal (when the number is preceded by ‘0x’). An optional minus sign may be the first character in a number. Some examples are,

42
    ⇒ 42

0177
    ⇒ 127

0xff
    ⇒ 255

-0x10
    ⇒ -16
Strings

The read syntax of a string is simply the string with a double-quote character (‘"’) at each end, for more details see Strings.

"This is a string"
Cons cells

A cons cell is written in what is known as dotted pair notation and is just the two objects in the cell separated by a dot and the whole thing in parentheses,

(car . cdr)
Lists

The syntax of a list is similar to a cons cell (since this is what lists are made of): no dot is used and there may be zero or more objects,

(object1 object2 object3 …)

("foo" ("bar" "baz") 100)

The second example is a list of three elements, a string, another list and a number.

Vectors

The read syntax of a vector is very similar to that of a list, simply use square brackets instead of parentheses,

[object1 object2 object3 …]
Symbols

A symbol’s read syntax is simply its name, for example the read syntax of a symbol called ‘my-symbol’ is,

my-symbol

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2.3 Printed Representation

The printed representation of an object is the string produced when the object is printed (with one of the print functions), this will usually be very similar to the read syntax of the object (see section Read Syntax).

Objects which do not have a read syntax do have a printed representation, it will normally be of the form,

#<relevant text>

where the “relevant text” is object-dependent and usually describes the object and its contents. The reader will signal an error if it encounters a description of an object in the format ‘#<…>’.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2.4 Equality Predicates

Function: eq arg1 arg2

Returns t when arg1 and arg2 are the same object. Two objects are the same object when they occupy the same place in memory and hence modifying one object would alter the other. The following Lisp fragments may illustrate this,

(eq "foo" "foo")	;the objects are distinct
    ⇒ nil

(eq t t)		;the same object -- the symbol t
    ⇒ t

Note that the result of eq is undefined when called on two integer objects with the same value, see eql.

Function: equal arg1 arg2

The function equal compares the structure of the two objects arg1 and arg2. If they are considered to be equivalent then t is returned, otherwise nil is returned.

(equal "foo" "foo")
    ⇒ t

(equal 42 42)
    ⇒ t

(equal 42 0)
    ⇒ nil

(equal '(x . y) '(x . y))
    ⇒ t
Function: eql arg1 arg2

This function is a cross between eq and equal: if arg1 and arg2 are both numbers then the value of these numbers are compared. Otherwise it behaves in exactly the same manner as eq does.

(eql 3 3)
    ⇒ t

(eql 1 2)
    ⇒ nil

(eql "foo" "foo")
    ⇒ nil

(eql 'x 'x)
    ⇒ t

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2.5 Comparison Predicates

These functions compare their two arguments in a scalar fashion, the arguments may be of any type but the results are only meaningful for numbers, strings (ASCII values of each byte compared until a non-matching pair is found then those two values are compared as numbers) and positions.

Function: > arg1 arg2

Returns t when arg1 is ‘greater than’ arg2.

Function: >= arg1 arg2

Returns t when arg1 is ‘greater than or equal to’ arg2.

Function: < arg1 arg2

Returns t when arg1 is ‘less than’ arg2.

Function: <= arg1 arg2

Returns t when arg1 is ‘less than or equal to’ arg2.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2.6 Type Predicates

Each type has a corresponding predicate which defines the objects which are members of that type.

The documentation for these functions is with the documentation for the relevant type.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2.7 Garbage Collection

In Lisp, data objects are used very freely; a side effect of this is that it is not possible to (easily) know when an object is stale, that is, no references to it exist and it can therefore be reused.

The garbage collector is used to overcome this problem; whenever enough new data objects have been allocated to make it worthwhile, everything stops and the garbage collector works its way through memory deciding which objects are still in use and which are stale. The stale objects are then recorded as being available for reuse and evaluation continues again.

Function: garbage-collect

Runs the garbage collector, usually this function doesn’t need to be called manually.

Variable: garbage-threshold

The number of bytes of data which must be allocated before evaluation will pause and the garbage collector called.

Its default value is about 100K.

See section Idle Actions.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3 Numbers

Currently Jade is only capable of representing integers, for this it uses signed 32-bit integers: this gives a range of -2147483648 through 0 to 2147483647.

The read syntax of an integer is simply the number written in decimal, octal or hexadecimal. If the integer starts with the string ‘0x’ it is assumed to be hexadecimal or if it starts with a zero it is treated as octal. The first character may be an optional minus or plus sign (this should come before any base-specifier). Examples of valid integer read syntaxes for the number 42 could be ‘42’, ‘0x2a’, ‘052’, ‘+052’, …

An integer’s printed representation is simply the number printed in decimal with a preceding minus sign if it is negative.

Function: numberp object

This function returns t if object is a number.

Function: integerp object

This function returns t when object is an integer.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.4 Arithmetic Functions

There are a number of functions which perform arithmetic operations on numbers, they take a varying number of integer objects as their arguments then return a new integer object as their result.

Note that none of these functions check for overflow.

Function: + number1 &rest numbers

This functions adds its arguments then returns their sum.

Function: - number1 &rest numbers

If this function is just given one argument (number1) that number is negated and returned. Otherwise each of numbers is subtracted from a running total starting with the value of number1.

(- 20)
    ⇒ -20

(- 20 10 5)
    ⇒ 5
Function: * number1 &rest numbers

This function multiplies its arguments then returns the result.

Function: / number1 &rest numbers

This function performs division, a running-total (initialised from number1 is successively divided by each of numbers then the result is returned.

(/ 100 2)
    ⇒ 50

(/ 200 2 5)
    ⇒ 20
Function: % dividend divisor

Returns the remainder from dividing dividend by divisor.

(mod 5 3)
    ⇒ 2
Function: 1+ number

This function returns the result of adding one to number.

(1+ 42)
    ⇒ 43
Function: 1- number

Returns number minus one.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.5 Bitwise Functions

These functions operate on the bit string which an integer is made of.

Function: lsh number count

This function bit-shifts the integer number count bits to the left, if count is negative number is shifted to the right instead.

(lsh 1 8)
    ⇒ 256

(lsh 256 -8)
    ⇒ 1
Function: ash number count

Similar to lsh except that an arithmetical shift is done, this means that the sign of number is always preserved.

(ash 1 8)
    ⇒ 256

(ash -1 2)
    ⇒ -4
Function: logand number1 &rest numbers

This function uses a bit-wise logical ‘and’ operation to combine all its arguments (there must be at least one argument).

(logand 15 8)
    ⇒ 8

(logand 15 7 20)
    ⇒ 4
Function: logior number1 &rest numbers

Uses a bit-wise logical ‘inclusive-or’ to combine all its arguments (there must always be at least one argument).

(logior 1 2 4)
    ⇒ 7
Function: logxor number1 &rest numbers

Uses a bitwise logical ‘exclusive-or’ to combine all its arguments (there must be at least one).

(logxor 7 3)
    ⇒ 4
Function: lognot number

This function inverts all the bits in number.

(lognot 0)
    ⇒ -1

(lognot 2)
    ⇒ -3

(lognot -1)
    ⇒ 0

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6 Numeric Predicates

For the documentation of the functions >, <, >= and <= see Comparison Predicates.

Function: = number1 number2

This function returns t if the two integers number1 and number2 have the same value.

(= 1 1)
    ⇒ t

(= 1 0)
    ⇒ nil
Function: /= number1 number2

This function will return t if number1 and number2 and not equal to each other.

(/= 1 1)
    ⇒ nil

(/= 1 0)
    ⇒ t
Function: zerop number

Returns t if number is equal to zero.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6.1 Characters

In Jade characters are stored in integers. Their read syntax is a question mark followed by the character itself which may be an escape sequence introduced by a backslash. For details of the available escape sequences see Strings.

?a
    ⇒ 97

?\n
    ⇒ 10

?\177
    ⇒ 127
Function: alpha-char-p character

This function returns t when character is one of the alphabetic characters.

(alpha-char-p ?a)
    ⇒ t
Function: upper-case-p character

When character is one of the upper-case characters this function returns t.

Function: lower-case-p character

Returns t when character is lower-case.

Function: digit-char-p character

This function returns t when character is one of the decimal digit characters.

Function: alphanumericp character

This function returns t when character is either an alphabetic character or a decimal digit character.

Function: space-char-p character

Returns t when character is a white-space character (space, tab, newline or form feed).

Function: char-upcase character

This function returns the upper-case equivalent of character. If character is already upper-case or has no upper-case equivalent it is returned unchanged.

(char-upcase ?a)
    ⇒ 65                       ;`A'

(char-upcase ?A)
    ⇒ 65                       ;`A'

(char-upcase ?!)
    ⇒ 33                       ;`!'
Function: char-downcase character

Returns the lower-case equivalent of the character character.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7 Sequences

Sequences are ordered groups of objects, there are several primitive types which can be considered sequences, each with its own good and bad points.

A sequence is either an array or a list, where an array is either a vector or a string.

Function: sequencep object

This function returns t if object is a sequence, nil otherwise.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.1 Cons Cells

A cons cell is an ordered pair of two objects, the car and the cdr.

The read syntax of a cons cell is an opening parenthesis followed by the read syntax of the car, a dot, the read syntax of the cdr and a closing parenthesis. For example a cons cell with a car of 10 and a cdr of the string ‘foo’ would be written as,

(10 . "foo")
Function: cons car cdr

This function creates a new cons cell. It will have a car of car and a cdr of cdr.

(cons 10 "foo")
    ⇒ (10 . "foo")
Function: consp object

This function returns t if object is a cons cell and nil otherwise.

(consp '(1 . 2))
    ⇒ t

(consp nil)
    ⇒ nil

(consp (cons 1 2))
    ⇒ t

In Lisp an atom is any object which is not a cons cell (and is, therefore, atomic).

Function: atom object

Returns t if object is an atom (not a cons cell).

Given a cons cell there are a number of operations which can be performed on it.

Function: car cons-cell

This function returns the object which the car of the cons cell cons-cell.

(car (cons 1 2))
    ⇒ 1

(car '(1 . 2))
    ⇒ 1
Function: cdr cons-cell

This function returns the cdr of the cons cell cons-cell.

(cdr (cons 1 2))
    ⇒ 2

(cdr '(1 . 2))
    ⇒ 2
Function: rplaca cons-cell new-car

This function sets the value of the car in the cons cell cons-cell to new-car. The value returned is new-car.

(setq x (cons 1 2))
    ⇒ (1 . 2)
(rplaca x 3)
    ⇒ 3
x
    ⇒ (3 . 2)
Function: rplacd cons-cell new-cdr

This function is similar to rplacd except that the cdr slot of cons-cell is modified.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.2 Lists

A list is a sequence of zero or more objects, the main difference between lists and vectors is that lists are more dynamic: they can change size, be split, reversed, concatenated, etc… very easily.

In Lisp lists are not a primitive type; instead singly-linked lists are created by chaining cons cells together (see section Cons Cells).

Function: listp object

This functions returns t when its argument, object, is a list (i.e. either a cons cell or nil).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.2.1 List Structure

Each element in a list is given its own cons cell and stored in the car of that cell. The list object is then constructed by making the cdr of a cell contain the cons cell of the next element (and hence the whole tail of the list). The cdr of the cell containing the last element in the list is nil. A list of zero elements is represented by the symbol nil.

The read syntax of a list is an opening parenthesis, followed by the read syntax of zero or more space-separated objects, followed by a closing parenthesis. Alternatively, lists can be constructed ‘manually’ using dotted-pair notation.

All of the following examples result in the same list of five elements: the numbers from zero to four.

(0 1 2 3 4)

(0 . (1 . (2 . (3 . (4 . nil)))))

(0 1 2 . (3 4))

An easy way to visualise lists and how they are constructed is to see each cons cell in the list as a separate box with pointers to its car and cdr,

+-----+-----+
|  o  |  o----> cdr
+--|--+-----+
   |
    --> car

Complex box-diagrams can now be drawn to represent lists. For example the following diagram represents the list (1 2 3 4).

+-----+-----+   +-----+-----+   +-----+-----+   +-----+-----+
|  o  |  o----> |  o  |  o----> |  o  |  o----> |  o  |  o----> nil
+--|--+-----+   +--|--+-----+   +--|--+-----+   +--|--+-----+
   |               |               |               |
    --> 1           --> 2           --> 3           --> 4

A more complex example, the list ((1 2) (foo bar)) can be drawn as,

+-----+-----+                          +-----+-----+
|  o  |  o---------------------------> |  o  |  o----> nil
+--|--+-----+                          +--|--+-----+
   |                                      |
+-----+-----+   +-----+-----+          +-----+-----+   +-----+-----+
|  o  |  o----> |  o  |  o----> nil    |  o  |  o----> |  o  |  o----> nil
+--|--+-----+   +--|--+-----+          +--|--+-----+   +--|--+-----+
   |               |                      |               |
    --> 1           --> 2                  --> foo         --> bar

Sometimes when manipulating complex list structures it is very helpful to make a diagram of what it is that’s being manipulated.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.2.2 Building Lists

It has already been shown how you can create lists using the Lisp reader; this method does have a drawback though: the list created is effectively static. If you modify the contents of the list and that list was created when a function was defined the list will remain modified for all future invocations of that function. This is not usually a good idea, consider the following function definition,

(defun bogus-function (x)
  "Return a list whose first element is nil and whose second element is X."
  (let
      ((result '(nil nil)))     ;Static list which is filled in each time
    (rplaca (cdr result) x)     ; the function is called
    result))

This function does in fact do what its documentation claims, but a problem arises when it is called more than once,

(setq x (bogus-function 'foo))
    ⇒ (nil foo)
(setq y (bogus-function 'bar))
    ⇒ (nil bar)               ;The first result has been destroyed
x
    ⇒ (nil bar)               ;See!

This example is totally contrived — no one would ever write a function like the one in the example but it nicely demonstrates the need for a dynamic method of creating lists.

Function: list &rest elements

This function creates a list out of its arguments, if zero arguments are given the empty list, nil, is returned.

(list 1 2 3)
    ⇒ (1 2 3)

(list (major-version-number) (minor-version-number))
    ⇒ (3 2)

(list)
    ⇒ nil               ;Equivalent to `()'
Function: make-list length &optional initial-value

This function creates a list length elements long. If the initial-value argument is given it defines the value of all elements in the list, if it is not given they are all nil.

(make-list 2)
    ⇒ (nil nil)

(make-list 3 t)
    ⇒ (t t t)

(make-list 0)
    ⇒ nil
Function: append &rest lists

This function creates a new list with the elements of each of its arguments (which must be lists). Unlike the function nconc this function preserves all of its arguments.

(append '(1 2 3) '(4 5))
    ⇒ (1 2 3 4 5)

(append)
    ⇒ nil

What actually happens is that all arguments but the last are copied then the last argument is linked on to the end of the list (uncopied).

(setq foo '(1 2))
    ⇒ (1 2)
(setq bar '(3 4))
    ⇒ (3 4)
(setq baz (append foo bar))
    ⇒ (1 2 3 4)
(eq (nthcdr 2 baz) bar)
    ⇒ t

The following diagram shows the final state of the three variables more clearly,

foo--> +-----+-----+   +-----+-----+
       |  o  |  o----> |  o  |     |
       +--|--+-----+   +--|--+-----+
          |               |
          o--> 1          o--> 2   bar
          |               |          ->
baz--> +--|--+-----+   +--|--+-----+   +-----+-----+   +-----+-----+
       |  o  |  o----> |  o  |  o----> |  o  |  o----> |  o  |     |
       +-----+-----+   +-----+-----+   +--|--+-----+   +--|--+-----+
                                          |               |
                                           --> 3           --> 4

Note how foo and the first half of baz use the same objects for their elements — copying a list only copies its cons cells, its elements are reused. Also note how the variable bar actually references the mid-point of baz since the last list in an append call is not copied.

Function: reverse list

This function returns a new list; it is made from the elements of the list list in reverse order. Note that this function does not alter its argument.

(reverse '(1 2 3 4))
    ⇒ (4 3 2 1)

As a postscript to this section, the function used as an example at the beginning could now be written as,

(defun not-so-bogus-function (x)
  (list nil x))

Also note that the cons function can be used to create lists by hand and to add new elements onto the front of a list.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.2.3 Accessing List Elements

The most powerful method of accessing an element in a list is via a combination of the car and cdr functions. There are other functions which provide an easier way to get at the elements in a flat list. These will usually be faster than a string of car and cdr operations.

Function: nth count list

This function returns the element count elements down the list, therefore to access the first element use a count of zero (or even better the car function). If there are too few elements in the list and no element number count can be found nil is returned.

(nth 3 '(0 1 2 3 4 5))
    ⇒ 3

(nth 0 '(foo bar)
    ⇒ foo
Function: nthcdr count list

This function takes the cdr of the list list count times, returning the last cdr taken.

(nthcdr 3 '(0 1 2 3 4 5))
    ⇒ (3 4 5)

(nthcdr 0 '(foo bar))
    ⇒ (foo bar)
Function: last list

This function returns the last element in the list list. If the list has zero elements nil is returned.

(last '(1 2 3))
    ⇒ 3

(last '())
    ⇒ nil
Function: member object list

This function scans through the list list until it finds an element which is equal to object. The tail of the list (the cons cell whose car is the matched object) is then returned. If no elements match object then the empty list nil is returned.

(member 'c '(a b c d e))
    ⇒ (c d e)

(member 20 '(1 2))
    ⇒ nil
Function: memq object list

This function is similar to member except that comparisons are performed by the eq function not equal.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.2.4 Modifying Lists

The nthcdr function can be used in conjunction with the rplaca function to modify an arbitrary element in a list. For example,

(rplaca (nthcdr 2 '(0 1 2 3 4 5)) 'foo)
    ⇒ foo

sets the third element of the list (0 1 2 3 4 5) to the symbol called foo.

There are also functions which modify the structure of a whole list. These are called destructive operations because they modify the actual structure of a list — no copy is made. This can lead to unpleasant side effects if care is not taken.

Function: nconc &rest lists

This function is the destructive equivalent of the function append, it modifies its arguments so that it can return a list which is the concatenation of the elements in its arguments lists.

Like all the destructive functions this means that the lists given as arguments are modified (specifically, the cdr of their last cons cell is made to point to the next list). This can be seen with the following example (similar to the example in the append documentation).

(setq foo '(1 2))
    ⇒ (1 2)
(setq bar '(3 4))
    ⇒ (3 4)
(setq baz (nconc foo bar))
    ⇒ (1 2 3 4)
foo
    ⇒ (1 2 3 4)                ;`foo' has been altered!
(eq (nthcdr 2 baz) bar)
    ⇒ t

The following diagram shows the final state of the three variables more clearly,

foo-->                           bar-->
baz--> +-----+-----+   +-----+-----+   +-----+-----+   +-----+-----+
       |  o  |  o----> |  o  |  o----> |  o  |  o----> |  o  |     |
       +--|--+-----+   +--|--+-----+   +--|--+-----+   +--|--+-----+
          |               |               |               |
           --> 1           --> 2             --> 3           --> 4
Function: nreverse list

This function rearranges the cons cells constituting the list list so that the elements are in the reverse order to what they were.

(setq foo '(1 2 3))
    ⇒ (1 2 3)
(nreverse foo)
    ⇒ (3 2 1)
foo
    ⇒ (1)                      ;`foo' wasn't updated when the list
                                ; was altered.
Function: delete object list

This function destructively removes all elements of the list list which are equal to object then returns the modified list.

(delete t '(nil t nil t nil))
    ⇒ (nil nil nil)

When this function is used to remove an element from a list which is stored in a variable that variable must be set to the return value of the delete function. Otherwise, if the first element of the list has to be deleted (because it is equal to object) the value of the variable will not change.

(setq foo '(1 2 3))
    ⇒ (1 2 3)
(delete 1 foo)
    ⇒ (2 3)
foo
    ⇒ (1 2 3)
(setq foo (delete 1 foo))
    ⇒ (2 3)
Function: delq object list

This function is similar to the delete function, the only difference is that the eq function is used to compare object with each of the elements in list, instead of the equal function which is used by delete.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.2.5 Association Lists

An association list (or alist) is a list mapping key values to to other values. Each element of the alist is a cons cell, the car of which is the key, the cdr is the value that it associates to. For example an alist could look like,

((fred . 20)
 (bill . 30))

this alist has two keys, fred and bill which both associate to an integer (20 and 30 respectively).

It is possible to make the associated values lists, this looks like,

((fred 20 male)
 (bill 30 male)
 (sue  25 female))

in this alist the symbol fred is associated with the list (20 male).

There are a number of functions which let you interrogate an alist with a given key for its association.

Function: assoc key alist

This function scans the association list alist for the first element whose car is equal to key, this element is then returned. If no match of key is found nil is returned.

(assoc 'two '((one . 1) (two . 2) (three . 3)))
    ⇒ (two . 2)
Function: assq key alist

Similar to the function assoc except that the function eq is used to compare elements instead of equal.

It is not usually wise to use assq when the keys of the alist may not be symbols — eq won’t think two objects are equivalent unless they are the same object!

(assq "foo" '(("bar" . 1) ("foo" . 2)))
    ⇒ nil
(assoc "foo" '(("bar" . 1) ("foo" . 2)))
    ⇒ ("foo" . 2)
Function: rassoc association alist

This function searches through alist until it finds an element whose cdr is equal to association, that element is then returned. nil will be returned if no elements match.

(rassoc 2 '((one . 1) (two . 2) (three . 3)))
    ⇒ (two . 2)
Function: rassq association alist

This function is equivalent to rassoc except that it uses eq to make comparisons.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.2.6 Infinite Lists

Sometimes it is useful to be able to create ‘infinite’ lists — that is, lists which appear to have no last element — this can easily be done in Lisp by linking the cdr of the last cons cell in the list structure back to the beginning of the list.

 ----------------------------------- 
|                                   |
 --> +-----+-----+   +-----+-----+  |
     |  o  |  o----> |  o  |  o----- 
     +--|--+-----+   +--|--+-----+
        |               |
         --> 1           --> 2

The diagram above represents the infinite list (1 2 1 2 1 2 …).

Infinite lists have a major drawback though, many of the standard list manipulation functions can not be used on them. These functions work by moving through the list until they reach the end. If the list has no end the function may never terminate and the only option is to send Jade an interrupt signal (@pxref{Interrupting Jade}).

The only functions which may be used on circular lists are: the cons cell primitives (cons, car, cdr, rplaca, rplacd), nth and nthcdr.

Also note that infinite lists can’t be printed.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.3 Vectors

A vector is a fixed-size sequence of Lisp objects, each element may be accessed in constant time — unlike lists where the time taken to access an element is proportional to the position of the element.

The read syntax of a vector is an opening square bracket, followed by zero or more space-separated objects, followed by a closing square bracket. For example,

[zero one two three]

In general it is best to use vectors when the number of elements to be stored is known and lists when the sequence must be more dynamic.

Function: vectorp object

This function returns t if its argument, object, is a vector.

Function: vector &rest elements

This function creates a new vector containing the arguments given to the function.

(vector 1 2 3)
    ⇒ [1 2 3]

(vector)
    ⇒ []
Function: make-vector size &optional initial-value

Returns a new vector, size elements big. If initial-value is defined each element of the new vector is set to initial-value, otherwise they are all nil.

(make-vector 4)
    ⇒ [nil nil nil nil]

(make-vector 2 t)
    ⇒ [t t]

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.4 Strings

A string is a vector of characters (see section Characters), they are generally used for storing and manipulating pieces of text. Jade puts no restrictions on the values which may be stored in a string — specifically, the null character (‘^@’) may be stored with no problems.

The read syntax of a string is a double quote character, followed by the contents of the string, the object is terminated by a second double quote character. For example, "abc" is the read syntax of the string ‘abc’.

Any backslash characters in the string’s read syntax introduce an escape sequence; one or more of the following characters are treated specially to produce the next actual character in the string.

The following escape sequences are supported (all are shown without their leading backslash ‘\’ character).

n

A newline character.

r

A carriage return character.

f

A form feed character.

t

A TAB character.

a

A ‘bell’ character (this is Ctrl-g).

^c

The ‘control’ code of the character c. This is calculated by toggling the seventh bit of the upper-case version of c.

For example,

\^C             ;A Ctrl-c character (ASCII value 3)
\^@            ;The NUL character (ASCII value 0)
012

The character whose ASCII value is the octal value ‘012’. After the backslash character the Lisp reader reads up to three octal digits and combines them into one character.

x12

The character whose ASCII value is the hexadecimal value ‘12’, i.e. an ‘x’ character followed by one or two hex digits.

Function: stringp object

This function returns t if its argument is a string.

Function: make-string length &optional initial-character

Creates a new string containing length characters, each character is initialised to initial-character (or to spaces if initial-character is not defined).

(make-string 3)
    ⇒ "   "

(make-string 2 ?$)
    ⇒ "$$"
Function: concat &rest args

This function concatenates all of its arguments, args, into a single string which is returned. If no arguments are given then the null string (‘’) results.

Each of the args may be a string, a character or a list or vector of characters. Characters are stored in strings modulo 256.

(concat "foo" "bar")
    ⇒ "foobar"

(concat "a" ?b)
    ⇒ "ab"

(concat "foo" [?b ?a ?r])
    ⇒ "foobar"

(concat)
    ⇒ ""
Function: substring string start &optional end

This function creates a new string which is a partial copy of the string string. The first character copied is start characters from the beginning of the string. If the end argument is defined it is the index of the character to stop copying at, if it is not defined all characters until the end of the string are copied.

(substring "xxyfoozwx" 3 6)
    ⇒ "foo"

(substring "xyzfoobar" 3)
    ⇒ "foobar"
Function: string= string1 string2

This function compares the two strings string1 and string2 — if they are made from the same characters in the same order then t is returned, else nil.

(string= "one" "one")
    ⇒ t

(string= "one" "two")
    ⇒ nil

Note that an alternate way to compare strings (or anything!) is to use the equal function.

Function: string< string1 string2

This function returns t if string1 is ‘less’ than string2. This is determined by comparing the two strings a character at a time, the first pair of characters which do not match each other are then compared with a normal ‘less-than’ function.

In Jade the standard < function understands strings so string< is just a macro calling that function.

(string< "abc" "abd")
    ⇒ t

(string< "abc" "abb")
    ⇒ nil

Functions are also available which match regular expressions with strings (see section Searching and Matching Functions) and which apply a mapping to each character in a string (see section Translation Functions).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.5 Array Functions

Function: arrayp object

This function returns t if object is an array.

Function: aref array position

Returns the element of the array (vector or string) array position elements from the first element (i.e. the first element is numbered zero). If no element exists at position in array, nil is returned.

(aref [0 1 2 3] 2)
    ⇒ 2

(aref "abcdef" 3)
    ⇒ 100                      ;`d'
Function: aset array position value

This function sets the element of the array array with an index of position (counting from zero) to value. An error is signalled if element position does not exist. The result of the function is value.

(setq x [0 1 2 3])
    ⇒ [0 1 2 3]
(aset x 2 'foo)
    ⇒ foo
x
    ⇒ [0 1 foo 3]

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7.6 Sequence Functions

Function: length sequence

This function returns the length (an integer) of the sequence sequence.

(length "abc")
    ⇒ 3

(length '(1 2 3 4))
    ⇒ 4

(length [x y])
    ⇒ 2
Function: copy-sequence sequence

Returns a new copy of the sequence sequence. Where possible (in lists and vectors) only the ‘structure’ of the sequence is newly allocated: the same objects are used for the elements in both sequences.

(copy-sequence "xy")
    ⇒ "xy"

(setq x '("one" "two"))
    ⇒ ("one" "two")
(setq y (copy-sequence x))
    ⇒ ("one" "two")
(eq x y)
    ⇒ nil
(eq (car x) (car y))
    ⇒ t
Function: elt sequence position

This function returns the element of sequence position elements from the beginning of the sequence.

This function is a combination of the nth and aref functions.

(elt [0 1 2 3] 1)
    ⇒ 1

(elt '(foo bar) 0)
    ⇒ foo

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8 Symbols

Symbols are objects with a name (usually a unique name), they are one of the most important data structures in Lisp since they are used to provided named variables (see section Variables) and functions (see section Functions).

Function: symbolp object

This function returns t when its argument is a symbol.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8.1 Symbol Syntax

The read syntax of a symbol is simply its name; if the name contains any meta-characters (whitespace or any from ‘()[]'";|’) they will have to be entered specially. There are two ways to tell the reader that a meta-character is actually part of the symbol’s name:

  1. Precede the meta-character by a backslash character (‘\’), for example:
    xy\(z\)                 ;the symbol whose name is ‘xy(z)
  2. Enclose part of the name in vertical lines (two ‘|’ characters). All characters after the starting vertical line are copied as-is until the closing vertical line is encountered. For example:
    xy|(z)|                 ;the symbol ‘xy(z)

Here are some example read syntaxes.

setq                    ; ‘setq’
|setq|                  ; ‘setq’
\s\e\t\q                ; ‘setq’
1                       ; the number 1
\1                      ; the symbol1’
|!$%zf78&|              ; ‘!$%zf78&’
foo|(bar)|              ; ‘foo(bar)’
foo\(bar\)              ; ‘foo(bar)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8.2 Symbol Attributes

All symbols have four basic attributes, most important is the print name of the symbol. This is a string containing the name of the symbol, after it has been defined (when the symbol is first created) it may not be changed.

Function: symbol-name symbol

This function returns the print name of the symbol symbol.

(symbol-name 'unwind-protect)
    ⇒ "unwind-protect"

Each symbol also has a value cell storing the value of this symbol when it is referenced as a variable. Usually this cell is accessed implicitly by evaluating a variable form but it can also be read via the symbol-value function(1) (see section Variables).

Similar to the value cell each symbol also has a function cell which contains the function definition of the symbol (see section Named Functions). The symbol-function function can be used to read this cell and the fset function to set it.

Lastly, there is the symbol’s property list, this is similar to an alist (see section Association Lists) and provides a method of storing arbitrary extra values in each symbol. See section Property Lists.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8.3 Obarrays

An obarray is the structure used to ensure that no two symbols have the same name and to provide quick access to a symbol given its name. An obarray is basically a vector (with a slight wrinkle), each element of the vector is a chain of symbols which share the same hash-value (a bucket). These symbols are chained together through links which are invisible to Lisp programs: if you examine an obarray you will see that each bucket looks as though it has at most one symbol stored in it.

The normal way to reference a symbol is simply to type its name in the program, when the Lisp reader encounters a name of a symbol it looks in the default obarray for a symbol of that name. If the named symbol doesn’t exist it is created and hashed into the obarray — this process is known as interning the symbol, for more details see Interning.

Variable: obarray

This variable contains the obarray that the read function uses when interning symbols. If you change this I hope you know what you’re doing.

Function: make-obarray size

This function creates a new obarray with size hash buckets (this should be a prime number for best results).

This is the only correct way of making an obarray.

Function: find-symbol symbol-name &optional obarray

This function scans the specified obarray (obarray or the value of the variable obarray if obarray is undefined) for a symbol whose name is the string symbol-name. The value returned is the symbol if it can be found or nil otherwise.

(find-symbol "setq")
    ⇒ setq
Function: apropos regexp &optional predicate obarray

Returns a list of symbols from the obarray obarray (or the default) whose print name matches the regular expression regexp. If predicate is defined and not nil, each symbol which matches regexp is applied to the function predicate, if the value is t it is considered a match.

The predicate argument is useful for restricting matches to a certain type of symbol, for example only commands.

(apropos "^yank" 'commandp)
    ⇒ (yank-rectangle yank yank-to-mouse)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8.4 Creating Symbols

It is possible to allocate symbols dynamically, this is normally only necessary when the symbol is to be interned in the non-default obarray or the symbol is a temporary object which should not be interned (for example: labels in a compiler?).

Function: make-symbol print-name

This function creates and returns a new, uninterned, symbol whose print name is the string print-name. Its variable and function value cells are void and it will have an empty property list.

(make-symbol "foo")
    ⇒ foo
Function: gensym

This function returns a new, uninterned, symbol which has a unique print name.

(gensym)
    ⇒ G0001

(gensym)
    ⇒ G0002

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8.5 Interning

Interning a symbol means to store it in an obarray so that it can be found in the future: all variables and named-functions are stored in interned symbols.

When a symbol is interned a hash function is applied to its print name to determine which bucket in the obarray it should be stored in. Then it is simply pushed onto the front of that bucket’s chain of symbols.

Normally all interning is done automatically by the Lisp reader. When it encounters the name of a symbol which it can’t find in the default obarray (the value of the variable obarray) it creates a new symbol of that name and interns it. This means that no two symbols can have the same print name, and that the read syntax of a particular symbol always produces the same object (unless the value of obarray is altered).

(eq 'some-symbol 'some-symbol)
    ⇒ t
Function: intern symbol-name &optional obarray

This function uses find-symbol to search the obarray (or the standard obarray) for a symbol called symbol-name. If a symbol of that name is found it is returned, otherwise a new symbol of that name is created, interned into the obarray, and returned.

(intern "setq")
    ⇒ setq

(intern "my-symbol" my-obarray)
    ⇒ my-symbol
Function: intern-symbol symbol &optional obarray

Interns the symbol symbol into the obarray obarray (or the standard one) then returns the symbol. If symbol is currently interned in an obarray an error is signalled.

(intern-symbol (make-symbol "foo"))
    ⇒ foo

(intern-symbol 'foo)
    error--> Error: Symbol is already interned, foo
Function: unintern symbol &optional obarray

This function removes the symbol symbol from the obarray obarray then returns the symbol.

Beware! this function must be used with extreme caution — once you unintern a symbol there’s no way to recover it.

(unintern 'setq)                ;This is extremely stupid
    ⇒ setq

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8.6 Property Lists

Each symbol has a property list (or plist), this is a structure which associates an arbitrary Lisp object with a key (usually a symbol). The keys in a plist may not have any duplications (so that each property is only defined once).

The concept of a property list is very similar to an association list (see section Association Lists) but there are two main differences:

  1. Structure; each element of an alist represents one key/association pair. In a plist each pair of elements represents an association: the first is the key, the second the property. For example, where an alist may be,
    ((one . 1) (two . 2) (three . 3))
    

    a property list would be,

    (one 1 two 2 three 3)
    
  2. Plists have their own set of functions to modify the list. This is done destructively, altering the property list (since the plist is stored in only one location, the symbol, this is quite safe).
Function: get symbol property

This function searches the property list of the symbol symbol for a property eq to property. If such a property is found it is returned, else the value nil is returned.

(get 'if 'lisp-indent)
    ⇒ 2

(get 'set 'lisp-indent)
    ⇒ nil
Function: put symbol property new-value

put sets the value of the property property to new-value in the property list of the symbol symbol. If there is an existing value for this property it is overwritten. The value returned is new-value.

(put 'foo 'prop 200)
    ⇒ 200
Function: symbol-plist symbol

Returns the property list of the symbol symbol.

(symbol-plist 'if)
    ⇒ (lisp-indent 2)
Function: setplist symbol plist

This function sets the property list of the symbol symbol to plist.

(setplist 'foo '(zombie yes))
    ⇒ (zombie yes)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9 Evaluation

So far I have only discussed a few of the various data types available and how the Lisp reader can convert textual descriptions of these types into Lisp objects. Obviously there has to be a way of actually computing something — it would be difficult to write a useful program otherwise.

What sets Lisp apart from other languages is that in Lisp there is no difference between programs and data: a Lisp program is just a sequence of Lisp objects which will be interpreted when the program is run.

The subsystem which does this interpreting is called the Lisp evaluator and each expression to be evaluated is called a form. The evaluator (the function eval) examines the structure of the form that is applied to and computes the value of the form within the current environment.

A form can be any type of data object; the only types which the evaluator treats specially are symbols (which stand for variables) and lists, anything else is returned as-is (and is called a self-evaluating form).

Function: eval form

This function computes the value of the form which is its argument, within the current environment. The computed value is then returned. eval is the basic function for interpreting Lisp objects.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9.1 Symbol Forms

When the evaluator is applied to a symbol the computed value of the form is the object stored in the symbol’s variable slot. Basically this means that to get the value of a variable you simply write its name. For example,

buffer-list
    ⇒ (#<buffer *jade*> #<buffer programmer.texi>)

this extract from a Lisp session shows the read syntax of a form to get the value of the variable buffer-list and the result when this form is evaluated.

Since forms are evaluated within the current environment the value of a variable is its newest binding, or in the case of buffer-local variables, its value in the current buffer. See section Variables.

If the value of an evaluated symbol is void an error is signalled.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9.2 List Forms

Forms which are lists are used to call a subroutine. The first element of the list is the subroutine which is to be called; all further elements are arguments to be applied to the subroutine.

There are several different types of subroutines available: functions, macros, special forms and autoloads. When the evaluator finds a form which is a list it tries to classify the form into one of these four types. First of all it looks at the first element of the list, if it is a symbol it gets the value from the function slot of the symbol (note that the first element of a list form is never evaluated itself). This value (either the first element or the symbol’s function value) is enough to classify the form into one of the four types.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9.2.1 Function Call Forms

The first element of a function call form is the name of the function, this can be either a symbol (in which case the symbol’s function value is indirected through to get the real function definition) or a lambda expression (see section Lambda Expressions).

Any other elements of the list are forms to be evaluated (in left to right order) and their values become the arguments to the function. The function is applied to these arguments and the result that it returns becomes the value of the form.

For example, consider the form (/ 100 (1+ 4)). This is a function call to the function /. First the 100 form is evaluated: it returns the value 100, next the form (1+ 4) is evaluated. This is also a function call and computes to a value of 5 which becomes the second argument to the / function. Now the / function is applied to its arguments of 100 and 5 and it returns the value 20 which then becomes the value of the form (/ 100 (1+ 4)).

(/ 100 (1+ 4))
≡ (/ 100 5)
⇒ 20

Or another example,

(+ (- 10 (1- 7)) (* (1+ 2) 4)
≡ (+ (- 10 6) (* (1+ 2) 4)
≡ (+ 4 (* (1+ 2) 4)
≡ (+ 4 (* 3 4))
≡ (+ 4 12)
⇒ 16

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9.2.2 Macro Call Forms

Macros are source code expansions, the general idea is that a macro is a function which using the unevaluated arguments applied to it, computes another form (the expansion of the macro and its arguments) which is then evaluated to provide the value of the form. For more details see Macros.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9.2.3 Special Forms

Special forms are built-in functions which the evaluator knows must be handled specially. The main difference between a special form and a function is that the arguments applied to a special form are not automatically evaluated — if necessary the special form will evaluate arguments itself. This will be noted in the documentation of the special form.

Special forms are generally used to provide control structures, for example, all of the conditional constructs are special forms (if all of their arguments, including the forms to be conditionally evaluated, were evaluated automatically this would defeat the object of being conditional!).

The special forms supported by Jade are: and, catch, cond, defconst, defmacro, defun, defvar, error-protect, function, if, let, let*, or, prog1, prog2, progn, quote, setq, setq-default, unless, unwind-protect, when, while, with-buffer, with-window.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9.2.4 Autoload Forms

Not all modules of Jade are needed at once, autoload forms provide a means of marking that a function (or macro) is contained by a specific file of Lisp code. The first time that the function is accessed the autoload form will be evaluated; this loads the file that the function is contained by then re-evaluates the list form.

By then the autoload form will have been overwritten in the symbol’s function slot by the true function (when it was loaded) so the form will execute properly.

An autoload form is a list whose first element is the symbol autoload, for full details see Autoloading.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9.3 Self-Evaluating Forms

The computed value of any form which is not a symbol or a list will simply be the form itself and the form is said to be a self-evaluating form.

Usually the only forms to be evaluated in this way will be numbers, strings and vectors (since they are the only other data types which have read syntaxes) but the effect is the same for other types of data.

This means that forms you know are self-evaluating do not have to be quoted to be used as constants (like lists and symbols do).

"foo"
    ⇒ "foo"

(eval (current-buffer))
    ⇒ #<buffer programmer.texi>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9.4 Quoting

As the above sections explain some types of Lisp object have special meaning to the Lisp evaluator (namely the symbol and list types) this means that if you want to refer to a symbol or a list in a program you can’t (yet) because the evaluator will treat the form as either a variable reference or a function call respectively.

To get around this Lisp uses something called quoting, the quote special form simply returns its argument, without evaluating it. For example,

(quote my-symbol)
    ⇒ my-symbol

the quote form prevents the my-symbol being treated as a variable — it is effectively ‘hidden’ from the evaluator.

Writing ‘quote’ all the time would be a bit boring so there is a shortcut: the Lisp reader treats any form x preceded by a single quote character (‘'’) as the form (quote x). So the example above would normally be written as,

'my-symbol
    ⇒ my-symbol
Special Form: quote form

This special form returns its single argument without evaluating it. This is used to quote constant objects to prevent them from being evaluated.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10 Control Structures

Control structures are special forms or macros which control which forms get evaluated, when they get evaluated and the number of times to evaluate them. This includes conditional structures, loops, etc…

The simplest control structures are the sequencing structures; they are used to evaluate a list of forms in left to right order.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.1 Sequencing Structures

Each of the special forms in this section simply evaluates its argument forms in left-to-right order. The only difference is the result they return.

The most widely used sequencing special form is progn: it evaluates all its argument forms and returns the computed value of the last one. Many other control structures are said to perform an implicit progn, this means that they call progn with a list of forms.

progn in Lisp is nearly analogous to a begin…end block in Pascal; it is used in much the same places — to allow you to evaluate a sequence of form where only one form was allowed (for example the true clause of an if structure).

Special Form: progn forms…

All of the forms are evaluated sequentially (from left-to-right), the result of the last evaluated form is the return value of this structure. If no arguments are given to progn it returns nil.

(progn 'one (+ 1 1) "three")
    ⇒ "three"

(progn)
    ⇒ nil
Special Form: prog1 first forms…

This special form evaluates its first form then performs an implicit progn on the rest of its arguments. The result of this structure is the computed value of the first form.

(prog1 'one (+ 1 1) "three")
    ⇒ one
Special Form: prog2 first second forms…

This is similar to prog1 except that the evaluated value of its second form is returned.

The first form is evaluated, then its second, then it performs an implicit progn on the remaining arguments.

(prog2 'one (+ 1 1) "three")
    ⇒ 2

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.2 Conditional Structures

Lisp provides a number of conditional constructs, the most complex of which (cond) will take a list of conditions, the first of which is t then has its associated list of forms evaluated. Theoretically this is the only conditional special form necessary — the rest could be implemented as macros.

Special Form: if condition true-form else-forms…

The if construct is the nearest thing in Lisp to the if-then-else construct found in most programming languages.

First the condition form is evaluated, if it returns t (not nil) the true-form is evaluated and its result returned. Otherwise the result of an implicit progn on the else-forms is returned. If there are no else-forms nil is returned.

Note that one of the true-form or the else-forms is completely ignored — it is not evaluated.

(if (special-form-p 'if)
    "`if' is a special form"
  "`if' is not a special form")
    ⇒ "`if' is a special form"
Special Form: when condition true-forms…

condition is evaluated, if it is t the result of an implicit progn on the true-forms is returned, otherwise nil is returned.

(when t
  (message "Pointless")
  'foo)
    ⇒ foo
Special Form: unless condition else-forms…

This special forms first evaluates condition, if its computed value is not nil its value is returned. Otherwise the else-forms are evaluated sequentially, the value of the last is returned.

Special Form: cond clause…

The cond special form is used to choose between an arbitrary number of conditions. Each clause is a list; its car is the condition the list which is the cdr of the clause is the body-forms. This means that each clause looks something like:

(condition body-forms…)

and a whole cond form looks like:

(cond
 (condition-1 body-forms-1…)
 (condition-2 body-forms-2…)
 …)

The condition in each clause is evaluated in sequence (condition-1, then condition-2, …), the first one which evaluates to a non-nil has an implicit progn performed on its body-forms, the value of which is the value returned by the cond form.

If the true condition has no body-forms the value returned by cond is the value of the condition. If none of the clauses has a non-nil condition the value of the cond is nil.

Often you want a default clause; one which has its body-forms to be evaluated if none of the other clauses are true. The way to do this is to add a clause with a condition of t and body-forms of whatever you want the default action to be.

(cond
 ((stringp buffer-list))        ;Clause with no body-forms
 ((consp buffer-list)
  (setq x buffer-list)          ;Two body-forms
  t)
 (t                             ;Default clause
  (error "`buffer-list' is corrupted!")))
    ⇒ t

All of the other conditionals can be written in terms of cond,

(if c t e…) ≡ (cond (c t) (t e…))

(when c t…) ≡ (cond (c t…))

(unless c e…) ≡ (cond (e) (t e…))

There are also a number of special forms which combine conditions together by the normal logical rules.

Special Form: or forms…

The first of the forms is evaluated, if it is non-nil its value becomes the value of the or form and no more of forms are evaluated. Otherwise this step is repeated for the next member of forms.

If all of the forms have been evaluated and none have a non-nil value nil becomes the value of the or form.

If there are no forms nil is returned.

(or nil 1 nil (beep))           ;(beep) won't be evaluated
    ⇒ 1
Special Form: and forms…

The first of the forms is evaluated. If it is nil no more of the forms are evaluated and nil becomes the value of the and structure. Otherwise the next member of forms is evaluated and its value tested. If none of the forms are nil the computed value of the last member of forms becomes the value of the and form.

(and 1 2 nil (beep))            ;(beep) won't be evaluated
    ⇒ nil

(and 1 2 3)                     ;All forms are evaluated
    ⇒ 3
Function: not object

This function inverts the boolean value of its argument. If object is non-nil, nil is returned, otherwise t is returned.

(not nil)
    ⇒ t

(not t)
    ⇒ nil

(not 42)
    ⇒ nil

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.3 Looping Structures

Jade’s version of Lisp has only one structure for looping — a while loop similar to those found in most programming languages.

Special Form: while condition body-forms…

The condition form is evaluated. If it is non-nil an implicit progn is performed on the body-forms and the whole thing is repeated again.

This continues until the condition form evaluates to nil. The value of any while structure is nil.

while can be recursively defined in terms of when:

(while c b …)
≡
(when c (progn b … (while c b …)))
;; Step through a list x
(while x
  ;; Do something with the current element, (car x)
  (setq x (cdr x)))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.4 Non-Local Exits

A non-local exit is a transfer of control from the current point of evaluation to a different point (somewhat similar to the much-maligned goto statement in some imperative languages).

Non-local exits can either be used explicitly (catch and throw) or implicitly (errors).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.4.1 Catch and Throw

The catch and throw structures are used to perform explicit transfers of control. First a catch form is used to setup a tag, this acts like a label for the C language’s goto statement. To transfer control a throw form is then used to transfer to the named tag. The tag is destroyed and the catch form exits with the value provided by the throw.

In a program this looks like,

(catch 'tag
  ;; Forms which may `throw' back to tag
  …
  (throw 'tag value)
  ;; Control has now passed to the `catch',
  ;; no more forms in this progn will be evaluated.
  …)
    ⇒ value

where tag is the tag to be used (this is normally a symbol) and value is the result of the catch form.

When a throw actually happens all catches in scope are searched for one with a tag which is eq to the tag in the throw. If more than one exists the most-recent is chosen. Now that the catch has been located the environment is ‘wound-back’ to the catch’s position (i.e. local variables are unbound, cleanup forms removed, unused catches forgotten, etc…) and all Lisp constructs between the current point of control and the catch are exited.

For example,

(let
    ((test 'outer))
  (cons (catch 'foo
          (let
              ((test 'inner))
            (throw 'foo test)
            (setq test 'unreachable)))  ;Never reached
        test))
    ⇒ (inner . outer)

when the throw executes the second binding of test is unwound and the first binding comes back into effect. For more details on variable binding see Local Variables.

Note that catch tags are dynamically scoped, the thrower does not have to be within the same lexical scope (this means you can throw through functions).

Special Form: catch tag body-forms…

This special form defines a catch tag which will be accessible while the body-forms are being evaluated.

tag is evaluated and recorded as the tag for this catch. Next the body-forms are evaluated as an implicit progn. The value of the catch form is either the value of the progn, or, if a throw happened, the value specified in the throw form.

Before exiting the tag installed by this form is removed.

Function: throw tag &optional catch-value

This function transfers the point of control to the catch form with a tag which is eq to tag. The value returned by this catch form is either catch-value or nil if catch-value is undefined.

If there is no catch with a tag of tag an error is signalled and the editor returns to the top-level of evaluation.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.4.2 Function Exits

It is often useful to be able to immediately return control from a function definition (like the C return statement). Jade’s version of Lisp has the return function for this.

Function: return &optional value

This function transfers control out of the most-recent lambda-expression (i.e. a function or macro definition) so that the result of the lambda- expression is value.

(funcall '(lambda () (return 'x) 'y))
    ⇒ x

The 'y form is never evaluated since control is passed straight from the (return 'y) form back to the funcall form.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.4.3 Cleanup Forms

It is sometimes necessary to be sure that a certain form is always evaluated, even when a non-local exit would normally bypass that form. The unwind-protect special form is used to stop this happening.

Special Form: unwind-protect body-form cleanup-forms…

The body-form is evaluated, if it exits normally the cleanup-forms are evaluated sequentially then the value which the body-form returned becomes the value of the unwind-protect form. If the body-form exits abnormally though (i.e. a non-local exit happened) the cleanup-forms are evaluated anyway and the non-local exit continues.

One use of this is to ensure that an opened file is always closed, for example,

(catch 'foo
  (unwind-protect
      (let
          ((temporary-file (open (tmp-file-name) "w")))
        ;; Use temporary-file
        (write temporary-file "A test\n")
        ;; Now force a non-local exit
        (throw 'foo))
    ;; This is the cleanup-form it will always
    ;; be evaluated no matter what happens.
    (close temporary-file)))
    ⇒ nil

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.4.4 Errors

Errors are a type of non-local exit; when a form can not be evaluated properly an error is normally signalled. If an error-handler has been installed for that type of error control is unwound back to the handler and evaluation continues. If there is no suitable handler control is passed back to the event loop of the most-recent recursive edit and a suitable error message is printed.

Function: signal error-symbol data

Signals that an error has happened. error-symbol is a symbol classifying the type of error, it should have a property error-message (a string) which is the error message to be printed.

data is a list of objects which are relevant to the error — they will be made available to any error-handler or printed with the error message otherwise.

(signal 'void-value '(some-symbol))
    error--> Value as variable is void: some-symbol
Variable: debug-on-error

This variable is consulted by the function signal. If its value is either t or a list containing the error-symbol to signal as one of its elements, the Lisp debugger is entered. When the debugger exits the error is signalled as normal.

When you expect an error to occur and need to be able to regain control afterwards the error-protect form can be used.

Special Form: error-protect body-form error-handlers…

error-protect evaluates the body-form with error handlers in place.

Each of the error-handlers is a list whose car is a symbol defining the type of error which this handler catches. The cdr of the list is a list of forms to be evaluated sequentially when the handler is invoked.

While the forms of the error handler are being evaluated the variable error-info is bound to the value (error-symbol . data) (these were the arguments to the signal form which caused the error).

The special value, the symbol error, in the car of one of the error-handlers will catch all types of errors.

(error-protect
    (signal 'file-error '("File not found" "/tmp/foo"))
  (file-error
   error-info)
  (error
   (setq x z)))         ;Default handler
    ⇒ (file-error "File not found" "/tmp/foo")

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.11 Variables

In Lisp symbols are used to represent variables. Each symbol contains a slot which is used to contain the value of the symbol when it is used as a symbol.

The normal way to obtain the current value of a variable is simply to evaluate the symbol it lives in (i.e. write the name of the variable in your program).

Function: symbol-value variable

This function returns the value of the symbol variable in the current environment.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.11.1 Local Variables

A local variable is a variable which has a temporary value while a program is executing, for example, when a function is called the variables which are the names of its arguments are temporarily bound (a binding is a particular instance of a local variable) to the values of the arguments passed to the function. When the function call exits its arguments are unbound and the previous definitions of the variables come back into view.

Even if a variable has more than one binding still ‘active’ only the most recent is visible — there is absolutely no way the previous bindings can be accessed until the bindings are unbound one-by-one.

A nice way of visualising variable binding is to think of each variable as a stack. When the variable is bound to, a new value is pushed onto the stack, when it is unbound the top of the stack is popped. Similarly when the stack is empty the value of the variable is void (see section Void Variables). Assigning a value to the variable (see section Setting Variables) overwrites the top value on the stack with a new value. When the value of the variable is required it is simply read from the top of the stack.

Apart from function calls there are two special forms which perform variable binding (i.e. creating local variables), let and let*.

Special Form: let bindings body-forms…

let creates new variable bindings as specified by the bindings argument then evaluates the body-forms in order. The variables are then unbound to their state before this let form and the value of the implicit progn of the body-forms becomes the value of the let form.

The bindings argument is a list of the bindings to perform. Each binding is either a symbol, in which case that variable is bound to nil, or a list whose car is a symbol. The cdr of this list is a list of forms which, when evaluated, give the value to bind the variable to.

(setq foo 42)
    ⇒ 42
(let
    ((foo (+ 1 2))
     bar)
  ;; Body forms
  (setq foo (1+ foo))   ;This sets the new binding
  (cons foo bar))
    ⇒ (4 . nil)
foo
    ⇒ 42        ;The original values is back

Note that no variables are bound until all the new values have been computed (unlike in let*). For example,

(setq foo 42)
    ⇒ 42
(let
    ((foo 100)
     (bar foo))
  (cons foo bar))
    ⇒ (100 . 42)

Although foo is given a new binding this is not actually done until all the new bindings have been computed, hence bar is bound to the old value of foo.

Special Form: let* bindings body-forms…

This special form is exactly the same as let except for one important difference: the new bindings are installed as they are computed.

You can see the difference by comparing the following example with the last example in the let documentation (above),

(setq foo 42)
    ⇒ 42
(let*                   ;Using let* this time
    ((foo 100)
     (bar foo))
  (cons foo bar))
    ⇒ (100 . 100)

By the time the binding of bar is computed the new binding of foo has already been installed.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.11.2 Setting Variables

Setting a variable means to overwrite its current value (that is, the value of its most recent binding) with a new one. The old value is irretrievably lost (unlike when a new value is bound to a variable, see section Local Variables).

Special Form: setq variable form …

The special form setq is the usual method of altering the value of a variable. Each variable is set to the result of evaluating its corresponding form. The last value assigned becomes the value of the setq form.

(setq x 20 y (+ 2 3))
    ⇒ 5

In the above example the variable x is set to 20 and y is set to the value of the form (+ 2 3) (5).

When the variable is marked as being buffer-local (see section Buffer-Local Variables) the current buffer’s instance of the variable is set.

Function: set variable new-value

The value of the variable variable (a symbol) is set to new-value and the new-value is returned.

This function is used when the variable is unknown until run-time, and therefore has to be computed from a form.

(set 'foo 20)
≡
(setq foo 20)           ;setq means `set-quoted'
    ⇒ 20

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.11.3 Scope and Extent

In Jade’s version of Lisp all variables have indefinite scope and dynamic extent. What this means is that references to variables may occur anywhere in a program (i.e. bindings established in one function are not only accessible within that function, that’s lexical scope) and that references may occur at any point in the time between the binding being created and it being unbound.

The combination of indefinite scope and dynamic extent is often termed dynamic scope.

As an aside, Lisp objects have indefinite extent, meaning that the object will exist for as long as there is a possibility of it being referenced (and possibly longer — until the garbage collector runs).

Note that in Common Lisp only those variables declared ‘special’ have indefinite scope and dynamic extent.

Try not to abuse the dynamic scoping, although it is often very useful to be able to bind a variable in one function and use it in another this can be confusing if not controlled and documented properly.

A quick example of the use of dynamic scope,

(defun foo (x)
  (let
      ((foo-var (* x 20)))
    (bar x)
    …

(defun bar (y)
  ;; Since this function is called from
  ;; the function foo it can refer
  ;; to any bindings which foo can.
  (setq y (+ y foo-var))
  …

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.11.4 Buffer-Local Variables

It is often very useful to be able to give variables different values for different editor buffers — most major modes need to record some buffer-specific information. Jade allows you to do this by giving a variable buffer-local bindings.

There are two strengths of buffer-local variables: you can either give a variable a buffer-local value in a single buffer, with other buffers treating the variable as normal, or a variable can be marked as being automatically buffer-local, each time the variable is set the current buffer’s value of the variable is updated.

Each buffer maintains an alist of the symbols which have buffer-local values in the buffer and the actual values themselves, this alist may be read with the buffer-variables function.

When the value of a variable is referenced (via the symbol-value function) the current buffer’s alist of local values is examined for a binding of the variable being referenced; if one is found that is the value of the variable, otherwise the default value (the value stored in the symbol’s value cell) is used.

Setting a variable also searches for a buffer-local binding; if one exists its value is modified, not the default value. If the variable has previously been marked as being automatically buffer-local (by make-variable-buffer-local) a buffer-local binding is automatically created if one doesn’t already exist.

Currently there is one main problem with buffer-local variables: they can’t have temporary values bound to them (or rather, they can but I guarantee it won’t work how you expect), so for the time being, don’t try to bind local values (with let or let*) to a buffer-local variable.

Function: make-local-variable symbol

This function gives the variable symbol a buffer-local binding in the current buffer. The value of this binding will be the same as the variable’s default value.

If symbol already has a buffer-local value in this buffer nothing happens.

Returns symbol.

Function: make-variable-buffer-local symbol

This function marks the variable symbol as being automatically buffer-local.

This means that any attempts at setting the value of symbol will actually set the current buffer’s local value (if necessary a new buffer-local binding will be created in the buffer).

Returns symbol.

(make-variable-buffer-local 'buffer-modtime)
    ⇒ buffer-modtime
Function: default-value symbol

This function returns the default value of the variable symbol.

(setq foo 'default)
    ⇒ default
(make-local-variable 'foo)      ;Create a value in this buffer
    ⇒ foo
(setq foo 'local)
    ⇒ local
foo
    ⇒ local
(symbol-value 'foo)
    ⇒ local
(default-value 'foo)
    ⇒ default
Function: default-boundp symbol

Returns t if the variable symbol has a non-void default value.

Special Form: setq-default symbol form …

Similar to the setq special form except that the default value of each variable is set. In non-buffer-local symbols there is no difference between setq and setq-default.

Function: set-default symbol new-value

Sets the default value of the variable symbol to new-value, then returns new-value.

Function: kill-local-variable symbol

This function removes the buffer-local binding of the variable symbol from the current buffer (if one exists) then returns symbol.

Function: kill-all-local-variables

This function removes all the buffer-local bindings associated with the current buffer. Subsequently, any buffer-local variables referenced while this buffer is current will use their default values.

The usual way to define an automatically buffer-local variable is to use defvar and make-variable-buffer-local, for example,

(defvar my-local-variable default-value
  "Doc string for my-local-variable.")
(make-variable-buffer-local 'my-local-variable)

Note that if you want to reference the value of a buffer-local variable in a buffer other than the current buffer, use the with-buffer special form (see section The Current Buffer). For example, the form,

(with-buffer other-buffer some-variable)

will produce the value of the variable some-variable in the buffer other-buffer.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.11.5 Void Variables

A variable which has no value is said to be void, attempting to reference the value of such a symbol will result in an error. It is possible for the most recent binding of a variable to be void even though the inactive bindings may have values.

Function: boundp variable

Returns t if the symbol variable has a value, nil if its value is void.

Function: makunbound variable

This function makes the current binding of the symbol variable be void, then returns variable.

(setq foo 42)
    ⇒ 42
foo
    ⇒ 42
(boundp 'foo)
    ⇒ t
(makunbound 'foo)
    ⇒ foo
(boundp 'foo)
    ⇒ nil
foo
    error--> Value as variable is void: foo

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.11.6 Constant Variables

In Lisp constants are represented by variables which have been marked as being read-only. Any attempt to alter the value of a constant results in an error.

Two of the most commonly used constants are nil and t.

Function: set-const-variable variable &optional read-write

This function defines whether or not the value of the symbol variable may be modified. If read-write is nil or undefined the variable is marked to be constant, otherwise it’s marked to be a normal variable. The value returned is variable.

Function: const-variable-p variable

Returns t if the value of the symbol variable may be altered, nil otherwise.

Constants may behave a bit strangely when you compile the program they are used in: the value of the constant is likely to be hardwired into the compiled functions it is used in, and the constant is unlikely to be eq to itself!

The compiler assumes that constant is always the same, whenever it is evaluated. It may even be evaluated more than once. See section Compiled Lisp.

The special form defconst can be used to define constants, see Defining Variables.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.11.7 Defining Variables

The special forms defvar and defconst allow you to define the global variables which will be used in a program. This is entirely optional; it is highly recommended though.

Special Form: defvar variable form [doc-string]

This special form defines a global variable, the symbol variable. If the value of variable is void the form is evaluated and its value is stored as the value of variable (note that the default value is modified, never a buffer-local value).

If the doc-string argument is defined it is a string documenting variable. This string is then stored as the symbol’s variable-documentation property and can be accessed by the describe-variable function.

(defvar my-variable '(x y)
  "This variable is an example showing the usage of the defvar
special form.")
    ⇒ my-variable
Special Form: defconst constant form [doc-string]

defconst defines a constant, the symbol constant. Its value (in the case of a buffer-local symbol, its default value) is set to the result of evaluating form. Note that unlike defvar the value of the symbol is always set, even if it already has a value.

The doc-string argument, if defined, is the documentation string for the constant.

(defconst the-answer 42
  "An example constant.")
    ⇒ the-answer

See section Constant Variables.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.12 Functions

A function is a Lisp object which, when applied to a sequence of argument values, produces a value — the function’s result. It may also produce side-effects. All Lisp functions return results — there is nothing like a procedure in Pascal.

Functions are the main building-block in Lisp programs, each program is usually a system of inter-related functions.

There are two types of function: primitive functions are functions written in the C language, these are sometimes called built-in functions, the object containing the C code itself is called a subr. All other functions are written in Lisp.

Function: functionp object

Returns t if object is a function (i.e. it can be used as the function argument of funcall.

(functionp 'set)
    ⇒ t

(functionp 'setq)
    ⇒ nil

(functionp #'(lambda (x) (+ x 2)))
   ⇒ t

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.12.1 Lambda Expressions

Lambda expressions are used to create an object of type function from other Lisp objects, it is a list whose first element is the symbol lambda. All functions written in Lisp (as opposed to the primitive functions in C) are represented by a lambda expression.

Note that a lambda expression is not an expression, evaluating a lambda expression will give an error (unless there is a function called lambda).

The format of a lambda expression is:

(lambda lambda-list [doc] [interactive-declaration] body-forms… )

Where lambda-list is the argument specification of the function, doc is an optional documentation string, interactive-declaration is only required by editor commands (see section Commands) and the body-forms is the actual function code (when the function is called each form is evaluated in sequence, the last form’s value is the result returned by the function).

The lambda-list is a list, it defines how the argument values applied to the function are bound to local variables which represent the arguments within the function. At its simplest it is simply a list of symbols, each symbol will have the corresponding argument value bound to it. For example, the lambda list,

(lambda (x y) (+ x y))

takes two arguments, x and y. When this function is called with two arguments the first will be bound to x and the second to y (then the function will return their sum).

To complicate matters there are several lambda-list keywords which modify the meaning of symbols in the lambda-list. Each keyword is a symbol whose name begins with an ampersand, they are:

&optional

All the variables following this keyword are considered optional (all variables before the first keyword are required: an error will be signalled if a required argument is undefined in a function call). If an optional argument is undefined it will simply be given the value nil.

Note that optional arguments must be specified if a later optional argument is also specified. Use nil to explicitly show that an optional argument is undefined.

For example, if a function foo takes two optional arguments and you want to call it with only the second argument defined, the first argument must be specified as nil to ensure that the correct argument value is bound to the correct variable.

(defun foo (&optional arg-1 arg-2)
  …

(foo nil arg-2-value)   ;Leave the first argument undefined
&rest

The &rest keyword allows a variable number of arguments to be applied to a function, all the argument values which have not been bound to argument variables are simply consed into a list and bound to the variable after the &rest keyword. For example, in,

(lambda (x &rest y) …)

the first argument, x, is required. Any other arguments applied to this function are made into a list and this list is bound to the y variable.

When a function represented by a lambda-list is called the first thing that happens is to bind the argument values to the argument variables. The lambda-list and the list of argument values applied to the function are worked through in parallel. Any required arguments which are left undefined when the end of the argument values has been reached causes an error.

After the arguments have been processed the body-forms are evaluated by an implicit progn, the value of which becomes the value of the function call. Finally, all argument variables are unbound and control passes back to the caller.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.12.2 Named Functions

Functions are normally associated with symbols, the name of the symbol being the same as the name of its associated function. Each symbol has a special function cell (this is totally separate from the symbol’s value as a variable — variables and functions may have the same name without any problems occurring) which is used to store the function’s definition, either a lambda expression (see section Lambda Expressions) or a subr (C code) object.

The evaluator knows to indirect through the function value of a symbol in any function call (see section Function Call Forms) so the normal way to call a function is simply write its name as the first element in a list, any arguments making up the other elements in the list. See section List Forms.

The functions and special forms which take functions as their arguments (i.e. funcall) can also take symbols. For example,

(funcall 'message "An example")
≡
(message "An example")
Function: symbol-function symbol

Returns the value of the function cell in the symbol symbol.

(symbol-function 'symbol-function)
    ⇒ #<subr symbol-function>
Function: fboundp symbol

This function returns t if the symbol symbol has a non-void value in its function cell, nil otherwise.

(fboundp 'setq)
    ⇒ t
Function: fset symbol new-value

Sets the value of the function cell in the symbol symbol to new-value, then returns new-value.

This function is rarely used, see Defining Functions.

Function: fmakunbound symbol

This function makes the value of the function cell in symbol void, then returns symbol.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.12.3 Anonymous Functions

When giving function names as arguments to functions it is useful to give an actual function definition (i.e. a lambda expression) instead of the name of a function.

In Lisp, unlike most other programming languages, functions have no inherent name. As seen in the last section named-functions are created by storing a function in a special slot of a symbol, if you want, a function can have many different names: simply store the function in many different symbols!

So, when you want to pass a function as an argument there is the option of just writing down its definition. This is especially useful with functions like mapcar and delete-if. For example, the following form removes all elements from the list which are even and greater than 20.

(setq list (delete-if #'(lambda (x)
                                (and (zerop (% x 2))
                                     (> x 20)))
                            list))

The lambda expression is very simple, it combines two predicates applied to its argument.

Note that the function definition is quoted by #', not the normal '. This is a special shortcut for the function special form (like ' is a shortcut to quote). In general, #'x is expanded by the Lisp reader to (function x).

Special Form: function arg

This special form is nearly identical to the quote form, it always returns its argument without evaluating it. The difference is that the Lisp compiler knows to compile the arg into a byte-code form (unless arg is a symbol in which case it is not compiled).

What this means is when you have to quote a function, use the #' syntax.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.12.4 Predicate Functions

In Lisp, a function which returns a boolean ‘true’ or boolean ‘false’ value is called a predicate. As is the convention in Lisp a value of nil means false, anything else means true. The symbol t is often used to represent a true value (in fact, sometimes the symbol t should be read as any non-nil value).

Another Lisp convention is that the names of predicate functions should be the concept the predicate is testing for and either ‘p’ or ‘-p’.

The ‘p’ variant is used when the concept name does not contain any hyphens.

For example a predicate to test for the concept const-variable (a variable which has a constant value, see section Constant Variables) would be called const-variable-p. On the other hand a predicate to test for the concept buffer (a Lisp object which is a buffer) would be called bufferp.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.12.5 Defining Functions

Named functions are normally defined by the defun special form.

Special Form: defun name lambda-list body-forms…

defun initialises the function definition of the symbol name to the lambda expression resulting from the concatenation of the symbol lambda, lambda-list and the body-forms. So,

(defun foo (x y)
  …
≡
(fset 'foo #'(lambda (x y)
               …

The body-forms may contain a documentation string for the function as its first form and an interactive calling specification as its first (if there is no doc-string) or second form if the function may be called interactively by the user (see section Commands).

An example function definition (actually a command) taken from Jade’s source is,

(defun upcase-word (count)
  "Makes the next COUNT words from the cursor upper-case."
  (interactive "p")
  (let
      ((pos (forward-word count)))
    (upcase-area (cursor-pos) pos)
    (goto-char pos)))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.12.6 Calling Functions

Most of the time function calls are done by the evaluator when it detects a function call form (see section List Forms); when the function to be called is not known until run-time it is easier to use a special function to call the function directly than create a custom form to apply to the eval function.

Function: funcall function &rest args

Applies the argument values args to the function function, then returns its result.

Note that the argument values args are not evaluated again. This also means that funcall can not be used to call macros or special forms — they would need the unevaluated versions of args, which are not available to funcall.

(funcall '+ 1 2 3)
    ⇒ 6
Function: apply function &rest args

Similar to funcall except that the last of its arguments is a list of arguments which are appended to the other members of args to form the list of argument values to apply to the function function.

Constructs a list of arguments to apply to the function function from args.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.12.7 Mapping Functions

A mapping function applies a function to each of a collection of objects. Jade currently has two mapping functions, mapcar and mapc.

Function: mapcar function list

Each element in the list list is individually applied to the function function. The values returned are made into a new list which is returned.

The function should be able to be called with one argument.

(mapcar '1+ '(1 2 3 4 5))
    ⇒ (2 3 4 5 6)
Function: mapc function list

Similar to mapcar except that the values returned when each element is applied to the function function are discarded. The value returned is list.

This function is generally used where the side effects of calling the function are the important thing, not the results.

The two following functions are also mapping functions of a sort. They are variants of the delete function (see section Modifying Lists) and use predicate functions to classify the elements of the list which are to be deleted.

Function: delete-if predicate list

This function is a variant of the delete function. Instead of comparing each element of list with a specified object, each element of list is applied to the predicate function predicate. If it returns t (i.e. not nil) then the element is destructively removed from list.

(delete-if 'stringp '(1 "foo" 2 "bar" 3 "baz"))
    ⇒ (1 2 3)
Function: delete-if-not predicate list

This function does the inverse of delete-if. It applies predicate to each element of list, if it returns nil then the element is destructively removed from the list.

(delete-if-not 'stringp '(1 "foo" 2 "bar" 3 "baz"))
    ⇒ ("foo" "bar" "baz")

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.13 Macros

Macros are used to extend the Lisp language, they are basically a function which instead of returning its value, return a new form which will produce the macro call’s value when evaluated.

When a function being compiled calls a macro the macro is expanded immediately and the resultant form is open-coded into the compiler’s output.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.13.1 Defining Macros

Macros are defined in the same style as functions, the only difference is the name of the special form used to define them.

A macro object is a list whose car is the symbol macro, its cdr is the function which creates the expansion of the macro when applied to the macro calls unevaluated arguments.

Special Form: defmacro name lambda-list body-forms…

Defines the macro stored in the function cell of the symbol name. lambda-list is the lambda-list specifying the arguments to the macro (see section Lambda Expressions) and body-forms are the forms evaluated when the macro is expanded. The first of body-forms may be a documentation string describing the macro’s use.

Here is a simple macro definition, it is a possible definition for the when construct (which might even be useful if when wasn’t already defined as a special form…),

(defmacro when (condition &rest body)
  "Evaluates condition, if it's non-nil evaluates the body
forms."
  (list 'if condition (cons 'progn body)))

When a form of the type (when c b …) is evaluated the macro definition of when expands to the form (if c (progn b …)) which is then evaluated to perform my when-construct.

When you define a macro ensure that the forms which produce the expansion have no side effects; it would fail spectacularly when you attempt to compile your program!


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.13.2 Macro Expansion

When a macro call is detected (see section List Forms) the function which is the cdr of the macro’s definition (see section Defining Macros) is applied to the macro call’s arguments. Unlike in a function call, the arguments are not evaluated, the actual forms are the arguments to the macro’s expansion function. This is so these forms can be rearranged by the macro’s expansion function to create the new form which will be evaluated.

There is a function which performs macro expansion, its main use is to let the Lisp compiler expand macro calls at compile time.

Function: macroexpand form &optional environment

If form is a macro call macroexpand will expand that call by calling the macro’s expansion function (the cdr of the macro definition). If this expansion is another macro call the process is repeated until an expansion is obtained which is not a macro call, this form is then returned.

The optional environment argument is an alist of macro definitions to use as well as the existing macros; this is mainly used for compiling purposes.

(defmacro when (condition &rest body)
  "Evaluates condition, if it's non-nil evaluates the body
forms."
  (list 'if condition (cons 'progn body)))
    ⇒ when

(macroexpand '(when x (setq foo bar)))
    ⇒ (if x (progn (setq foo bar)))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.13.3 Compiling Macros

Although it may seem odd that macros return a form to produce a result and not simply the result this is their most important feature. It allows the expansion and the evaluation of the expansion to happen at different times.

The Lisp compiler makes use of this; when it comes across a macro call in a form it is compiling it uses the macroexpand function to produce the expansion of that form which it then compiles straight into the object code. Obviously this is good for performance (why evaluate the expansion every time it is needed when once will do?).

Some rules do need to be observed to make this work properly:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.14 Streams

A stream is a Lisp object which is either a data sink (an output stream) or a data source (an input stream). In Jade all streams produce or consume sequences of 8-bit characters.

Streams are very flexible, functions using streams for their input and output do not need to know what type of stream it is. For example the Lisp reader (the read function) takes an input stream as its one argument, it then reads characters from this stream until it has parsed a whole object. This stream could be a file, a position in a buffer, a function or even a string; the read function can not tell the difference.

Function: streamp object

This function returns t if its argument is a stream.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.14.1 Input Streams

These are the possible types of input stream, for the functions which use them see Input Functions.

file

Characters are read from the file object file, for the functions which manipulate file objects see Files.

mark

The marker mark points to the next character that will be read. Each time a character is read the position that mark points to will be advanced to the following character. See section Marks.

buffer

Reads from the position of the cursor in the buffer buffer. This position is advanced as characters are read.

(buffer . position)

Characters are read from the position position in the buffer buffer. position is advanced to the next character as each character is read.

function

Each time an input character is required the function is called with no arguments. It should return the character read (an integer) or nil if for some reason no character is available.

function should also be able to ‘unread’ one character. When this happens the function will be called with one argument — the value of the last character read. The function should arrange it so that the next time it is called it returns this character. A possible implementation could be,

(defvar ms-unread-char nil
  "If non-nil the character which was pushed back.")

(defun my-stream (&optional unread-char)
  (if unread-char
      (setq ms-unread-char unread-char)
    (if ms-unread-char
        (prog1
          ms-unread-char
          (setq ms-unread-char nil))
      ;; Normal case -- read and return a character from somewhere
      …
nil

Read from the stream stored in the variable standard-input.

It is also possible to use a string as an input stream. The string to be read from must be applied to the make-string-input-stream function and the result from this function used as the input stream.

Function: make-string-input-stream string &optional start

Returns an input stream which will supply the characters of the string string in order starting with the character at position start (or from position zero if this argument is undefined).

(read (make-string-input-stream "(1 . 2)"))
    ⇒ (1 . 2)
Variable: standard-input

The input stream which is used when no other is specified or is nil.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.14.2 Output Streams

These are the different types of output stream, for the functions which use them see Output Functions.

file

Writes to the file object file. See section Files.

mark

Writes to the position pointed to by the marked mark, then advances the position of the mark.

buffer

Writes to buffer at the position of the cursor in that buffer, which is then advanced.

(buffer . position)

position in the buffer buffer. position is then moved over the written text.

(buffer . t)

Writes to the end of the buffer buffer.

function

The function function is called with one argument, either a string or a character. This should be used as the circumstances dictate. If the function returns a number it is the number of characters actually used, otherwise it is assumed that all the characters were successful.

process

Writes to the standard input of the process object process. If process isn’t running an error is signalled. See section Processes.

t

Appends the character(s) to the end of the status line message.

nil

Write to the stream stored in the variable standard-output.

It is also possible to store the characters sent to an output stream in a string.

Function: make-string-output-stream

Returns an output stream. It accumulates the text sent to it for the benefit of the get-output-stream-string function.

Function: get-output-stream-string string-output-stream

Returns a string consisting of the text sent to the string-output-stream since the last call to get-output-stream-string (or since this stream was created by make-string-output-stream).

(setq stream (make-string-output-stream))
    ⇒ ("" . 0)
(prin1 keymap-path stream)
    ⇒ ("(lisp-mode-keymap global-keymap)" . 64)
(get-output-stream-string stream)
    ⇒ "(lisp-mode-keymap global-keymap)"
Variable: standard-output

This variable contains the output stream which is used when no other is specified (or when the given output stream is nil).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.14.3 Input Functions

Function: read-char stream

Read and return the next character from the input stream stream. If the end of the stream is reached nil is returned.

Function: read-line stream

This function reads one line of characters from the input stream stream, creates a string containing the line (including the newline character which terminates the line) and returns it.

If the end of stream is reached before any characters can be read nil is returned, if the end of stream is reached but some characters have been read (but not the newline) these characters are made into a string and returned.

Note that unlike the Common Lisp function of the same name, the newline character is not removed from the returned string.

Function: read stream

This function is the function which contains the Lisp reader (see section The Lisp Reader). It reads as many characters from the input stream stream as it needs to make the read syntax of a single Lisp object (see section Read Syntax), this object is then returned.

Function: read-from-string string &optional start

Reads one Lisp object from the string string, the first character is read from position start (or position zero).

(read-from-string string start)
≡
(read (make-string-input-stream string start))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.14.4 Output Functions

Function: write stream data &optional length

Writes the specified character(s) to the output stream stream. data is either the character or the string to be written. If data is a string the optional argument length may specify how many characters are to be written. The value returned is the number of characters successfully written.

(write standard-output "Testing 1.. 2.. 3..")
    -| Testing 1.. 2.. 3..
    ⇒ 19
Function: copy-stream input-stream output-stream

This function copies all characters which may be read from input-stream to output-stream. The copying process is not stopped until the end of the input stream is read. Returns the number of characters copied.

Be warned, if you don’t choose the streams carefully you may get a deadlock which only an interrupt signal can break!

Function: print object &optional stream

Outputs a newline character to the output stream stream, then writes a textual representation of object to the stream.

If possible, this representation will be such that read can turn it into an object structurally similar to object. This will not be possible if object does not have a read syntax.

object is returned.

(print '(1 2 3))
    -|
    -| (1 2 3)
    ⇒ (1 2 3)
Function: prin1 object &optional stream

Similar to print but no initial newline is output.

(prin1 '(1 2 3))
    -| (1 2 3)
    ⇒ (1 2 3)

(prin1 '|(xy((z]|)              ;A strange symbol
    -| \(xy\(\(z\]
    ⇒ \(xy\(\(z\]
Function: prin1-to-string object

Returns a string containing the characters that prin1 would output when it prints object.

(prin1-to-string '(1 2 3))
    ⇒ "(1 2 3)"
Function: princ object &optional stream

Prints a textual representation of object to the output stream stream. No steps are taken to create output that read can parse and no quote characters surround strings.

(princ "foo")
    -| foo
    ⇒ "foo"

(princ '|(xy((z]|)
    -| (xy((z]
    ⇒ \(xy\(\(z\]
Function: format stream template &rest values

Writes to a stream, stream, a string constructed from the format string, template, and the argument values.

If stream is nil the resulting string will be returned, not written to a stream.

template is a string which may contain format specifiers, these are a ‘%’ character followed by another character telling how to print the next of the values. The following options are available

s

Write the printed representation of the value without quoting (as if from the princ function).

S

Write the printed representation with quoting enabled (like the prin1 function).

d

Output the value as a decimal number.

o

Write the value in octal.

x

In hexadecimal.

c

Write the character specified by the value.

%

Print a literal percent character. None of the values are used.

The function works through the template a character at a time. If the character is a format specifier (a ‘%’) it inserts the correct string (as defined above) into the output. Otherwise, the character is simply put into the output stream.

If stream isn’t nil (i.e. the formatted string is returned) the value of stream is returned.

(format nil "foo %S bar 0x%x" '(x . y) 255)
    ⇒ "foo (x . y) bar 0xff"

(format standard-output "The %s is %s!" "dog" "purple")
    -| The dog is purple!
    ⇒ #<buffer *jade*>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.15 Loading

In Lisp, programs (also called modules) are stored in files. Each file is a sequence of Lisp forms (known as top-level forms). Most of the top-level forms in a program will be definitions (i.e. function, macro or variable definitions) since generally each module is a system of related functions and variables.

Before the program can be used it has to be loaded into the editor’s workspace; this involves reading and evaluating each top-level form in the file.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.15.1 Load Function

Function: load program &optional no-error no-path no-suffix

This function loads the file containing the program called program; first the file is located then each top-level form contained by the file is read and evaluated in order.

Each directory named by the variable load-path is searched until the file containing program is found. In each directory three different file names are tried,

  1. program with ‘.jlc’ appended to it. Files with a ‘.jlc’ suffix are usually compiled Lisp files. See section Compiled Lisp.
  2. program with ‘.jl’ appended, most uncompiled Lisp programs are stored in files with names like this.
  3. program with no modifications.

If none of these gives a result the next directory is searched in the same way, when all directories in load-path have been exhausted and the file still has not been found an error is signalled.

Next the file is opened for reading and Lisp forms are read from it one at a time, each form is evaluated before the next form is read. When the end of the file is reached the file has been loaded and this function returns t.

The optional arguments to this function are used to modify its behaviour,

no-error

When this argument is non-nil no error is signalled if the file can not be located. Instead the function returns nil.

no-path

The variable load-path is not used, program must point to the file from the current working directory.

no-suffix

When non-nil no ‘.jlc’ or ‘.jl’ suffixes are applied to the program argument when locating the file.

If a version of the program whose name ends in ‘.jlc’ is older than a ‘.jl’ version of the same file (i.e. the source code is newer than the compiled version) a warning is displayed and the ‘.jl’ version is used.

(load "foobar")
    error--> File error: Can't open lisp-file, foobar

(load "foobar" t)
    ⇒ nil
Variable: load-path

A list of strings, each element is the name of a directory which is prefixed to the name of a program when Lisp program files are being searched for.

load-path
    ⇒ ("" "/usr/local/lib/jade/3.2/lisp/")

The element "" means the current directory, note that directory names should have an ending ‘/’ (or whatever) so that when concatenated with the name of the file they make a meaningful filename.

Variable: lisp-lib-dir

The name of the directory in which the standard Lisp files are stored.

lisp-lib-dir
    ⇒ "/usr/local/lib/jade/3.2/lisp/"

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.15.2 Autoloading

Obviously, not all the features of the editor are always used. Autoloading allows modules to be loaded when they are referenced. This speeds up the initialisation process and may save memory.

Functions which may be autoloaded have a special form in their symbol’s function cell — an autoload form. This is a list whose first element is the symbol autoload. When the function call dispatcher finds one of these forms it loads the program file specified in the form then re-evaluates the function call. The true function definition will have been loaded and therefore the call may proceed as normal.

The structure of an autoload form is:

(autoload program-file [is-command])

program-file is the argument to give to the load function when the function is to be loaded. It should be the program containing a definition of the autoloaded function.

The optional is-command object specifies whether or not the function may be called interactively (i.e. it is an editor command).

Function: autoload symbol &rest autoload-defn

Installs an autoload form into the function cell of the symbol symbol. The form is a cons cell whose car is autoload and whose cdr is the argument autoload-defn.

Returns the resulting autoload form.

(autoload 'foo "foos-file")
    ⇒ (autoload "foos-file")
(symbol-function 'foo)
    ⇒ (autoload "foos-file")

(autoload 'bar "bars-file" t)
    ⇒ (autoload "bars-file" t)
(commandp 'bar)
    ⇒ t

It is not necessary to call the autoload function manually. Simply prefix the definitions of all the functions which may be autoloaded (i.e. the entry points to your module; not all the internal functions!) with the magic comment ;;;###autoload. Then the add-autoloads command can be used to create the necessary calls to the autoload function in the ‘autoloads.jl’ Lisp file (this file which lives in the Lisp library directory is loaded when the editor is initialised).

Meta-x add-autoloads

Scans the current buffer for any autoload definitions. Functions with the comment ;;;###autoload preceding them have autoload forms inserted into the ‘autoloads.jl’ file. Simply save this file’s buffer and the new autoloads will be used the next time Jade is initialised.

It is also possible to mark arbitrary forms for inclusion in the ‘autoloads.jl’ file: put them on a single line which starts with the comment ;;;###autoload call the command.

The unsaved ‘autoloads.jl’ buffer will become the current buffer.

;;;###autoload
(defun foo (bar)                ;foo is to be autoloaded
  …

;;;###autoload (setq x y)       ;Form to eval on initialisation
Meta-x remove-autoloads

Remove all autoload forms from the ‘autoloads.jl’ file which are marked by the ;;;###autoload comment in the current buffer.

The unsaved ‘autoloads.jl’ buffer will become the current buffer.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.15.3 Features

Features correspond to modules of the editor. Each feature is loaded separately. Each feature has a name, when a certain feature is required its user asks for it to be present (with the require function), the feature may then be used as normal.

When a feature is loaded one of the top-level forms evaluated is a call to the provide function. This names the feature and installs it into the list of present features.

Variable: features

A list of the features currently present (that is, loaded). Each feature is represented by a symbol. Usually the print name of the symbol (the name of the feature) is the same as the name of the file it was loaded from, minus any ‘.jl’ or ‘.jlc’ suffix.

features
    ⇒ (info isearch fill-mode texinfo-mode lisp-mode xc)
Function: provide feature

Adds feature (a symbol) to the list of features present. A call to this function is normally one of the top-level forms in a module.

;;;; maths.jl -- the maths module

(provide 'maths)
…
Function: require feature &optional file

Show that the caller is planning to use the feature feature (a symbol). This function will check the features variable to see if feature is already loaded, if so it will return immediately.

If feature is not present it will be loaded. If file is non-nil it specifies the first argument to the load function, else the print name of the symbol feature is used.

;;;; physics.jl -- the physics module

(require 'maths)                ;Need the maths module
(provide 'physics)
…

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.16 Compiled Lisp

Jade contains a rudimentary Lisp compiler; this takes a Lisp form or program and compiles it into a byte-code form. This byte-code form contains a string of byte instructions, a vector of data constants and some other information.

The main reason for compiling your programs is to increase their speed, it is difficult to quantify the speed increase gained — some programs (especially those using a lot of macros) will execute many times quicker than their uncompiled version whereas others may only execute a bit quicker.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.16.1 Compilation Functions

Function: compile-form form

This function compiles the Lisp form form into a byte-code form which is returned.

(compile-form '(setq foo bar))
    ⇒ (jade-byte-code "F!" [bar foo] 2)
Command: compile-file file-name

This function compiles the file called file-name into a file of compiled Lisp forms whose name is file-name with ‘c’ appended to it (i.e. if file-name is ‘foo.jl’ it will be compiled to ‘foo.jlc’).

If an error occurs while the file is being compiled any semi-written file will be deleted.

When called interactively this function will ask for the value of file-name.

Command: compile-directory directory &optional force exclude

Compiles all the Lisp files in the directory called directory which either haven’t been compiled or whose compiled version is older than the source file (Lisp files are those ending in ‘.jl’).

If the optional argument force is non-nil all Lisp files will be recompiled whatever the status of their compiled version.

The exclude argument may be a list of filenames, these files will not be compiled.

When this function is called interactively it prompts for the directory.

Function: compile-lisp-lib &optional force

Uses compile-directory to compile the library of standard Lisp files. If force is non-nil all of these files will be compiled.

The ‘autoloads.jl’ is never compiled since it is often modified and wouldn’t really benefit from compilation anyway.

Function: jade-byte-code byte-codes constants max-stack

Interprets the string of byte instructions byte-codes with the vector of constants constants. max-stack defines the maximum number of stack cells required to interpret the code.

This function is never called by hand. The compiler will produce calls to this function when it compiles a form or a function.

(setq x 1
      y 3)
    ⇒ 3
(setq comp (compile-form '(cons x y)))
    ⇒ (jade-byte-code "K" [x y] 2)
(eval comp)
    ⇒ (1 . 3)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.16.2 Compilation Tips

Here are some tips for making compiled code run fast:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.16.3 Disassembly

It is possible to disassemble byte-code forms; originally this was so I could figure out why the compiler wasn’t working but if you’re curious about how the compiler compiles a form it may be of use to you.

Naturally, the output of the disassembler is a listing in Jade’s pseudo-machine language — it won’t take a byte-code form and produce the equivalent Lisp code!

Command: disassemble-fun function &optional stream

This function disassembles the compile Lisp function function. It writes a listing to the output stream stream (normally the value of the standard-output variable).

When called interactively it will prompt for a function to disassemble.

When reading the output of the disassembler bear in mind that Jade simulates a stack machine for the code to run on. All calculations are performed on the stack, the value left on the stack when the piece of code ends is the value of the byte-code form.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.17 Hooks

A hook allows you to wedge your own pieces of Lisp code into the editor’s operations. These pieces of code are evaluated via the hook and the result is available to the hook’s caller.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.17.1 Functions As Hooks

Some hooks only allow a single piece of code to be hooked in. Usually a normally-undefined function is used; to install your hook defined a function with the name of the hook. When the hook is to be evaluated the function is called.

Generally the name of the hook’s function will end in -function.

An alternative scheme is to use a variable to store the hook, its value should be the function to call.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.17.2 Normal Hooks

This is the standard type of hook, it is a variable whose value is a list of functions. When the hook is evaluated each of the named functions will be called in turn until one of them returns a value which is not nil. This value becomes the value of the hook and no more of the functions are called. If all of the functions in the hook return nil the value of the hook is nil.

The names of hooks of this type will normally end in -hook.

Function: add-hook hook function &optional at-end

This function adds a new function function to the list of functions installed in the (list) hook hook (a symbol).

If at-end is non-nil the new function is added at the end of the hook’s list of functions (and therefore will be called last when the hook is evaluated), otherwise the new function is added to the front of the list.

text-mode-hook
    ⇒ (fill-mode-on)
(add-hook 'text-mode-hook 'my-function)
    ⇒ (my-function fill-mode-on)
Function: remove-hook hook function

This function removes the function function from the list of functions stored in the (list) hook hook (a symbol).

All instances of function are deleted from the hook.

text-mode-hook
    ⇒ (my-function fill-mode-on)
(remove-hook 'text-mode-hook 'my-function)
    ⇒ (fill-mode-on)
Function: eval-hook hook &rest args

Evaluates the (list) hook hook (a symbol) with argument values args.

Each function stored in the hook is applied to the args in turn until one returns non-nil. This non-nil value becomes the result of the hook. If all functions return nil then the result of the hook is nil.

Note that most functions which are installed in hooks should always return nil to ensure that all the functions in the hook are evaluated.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.17.3 Standard Hooks

This is a table of the predefined hooks in Jade:

asm-cpp-mode-hook

@xref{Asm mode}.

asm-mode-hook

@xref{Asm mode}.

auto-save-hook

See section Controlling Auto-Saves.

buffer-menu-mode-hook
c-mode-hook

@xref{C mode}.

destroy-window-hook

See section Closing Windows.

gdb-hook
idle-hook

See section Idle Actions.

indented-text-mode-hook

@xref{Indented-Text mode}.

insert-file-hook

See section Reading Files Info Buffers.

kill-buffer-hook

See section Destroying Buffers.

lisp-mode-hook

@xref{Lisp mode}.

make-window-hook

See section Opening Windows.

open-file-hook

See section Reading Files Info Buffers.

read-file-hook

See section Reading Files Info Buffers.

shell-callback-function
shell-mode-hook
texinfo-mode-hook

@xref{Texinfo mode}.

text-mode-hook

@xref{Text mode}.

unbound-key-hook

See section Event Loop.

window-closed-hook

See section Event Loop.

write-file-hook

See section Writing Buffers.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.18 Buffers

A buffer is a Lisp object containing a ‘space’ in which files (or any pieces of text) may be edited, either directly by the user or by Lisp programs.

Each window (see section Windows) may display any one buffer at any time, the buffer being displayed by the current window is known as the current buffer. This is the buffer which functions will operate on by default.

Function: bufferp object

Returns t if its argument is a buffer.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.18.1 Buffer Attributes

All buffer objects store a set of basic attributes, some of these are:

name

Each buffer has a unique name.

Function: buffer-name &optional buffer

Returns the name of the buffer buffer, or of the current buffer if buffer is undefined.

(buffer-name)
    ⇒ "programmer.texi"
Function: set-buffer-name name &optional buffer

Sets the name of the buffer buffer (or the current buffer) to the string name.

Note that name is not checked for uniqueness, use the make-buffer-name function if you want a guaranteed unique name.

Function: make-buffer-name name

Returns a unique version of the string name so that no existing buffer has the same string as its name. If a clash occurs a suffix ‘<N>’ is appended to name, where n is the first number which guarantees the uniqueness of the result.

Function: get-buffer name

Returns the existing buffer whose name is name, or nil if no such buffer exists.

file name

Since buffers often contain text belonging to files on disk the buffer stores the name of the file its text was read from. See section Editing Files.

Function: buffer-file-name &optional buffer

Returns the name of the file stored in buffer. If no file is stored in the buffer the null string (‘’) is returned.

(buffer-file-name)
    ⇒ "man/programmer.texi"
Function: set-buffer-file-name name &optional buffer

This function sets the file-name of the buffer to the string name.

Function: get-file-buffer file-name

Searches for an existing buffer containing the file file-name then returns it, or nil if no such buffer exists.

contents

The contents of a buffer is the text it holds. This is stored as an array of lines. See section Text.

tab size

This is the spacing of tab stops. When the contents of the buffer is being displayed (in a window) this value is used.

Variable: tab-size

A buffer-local variable which holds the size of tab stops in the buffer.

glyph table

Each buffer has its own glyph table which is used when the buffer is being displayed. See section Buffer Glyph Tables.

local variables

Each buffer can have its own value for any variable, these local values are stored in an alist which lives in the buffer object. See section Buffer-Local Variables.

Function: buffer-variables &optional buffer

Returns the alist of local variables in the buffer. Each alist element is structured like, (symbol . local-value).

modification counter

Each modification made to the buffer increments its modification counter. See section Modifications to Buffers.

Function: buffer-changes &optional buffer

Returns the number of modifications made to the buffer since it was created.

undo information

When a modification is made to a buffer enough information is recorded so that the modification can later be undone. See section Controlling Undo.

All other buffer-specific information is kept in buffer-local variables.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.18.2 Creating Buffers

Function: make-buffer name

Creates and returns a new buffer object. Its name will be a unique version of name (created by the make-buffer-name function).

The buffer will be totally empty and all its attributes will have standard values.

(make-buffer "foo")
    ⇒ #<buffer foo>
Function: open-buffer name

If no buffer called name exists, creates a new buffer of that name and adds it to the end of each windows buffer-list. This function always returns the buffer called name.

For more ways of creating buffers see Editing Files.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.18.3 Modifications to Buffers

Each buffer maintains a counter which is incremented each time the contents of the buffer is modified. It also holds the value of this counter when the buffer was last saved, when the two numbers are different the buffer is classed as have being modified.

Function: buffer-modified-p &optional buffer

This function returns t when the buffer has been modified.

Function: set-buffer-modified buffer status

Sets the modified status of the buffer buffer. When status is nil the buffer will appear to be unmodified, otherwise it will look modified.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.18.4 Read-Only Buffers

When a buffer has been marked as being read-only no modifications may be made to its contents (neither by the user nor a Lisp program).

Function: buffer-read-only-p &optional buffer

Returns t when the buffer is read-only.

Function: set-buffer-read-only buffer read-only

When read-only is non-nil the buffer buffer is marked as being read-only, otherwise it is read-write.

Variable: inhibit-read-only

When this variable is non-nil any buffer may be modified, even if it is marked as being read-only.

Lisp programs can temporarily bind a non-nil value to this variable when they want to edit one of their normally read-only buffers.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.18.5 Destroying Buffers

Since all Lisp objects have indefinite extent (i.e. they live until there are no references to them) a buffer will be automatically destroyed when all references to it disappear.

Alternatively one of the following functions can be used to explicitly kill a buffer; the buffer object will still exist but all data associated with it (including the text it contains) will be released.

Command: kill-buffer buffer

Removes the buffer buffer (a buffer or the name of a buffer) from all windows (any windows displaying buffer will be changed to display the previous buffer they showed) and destroys the buffer.

The hook kill-buffer-hook is evaluated before the buffer is killed with buffer as its argument.

If the buffer contains unsaved modifications the user will be asked if they really want to lose them before the buffer is killed (if the answer is yes).

When called interactively a buffer will be prompted for.

Hook: kill-buffer-hook

Hook called by kill-buffer before it does anything. If a function in the hook doesn’t want the buffer deleted it should signal some sort of error.

Function: destroy-buffer buffer

This function may be used to remove all data stored in the buffer object manually. Also, any marks in this buffer are made non-resident.

After applying this function to a buffer the buffer will contain one empty line.

Use this function wisely, there are no safety measures taken to ensure valuable data is not lost.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.18.6 Special Buffers

When a buffer is special it means that it is controlled by a Lisp program, not by the user typing into it (although this can happen as well).

Special buffers are used for things like the ‘*jade*’ or ‘*Info*’ buffers (in fact most of the buffers whose names are surrounded by asterisks are special).

What the special attribute actually does is make sure that the buffer is never truly killed (kill-buffer removes it from each window’s buffer-list but doesn’t call destroy-buffer on it) and modifications don’t cause the ‘+’ flag to appear in the status line.

Function: buffer-special-p &optional buffer

Returns t if the buffer is marked as being special.

Function: set-buffer-special buffer special

Sets the value of the special flag in the buffer buffer to the value of special (nil means non-special, anything else means special).

Another type of special buffer exists; the mildly-special buffer.

Variable: mildly-special-buffer

When this buffer-local variable is set to t (it is nil by default) and the buffer is marked as being special, the kill-buffer function is allowed to totally destroy the buffer.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.18.7 The Buffer List

Each window (see section Windows) has a list of buffers which may be displayed in that window. It is arranged is most-recently-used order, so that the car of the list is the buffer currently being shown in the window, the second element the window previously being shown and so on.

Variable: buffer-list

A variable, local to each window, which contains a list of the buffers available in the window. The list is maintained in most-recently-used order.

buffer-list
    ⇒ (#<buffer programmer.texi> #<buffer *Help*>
               #<buffer buffers.c> #<buffer buffers.jl>
               #<buffer edit.c> #<buffer edit.h>
               #<buffer *jade*> #<buffer lisp.jl>
               #<buffer *compilation*> #<buffer *Info*>)

Generally each window’s buffer-list contains the same buffers, each window has its own value for the variable so it can be kept in the correct order (each window will probably be displaying different buffers).

Function: add-buffer buffer

This function ensures that the buffer buffer is in each window’s buffer-list. If it isn’t it is appended to the end of the list.

Function: remove-buffer buffer

Deletes all references to buffer in each window’s buffer-list.

Command: bury-buffer &optional buffer all-windows

Puts buffer (or the currently displayed buffer) at the end of the current window’s buffer-list then switch to the buffer at the head of the list.

If all-windows is non-nil this is done in all windows (the same buffer will be buried in each window though).

Command: rotate-buffers-forward

Moves the buffer at the head of the buffer-list to be last in the list, the new head of the buffer-list is displayed in the current window.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.18.8 The Current Buffer

The current buffer is the buffer being displayed in the current window (see section Windows), all functions which take an optional buffer argument will operate on the current buffer if this argument is undefined. Similarly if a window argument to a function is left undefined the current window will be used.

Function: current-buffer &optional window

Returns the buffer being displayed by the window window (or the current window).

(current-buffer)
    ⇒ #<buffer programmer.texi>

The set-current-buffer function sets the current buffer of a window. If, when the window is next redisplayed (i.e. after each command), the current buffer is different to what it was at the last redisplay the new buffer will be displayed in the window.

Function: set-current-buffer buffer &optional window

Sets the buffer that the window is displaying.

Usually a window’s current buffer will be the buffer which is at the head of the window’s buffer-list. The function goto-buffer can be used to set both of these at once.

Function: goto-buffer buffer

Set the current buffer to buffer which is either a buffer or a string naming a buffer. The selected buffer is moved to the head of the window’s buffer-list.

If buffer is a string and no buffer exists of that name a new one is created.

Often you will want to temporarily switch to a different current buffer, that is what the with-buffer special form is for.

Special Form: with-buffer buffer forms…

Temporarily sets the current buffer to the value of evaluating buffer, then evaluates the forms in sequence. The old value of the current buffer is reinstated and the structure returns the value of the last of the forms to be evaluated.

If the implicit progn evaluating forms is exited abnormally the old value of the current buffer will still be reinstated.

If the window is redisplayed while the forms are being evaluated (i.e. in a recursive edit) the new buffer will be drawn into the window.

(with-buffer new-buffer         ;Enter a recursive edit in
  (recursive-edit))             ; the buffer new-buffer.

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19 Windows

A window is a Lisp object representing a window (a rectangular section of the display) open in the windowing-system you are running Jade in.

Windows have two main functions, firstly to provide a means of seeing the contents of a buffer and secondly to receive input events. For more details about event handling see Event Loop.

A window always displays a buffer and there is always at least one window open. The editor remembers which of the open windows is the current window, this is normally the window it last received an input event from, though it can be set by programs.

For some basic details about using windows see @ref{Using Windows}.

Function: windowp object

This function returns t if its argument is a window.

Variable: window-list

This variable’s value is a list of all the currently open windows. The order of the elements in the list is insignificant.

window-list
    ⇒ (#<window 20971528 *Info*> #<window 20971524 *jade*>)

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19.1 Opening Windows

Function: open-window &optional buffer x y width height

Opens a new window and returns it. If buffer is defined it is the buffer to display in the new window, otherwise the current buffer is displayed.

The x and y arguments are the pixel coordinates of the new window’s top left corner in the display. The width and height arguments are the size of the window in columns and rows of characters respectively.

What happens when the position and size of the window is undefined will depend on the underlying window system, on the Amiga the window will probably be the same as the current window, in X11 the window manager will probably let the user size it interactively.

The new window will have its buffer-list variable initialised suitably and it will be added to the head of the window-list variable.

The make-window function is the lowest level of creating a new window, open-window uses it to open the window.

Function: make-window &optional x y width height

Creates a new window and returns it, the arguments are similar to those of the same name in the open-window function. The window will display the current buffer.

After the window is created the make-window-hook will be called with the window as its argument.

Hook: make-window-hook

Hook called each time a new window is created. It has one argument, the new window.

Variable: pub-screen

This window-local variable is only used on the Amiga version of Jade; it holds the name of the public screen which windows are opened on. By default this is the Workbench screen.

When a window is opened it inherits this value from the current window at the time.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19.2 Closing Windows

Unlike buffers, window objects don’t have indefinite extent, even when a window is incapable of being referenced the object will not be destroyed by the garbage collector; count the user looking at the window as a reference!

When the window is closed (by the destroy-window function) the object loses its ‘window-ness’ and the garbage collector is free to reclaim its memory.

Function: close-window &optional window

This function closes the window window (or the current window) and deletes its entry from the window-list variable.

If this window is the only one the editor has open the user is asked if it’s okay to lose any modified buffers before the window is closed.

Function: close-other-windows &optional window

Uses close-window to close all windows except window (or the current window).

Function: destroy-window window

Closes the window window. After a window object has been closed it is no longer a member of the type ‘window’.

Before closing the window the destroy-window-hook is evaluated with the window being destroyed as an argument.

When the last window is closed the editor will exit automatically.

Like the destroy-buffer function, this function is dangerous if used carelessly.

Both close-window and close-other-windows eventually call this function.

Hook: destroy-window-hook

Hook called by destroy-window before it does anything. It has one argument — the window to be destroyed.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19.3 Iconifying Windows

When you don’t want a window cluttering the display, but don’t want to kill it totally it can be iconified; the window will be displayed as a small icon which can be reactivated when the window is wanted again.

Function: sleep-window &optional window

Iconifies the specified window.

Function: unsleep-window &optional window

Uniconifies the specified window. This may be done automatically if the user needs to be prompted.

Function: toggle-iconic

Toggles the current window between the iconified and normal states. This command is bound to the key sequence Ctrl-z.

Function: window-asleep-p

Returns t when the current window is iconified.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19.4 Displaying Messages

Often it is useful to be able to show the user a short one-line message, this is what the message function does.

Function: message message &optional display-now

This function displays the string message in the status line of the current window, then returns message.

If display-now is non-nil the message is rendered into the window immediately, otherwise it will not be visible until the next general redisplay (usually after each command exits).

Note that an alternate way of writing in the status line is to use the output stream t. See section Output Streams.

When writing interactive programs it is sometimes useful to be able to render the cursor in the status line. This shows that the next key press will not be subject to normal editing key bindings but to the special user interface (usually explained by a message in the status line).

For example the y-or-n-p function uses this technique to show that it needs an answer.

Variable: status-line-cursor

When this window-local variable is non-nil the window’s cursor is rendered at the end of the message in the status line, not at the cursor’s position in the main display.

Another way of alerting the user is to use the beep function,

Function: beep

This function rings a bell or flashes the current window or screen depending on your system.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19.5 The Current Window

The current window is the window that functions operate on by default; every time the event loop receives some input from the user the window which the input event originated in becomes the current window. It is also possible for Lisp programs to set the current window, either permanently or temporarily.

The active window is the window which the windowing system will send any keyboard input to. Since Jade sets the current window to where it receives input from, it is often the case that the current window is the same as the active window. Jade also provides the means to set the active window; in some cases this may be best left to the user though.

Function: current-window

This function returns the current window.

(current-window)
    ⇒ #<window 20971524 programmer.texi>
Function: set-current-window window &optional activate

This function sets the current window to be the window window. If the optional argument activate is non-nil this window will also become the active window.

When using the activate argument bear in mind that it may be confusing for the user if the active window is suddenly changed; only change the active window synchronously with some input from the user.

Special Form: with-window window forms…

Temporarily sets the current window to the value of evaluating the form window, then uses an implicit progn to evaluate the forms. The old current window is then reinstated before returning the value of the implicit progn.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19.6 Window Font

Each window may use a different font; this font will be used for rendering all text in the window. When windows are created they inherit their font from the current window at the time.

Currently Jade only allows the use of fixed-width fonts; proportional fonts won’t work properly.

Command: set-font font-name &optional window

This function sets the font used in the window window (or the current window) to the font named by the string font-name.

The format of the string font-name depends on the underlying windowing system:

X11

Simply use the standard name of the font, asterisk characters work like usual (i.e. match zero or more characters).

Amiga

This is different to the normal Amiga conventions, use the name of the font followed by a dash and then the size of the font. For example to get an 8-point topaz font, use ‘topaz.font-8’.

When this function is called interactively it will prompt for font-name.

Function: font-name &optional window

Returns the name of the font being used in the specified window.

Note that on an Amiga this will only return the name, and not the size of the font. For example, if set-font has been used with an argument of "topaz.font-8", a call to font-name would produce "topaz.font".

Function: font-x-size &optional window

Returns the width (in pixels) of a character in the specified window’s font.

(font-x-size)
    ⇒ 7
Function: font-y-size &optional window

Returns the height in pixels of each character in the window’s font.

(font-y-size)
    ⇒ 13

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19.7 Window Information

There are a number of functions which provide information about the current state of a window.

Function: window-id &optional window

Returns an integer which is the window system’s ‘handle’ on the window window (or the current window). Under X11 this is the Window identifier, on an Amiga it’s a pointer to the window’s struct Window.

(window-id)
    ⇒ 20971524
Function: window-count

Returns the number of currently-opened windows.

Function: screen-width

Returns the width of the root window or screen in pixels.

Function: screen-height

Returns the height in pixels of the root window.

Function: window-left-edge

Returns the x coordinate of the current window relative to the root window’s top-left corner.

Function: window-top-edge

The y coordinate of the current window relative to the root window’s top-left corner.

Function: window-width

Returns the width, in pixels, of the current window.

Function: window-height

Returns the height in pixels of the current window.

Function: window-bar-height

Only used by Amigas, this returns the height of the current window’s title bar. This will always be zero in X.

Function: screen-top-line

Returns the line number of the first line being shown in the current window.

Function: screen-bottom-line

Returns the line number of the last line being shown in the current window.

Function: screen-first-column

Returns the column number of the first column being shown in the current window.

Function: screen-last-column

Returns the column number of the last column being shown in the current window.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19.8 Rendering

After each command is executed a full redisplay is done; the display of each window is made to be consistent with the contents of the buffer it is showing.

Function: refresh-all

This function calls the redisplay code, any windows, whose display is inconsistent with what it should be displaying, are updated.

Function: cursor on

Turns the cursor in the current window on or off (depending on whether on is non-nil or not). Normally the cursor is erased while Lisp programs are executing.

If you use this function be sure to leave the cursor undrawn when you’ve finished.

Function: centre-display &optional window

If possible, this function will arrange it so that the line which the cursor is on (see section The Cursor Position) will be in the centre of the display.

Function: next-screen &optional count

Move count (or 1 by default) screens forwards in the display, Lisp programs shouldn’t need to call this.

Function: prev-screen &optional count

Move count screens backwards in the display. Don’t call this from Lisp programs.

Function: flush-output

This function forces any locally-cached rendering operations to be drawn into the actual window. This should be called after any use of the refresh-all or cursor functions.

Currently this function only actually does anything in the X11 version of Jade (it calls XFlush()), but to ensure the portability of Lisp programs it should be used anyway.

Variable: max-scroll

This window-local variable defines the maximum number of lines which may be scrolled in one go; if more than this number of lines have to be moved when a redisplay happens the whole window will be redrawn.

Variable: y-scroll-step-ratio

This window-local variable controls the actual number of lines scrolled when the cursor moves out of the visible part of the window. The number of lines to move the display origin is calculated with the formula:

(/ total-lines-in-window y-scroll-step-ratio)

If the variable’s value is zero then the window will be scrolled by the least number of lines necessary to get the cursor back into the visible part.

Variable: x-scroll-step-ratio

Similar to y-scroll-step-ratio, except that it’s used when the cursor disappears to the left or the right of the display.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.19.9 Block Marking

Each window may define one block, this is a region of the buffer displayed in the window which is rendered in the opposite colours to normal (i.e. the same as the normal cursor, when the cursor is in a block it’s drawn in the inverse of the block). Blocks are primarily used for marking areas of a buffer which will subsequently be manipulated.

Normally the area of the buffer contained by a block is delimited by two positions; the start and end of the block (these will track changes made to the buffer and adjust themselves, like marks do). It is also possible to mark rectangular blocks; these are also delimited by two positions, but they define the two opposite corners of the rectangular block.

Function: blockp

Returns t if a block is marked in the current window.

Function: mark-block start-pos end-pos

Define the beginning and end markers of the block to display in the current window.

Command: block-kill

Unmark the block displayed in the current window.

Command: mark-word count &optional pos

Mark count words from pos (or the cursor pos) in the current window.

Command: mark-whole-buffer

Mark the whole of the current buffer.

Function: block-start

Returns the position of the beginning of the block marked in the current window. If no block is defined returns nil.

Function: block-end

Returns the position of the end of the block, or nil if no block is defined in the current window.

Command: block-toggle

Toggles between marking the beginning, marking the end and totally unmarking the block in the current window.

Function: rect-blocks-p &optional window

Returns t if the block marked in the window is drawn as a rectangle.

Function: set-rect-blocks window status

Defines whether or not the block drawn in window is drawn as a rectangle or not. If status is nil it isn’t.

Command: toggle-rect-blocks

Toggles between marking normal and rectangular blocks in the current window.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20 Positions

A position is a Lisp object representing the location of one of the characters in the contents of a buffer (see section Buffers). Since Jade stores buffer contents as an array of lines, two index values are needed to reference a single character. A position object contains two integers; the column and line numbers of the character, both these values count upwards from zero (i.e. the first character in a buffer has line and column numbers of zero).

Position objects have no read syntax; they print as,

#<pos column line>
Function: posp object

This function returns t when its argument is a position object.

Function: pos column line

Creates and returns a new position object, it points to column number column and line number line (both integers).

Function: copy-pos pos

Creates a new copy of the position object pos.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.1 Position Components

As previously noted, each position object has two components; one number defining the column, the other defining the line that the position represents. These components can be accessed individually.

Function: pos-col pos

Returns the column which the position object pos points to.

(pos-col (pos 1 2))
    ⇒ 1
Function: pos-line pos

This function returns the line number which pos points to.

Function: set-pos-col pos new-col

Sets the number of the column which the position object pos points to, to new-col (an integer), then returns col.

(setq x (pos 1 2))
    ⇒ #<pos 1 2>
(set-pos-col x 3)
    ⇒ 3
x
    ⇒ #<pos 3 2>
Function: set-pos-line pos new-line

Similar to set-pos-col except the line number is modified.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.2 The Cursor Position

Each window displays a cursor, this is rendered as a character in the opposite colour to what it would usually be (i.e. normally a dark rectangle). The cursor is used to show the user where any characters they type will be inserted, each window has a separate cursor position and buffers which are not being displayed ‘remember’ the last position of their cursor.

Function: cursor-pos

This function returns a copy of the cursor position in the current window.

(cursor-pos)
    ⇒ #<pos 14 5638>
Function: goto-char pos

Sets the position of the current window’s cursor to the position object pos, then returns pos.

Note that the components of pos are copied, any subsequent modification of pos will not affect the cursor.

If the line number of pos points to a non-existent line the cursor won’t be moved and nil will be returned.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.3 Movement Functions

This section documents the functions which are used to create and modify position objects so that they point to a different position which is related to the original position in some way.

The functions which begin goto- set the cursor position of the current window to the new position; the others do not move the cursor, they simply calculate the new position and return it.

In some cases the position argument itself will be modified and returned, this may cause confusion; if there are existing references to the object they subtle bugs may result. Consider the following,

(setq x (cursor-pos)
      y (next-char 1 x))

At first glance this looks as though the variable y will point to one character after the variable x does. Since the next-char function modifies its argument position both variables will contain the same object, and therefore, point to the same position.

A solution is,

(setq x (cursor-pos)
      y (next-char 1 (copy-pos x)))

Read each function’s description carefully to see if it alters its arguments!


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.3.1 Buffer Extremes

Function: buffer-end &optional buffer

Create and return a new position object pointing to the character after the last character in the buffer.

Function: goto-buffer-end

Set the cursor to the character after the last character in the current buffer.

Function: buffer-start &optional buffer

Create a new position pointing to the first character in the buffer. Currently this is always the position #<pos 0 0> and the buffer argument is ignored.

Function: goto-buffer-start

Set the cursor position to the first character in the buffer.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.3.2 Character Movement

Function: left-char &optional count pos

Alter and return pos (or a copy of the cursor pos) so that it points count characters (default is one) to the left of its current position. If the resulting column number is less than zero nil is returned, else the position.

(goto-char (pos 20 0))
    ⇒ #<pos 20 0>
(left-char)
    ⇒ #<pos 19 0>

(setq x (pos 4 1))
    ⇒ #<pos 4 1>
(left-char 3 x)
    ⇒ #<pos 1 1>
x
    ⇒ #<pos 1 1>
Function: goto-left-char &optional count

Move count (or one) characters to the left.

Function: right-char &optional count pos

Alter and return pos (or a copy of the cursor pos) so that it points count (or one) characters to the right of its current position. May return a position which points to a character past the end of the line.

Function: goto-right-char &optional count

Move count (or one) characters to the right.

The following functions results depends on the contents of the buffer they are operating on; they move a certain number of characters, and hence will cross line boundaries.

Function: next-char &optional count pos buffer

Alter and return pos (or a copy of the cursor pos) to point to the character count characters in front of its current position.

If count is negative this function will work backwards through the buffer.

Function: goto-next-char &optional count

Move count characters forwards.

Function: prev-char &optional count pos buffer

Similar to the next-char function but will work backwards when count is positive and forwards when it is negative.

Function: goto-prev-char count

Move count characters backwards.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.3.3 Word Movement

There are two buffer-local variables which control the syntax of words in each buffer.

Variable: word-regexp

This buffer-local variable contains a regular expression which will match each character allowed to be in a word.

The standard value is ‘[a-zA-Z0-9]’, i.e. all alphanumeric characters.

Variable: word-not-regexp

A buffer-local variable. Holds a regular expression which will match anything not in a word.

The normal value is ‘[^a-zA-Z0-9]|$’, i.e. anything which is not alphanumeric or the end of a line.

The following functions use these variables when deciding what is and what isn’t a word.

Function: forward-word &optional count pos move

Return the position of the first character after the end of the word at position pos (or the cursor). count is the number of words to move, negative values mean go backwards.

If move is non-nil then the cursor is moved to the result.

Note that pos is not altered.

Function: backward-word &optional count pos move

Similar to forward-word except that it works backwards. In fact, all this function does is call forward-word with count negated.

Function: word-start &optional pos

Returns the position of the first character of the word at pos (or the cursor position).

Function: in-word-p &optional pos

This function returns t if pos (or the cursor) is in a word.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.3.4 Tab Movement

Function: prev-tab &optional count pos size

Alter and return pos (or a copy of the cursor position) so that it points count (default is one) tab stops to the left of its current position. Returns nil if that position is before the start of the line.

size is optionally the number of glyphs in each tab, or the value of the tab-size variable.

Note that the position returned is not the position of a character but of a glyph (see section Glyph Positions).

(prev-tab 1 (pos 20 0))
    ⇒ #<pos 16 0>
Function: goto-prev-tab &optional count size

Move count tab stops to the left.

Function: next-tab &optional count pos size

Alter and return pos (or a copy of the cursor position) so that it points count tab stops to the right of its current position.

size is optionally the number of glyphs in each tab, or the value of the tab-size variable.

Note that the position returned is not the position of a character but of a glyph (see section Glyph Positions).

Function: goto-next-tab &optional count size

Move count tab stops to the right.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.3.5 Line Movement

Function: next-line &optional count pos

Alter and return pos (or a copy of the cursor position) so that it points count (or one) lines forwards, the column component is not changed.

If count is negative (i.e. go backwards) and the resulting line number is less than zero nil is returned.

(next-line 2 (pos 1 1))
    ⇒ #<pos 1 3>

(next-line -1 (pos 1 1))
    ⇒ #<pos 1 0>
Function: goto-next-line &optional count

Move count lines downwards, the column number of the cursor is adjusted so that its glyph position is as close to its previous glyph position as possible.

Function: prev-line &optional count pos

Similar to next-line but goes backwards (or forwards with a negative count).

Function: goto-prev-line &optional count

Move count lines backwards, adjusting the column number of the cursor as necessary.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.3.6 Expression Movement

Some major modes provide functions to move backwards and forwards over expressions written in a buffer in the programming language that the mode supports (see section Mode-Specific Expressions), for example the Lisp mode defines the syntax of Lisp forms written in a buffer.

Function: forward-exp &optional count

This function moves the cursor over count expressions, as defined in the current buffer. If the buffer has no expression definitions an error is signalled.

Function: backward-exp &optional count

Moves backwards over count (or one) expressions, leaving the cursor at the beginning of the expression. If the buffer has no expression definition functions an error is signalled.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.20.4 Positions and Offsets

Although Jade stores the position of a character as a pair of two numbers many other programs define the position of a character as its offset from the beginning of the buffer or file it is in. The following functions may be used to convert between these two types of positions in a specified buffer.

Function: pos-to-offset &optional pos buffer

This function returns the offset of the character at the position pos (or the cursor position by default) in the specified buffer. This will be an integer, the first character in a buffer is represented by an offset of zero.

(pos-to-offset (pos 0 0))
    ⇒ 0

(pos-to-offset)
    ⇒ 195654
Function: offset-to-pos offset &optional buffer

Creates a new position object which contains the position of the character offset characters from the start of the specified buffer.

(offset-to-pos 0)
    ⇒ #<pos 0 0>

(offset-to-pos 195654)
    ⇒ #<pos 14 5974>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.21 Marks

A mark is a Lisp object which points to a character in a file (or buffer), as the buffer the file is stored in is modified the position the mark points to is also modified so that the mark will always point to the same character.

The character that a mark points to does not have to be loaded into the editor all the time either; if the file the character is in is not resident in a buffer the mark will simply contain the character’s position and the file’s name. When a file is loaded any marks pointing to the file are altered so that they point straight to the buffer containing the file.

Function: markp object

This function returns t if its argument is a mark.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.21.1 Mark Components

Each mark object has two main components; the position of the character pointed to by the mark (a position object) and the file which the character is contained by.

The file is the most complex component, it can be either a string naming the file or a buffer. When the file component is a string the mark is said to be non-resident since none of the editor buffers contain the character which the mark points to.

Function: mark-pos mark

Returns the position object contained in the marker mark, no copy is made: if you modify the position returned it will be reflected in the position of the mark.

Note that if you later modify the buffer the mark is resident in the position previously returned by mark-pos may be altered by the mark relocation process. See section Mark Relocation.

Function: mark-file mark

Returns the file component of mark. This will be either the name of the file or the buffer itself depending on whether the mark is resident or not. See section Mark Residency.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.21.2 Mark Relocation

An important feature of marks is that they always point to the same character, even when the buffer has been modified, changing the position of the character (i.e. if some text is deleted from somewhere before the character its position will probably change).

Every time a buffer is modified each mark which points to a character in that buffer is examined and then, if necessary, the position it points to is changed to take account of the buffer’s new state.

Basically, what happens is that each mark will try to point at the same character all the time. If some text is inserted at the position of the mark the mark’s position will be advanced to the end of the insertion and hence the original character.

The only time the mark will not point at the same character is when the character is deleted from the buffer. In this case the mark will point to the start of the deletion.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.21.3 Mark Residency

As I have already explained, a mark does not necessarily have to point at a character loaded into a buffer; it can also point at a character in a file on disk somewhere. When this happens the mark is said to be non-resident.

Function: mark-resident-p mark

This function returns t when the character pointed to by the marker mark is resident in one of the editor’s buffers.

When the function mark-file (see section Mark Components) is applied to a non-resident mark it returns the full name of the file, for example,

(setq x (make-mark (pos 0 20) "/tmp/foo.c"))
    ⇒ #<mark "/tmp/foo.c" #<pos 1 21>>
(mark-resident-p x)
    ⇒ nil
(mark-file x)
    ⇒ "/tmp/foo.c"

When a file is loaded into a buffer all existing non-resident marks are examined to see if they point to that file. If so that mark has its file component set to the buffer that the file was loaded into.

Similarly, when a buffer is deleted any marks pointing to characters in that buffer are made non-resident: their file component is set to the name of the file.

When the function which moves the cursor to the position of a specific mark (goto-mark, see section Moving to Marks) is called with a non-resident mark it will try to load the file into a buffer.

The following code fragment can be used to ensure that a mark mark is resident,

(or (mark-resident-p mark)
    (open-file (mark-file mark))
    (error "Can't make mark resident, %S" mark))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.21.4 Creating Marks

Function: make-mark &optional pos buffer-or-filename

This function allocates a new mark object and fills it in according to the supplied arguments.

It will point at a character at position pos, or the position of the cursor in the current window. Note that a copy of pos is made.

The buffer-or-filename argument specifies the file component of the mark. If buffer-or-filename is a buffer (nil or undefined means the current buffer) the mark will use it and therefore will be resident (see section Mark Residency).

Alternatively, buffer-or-filename can be a string naming the file explicitly. If the file is already loaded into a buffer that buffer will be used and the mark will be resident. Otherwise the mark will be non-resident and the string will be used as the file component.

With no arguments this function will produce a resident mark pointing at the cursor in the current buffer.

(make-mark)
    ⇒ #<mark #<buffer programmer.texi> #<pos 46 6152>>

(make-mark (buffer-start) "/tmp/foo")
    ⇒ #<mark "/tmp/foo" #<pos 0 0>>

(make-mark (pos 0 3))
    ⇒ #<mark #<buffer programmer.texi> #<pos 0 3>>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.21.5 Altering Marks

If you just want to set the position of a mark you can modify its position component (see section Mark Components). Alternately the following function may be used. When you need to set the file a mark points to the only method is to use this function.

Function: set-mark mark &optional pos buffer-or-filename

This function sets either or both of the position and file components of the mark object mark, then returns mark.

If pos is a position object the position component of mark will be set to it (a copy of it actually).

If the buffer-or-filename argument is non-nil the file component of mark will be set. This argument can be a buffer object or a string naming a file. If a named file is already in a buffer that buffer will be used instead.

(setq x (make-mark))
    ⇒ #<mark #<buffer programmer.texi> #<pos 46 6186>>
(set-mark x (buffer-start))
    ⇒ #<mark #<buffer programmer.texi> #<pos 0 0>>
(set-mark x nil "/tmp/foo")
    ⇒ #<mark "/tmp/foo" #<pos 0 0>>

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.21.6 Moving to Marks

Function: goto-mark mark

This function switches to the buffer containing mark (if necessary) and then moves the cursor to the character that the mark points to.

If the mark is not currently resident an attempt will be made to load the mark’s file into a new buffer and use that.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.22 Glyph Tables

A glyph table is a Lisp object used to define a mapping between the characters which may occur in a buffer (anything with a numeric value between 0 and 255 inclusive) and the sequences of glyphs which are drawn into a window to represent these characters.

A glyph is a image which, when rendered into the display, takes up one character position. Each character in a buffer is rendered as a sequence of 1 or more glyphs.

Function: glyph-table-p object

This function returns t when its argument is a glyph table.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.22.1 Glyph Table Basics

A glyph table is basically an array that has 256 elements; each element represents one character and contains between zero and four glyphs — the glyphs which will be printed for the character.

A special case exists for the tab character; when an element in the table contains zero glyphs, enough spaces will be printed to fill in to the next tab stop.

Function: get-glyph glyph-table character

This function returns a string containing the glyphs in the element of the glyph table glyph-table for the character character.

(get-glyph (default-glyph-table) ?a)
    ⇒ "a"

(get-glyph (default-glyph-table) ?\t)
    ⇒ ""        ;TAB is special

(get-glyph (default-glyph-table) ?\000)
    ⇒ "^@"      ;the NUL character
Function: set-glyph glyph-table character glyph-string

This function sets the sequence of glyphs used to render the character character in the glyph table glyph-table to the characters in the string glyph-string.

An error is signalled if there are more than four characters in glyph-string.

All buffers which use glyph-table for their rendering will be totally redrawn at the next redisplay.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.22.2 Glyph Positions

Position objects are usually used to refer to the position of a character in a buffer, this position (sometimes called the character position may not be the same as the position of the sequence of glyphs printed to represent the character. When a position object is used to refer to the position of a glyph it is called a glyph position.

For example, consider a line in a buffer containing the string ‘a\tb’ (where ‘\t’ represents a tab character). When this is rendered in a buffer the glyphs which will actually be drawn are,

a       b

That is, an ‘a’ glyph, followed by seven (assuming tab-size is set to 8) ‘ ’ glyphs, and lastly a ‘b’ glyph.

The character position of the ‘b’ character in the buffer is #<pos 2 line>, where line is the line’s number.

Now the confusing bit: the glyph position of the ‘bglyph is #<pos 8 line> since it is actually the ninth glyph to be drawn.

The good news is that most of the time you can forget about glyph positions, they only need to be considered when you’re thinking about how the buffer will look when rendered in the window. For example, Lisp programs which indent source code will definitely need to use glyph positions.

Two functions are provided for converting between character and glyph positions and vice versa.

Function: char-to-glyph-pos &optional pos buffer

Return a new position object containing the glyph position of the character at character position pos (or the cursor position) in the specified buffer.

Function: glyph-to-char-pos pos &optional buffer

This function returns a new position object containing the character position of the glyph printed at glyph position pos in the specified buffer.

If the glyph position pos is not the position of the first in a sequence of glyphs representing a single character the position of the next character will be returned.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.22.3 Creating Glyph Tables

Function: make-glyph-table source

This function creates a new glyph table, containing glyph sequences defined by the source argument.

If source is a glyph table it will be copied, if it’s a buffer that buffer’s glyph table will be copied or if source is nil a copy of the default glyph table will be made.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.22.4 Buffer Glyph Tables

Each buffer may define its own glyph table that will be used to provide the character-to-glyph mappings for that buffer.

Function: buffer-glyph-table &optional buffer

Returns the glyph table installed in the buffer.

Function: set-buffer-glyph-table glyph-table &optional buffer

Sets the glyph table being used in the buffer to glyph-table.

By default, each buffer uses the default glyph table. This is a glyph table set up when the editor initialise itself. The mappings it provides are very generic, for more details see @ref{Character Images}.

Function: default-glyph-table

This function returns the default glyph table.

Redefining some of the mappings in the default glyph table is an easy way to affect rendering operations, for example if I want the UK pound sign character (ASCII value is octal 243) to be printed as itself and not the usual escape sequence I can do the following,

(set-glyph (default-glyph-table) ?243 "\243")

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.23 Input Events

An input event is a Lisp object representing an action initiated by the user, i.e. a key press, pressing a mouse button and similar things.

Note that input events are often referred to as key presses, this isn’t really accurate but since most input events are key presses the term sort of stuck. Anyway, wherever the phrase ‘key press’ occurs in this manual it could be replaced by ‘input event’.

Each input event is represented by a cons cell (see section Cons Cells) containing two integers, these integers encode the actual input event. The encoding is opaque; the only way to access an event meaningfully is via the functions provided.

Function: eventp object

This function returns t if its argument is an input event.

Each event has a textual name, for the actual format of these names see @ref{Key Names}.

Functions are available to convert between the name of an event and the actual event itself, and vice versa.

Function: lookup-event event-name

Create and return a new input event whose name is event-name.

(lookup-event "Ctrl-x")
    ⇒ (120 . 9)

(lookup-event "Ctrl-Meta-LMB-Click1")
    ⇒ (1 . 58)
Function: event-name event

This function returns a string naming the input event event.

(event-name (lookup-event "Ctrl-x"))
    ⇒ "Ctrl-x"

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.24 Keymaps

A keymap is a Lisp object defining a mapping between input events (see section Input Events) and commands to be executed when the event loop (see section Event Loop) receives the input event.

Function: keymapp object

Returns t when object is a keymap.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.24.1 Types of Keymap

There are two different types of keymap; one for keymaps which contain only a few bindings, the other providing a more efficient method of storing larger numbers of bindings.

Key lists

These are used for keymaps which only contain a few bindings; they are lists whose first element is the symbol keymap. All subsequent elements define bindings, they are represented by three-element vectors. The first two are the contents of the cons cell representing the input event, the other element is the command to be invoked.

For example,

(keymap [120 9 some-command])

Since the event (120 . 9) is the key press Ctrl-x, this keymap binds the command some-command to the key press Ctrl-x.

Key tables

Key tables are used for keymaps which contain a larger number of bindings. They are vectors of 127 elements, a hash function is used to hash each event contained in the keymap into one of the 127 buckets. Each bucket is a list of key bindings in the same form as a key list (but without the keymap symbol).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.24.2 Creating Keymaps

Since there are two different types of keymap (lists and tables) there are two different functions for creating them with.

Function: make-keylist

Creates and returns a new key list containing no bindings.

(make-keylist)
    ⇒ (keymap)
Function: make-keytab

This function returns a new key table; it will be totally empty.

(make-keytab)
    ⇒ [nil nil … nil]

If you want to produce a new copy of a keymap use the copy-sequence function (see section Sequence Functions) to duplicate the source keymap.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.24.3 Binding Keys

The bind-keys function is used to install new key bindings into a keymap (either a key list or table).

Function: bind-keys keymap &rest bindings

This function installs zero or more key bindings into the keymap keymap.

Each binding is defined by two elements in the list of bindings, the first defines the name of the input event (or the event itself) and the second defines the command to be associated with the event.

For example to bind two keys in the keymap keymap; the event Ctrl-f to the command goto-next-char and the event Ctrl-b to the command goto-prev-command the following form would be used,

(bind-keys keymap
 "Ctrl-f" 'goto-next-char
 "Ctrl-b" 'goto-prev-char)
Function: unbind-keys keymap &rest keys

This function removes the bindings of the events keys (these may be the names of the events or the event objects themselves) from the keymap keymap.

(unbind-keys keymap
 "Ctrl-f"
 "Ctrl-b")

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.24.4 Key Lookup

Each time the event loop (see section Event Loop) receives an input event from the window system it searches for a binding of that event.

The variables keymap-path and next-keymap-path are used to determine the keymap environment, this is the list of keymaps which are searched when looking for the binding.

Function: lookup-event-binding event &optional reset-path

This function examines the current keymap environment for a binding of the event event (see section Input Events). If such a binding is found its command is returned, otherwise nil is returned.

If the optional reset-path argument is non-nil the next-keymap-path variable will be set to nil, otherwise it will be left with its original value.

Variable: keymap-path

A buffer-local variable providing the list of keymaps (or variables whose values are keymaps) which will be searched for a binding when the value of the next-keymap-path variable is nil.

keymap-path
    ⇒ (minor-mode-keymap texinfo-keymap global-keymap)
Variable: next-keymap-path

This variable is used to create multi-event key bindings. When it has a non-nil value it overrides the keymap-path variable when a key binding is being searched for.

After the value of this variable is used to search for a key binding it is set to nil. This means that, unless another prefix key occurred, the next input event received will be resolved through the keymap-path variable.

When this variable is set the value of the prefix-arg variable is set to the current value of the current-prefix-arg variable. This is so a prefix argument given to a multi-event command is transmitted through to the command.

For more details on multi-event bindings see Prefix Keys.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.24.5 Prefix Keys

As briefly noted in the previous section it is possible to create multi-event key bindings. The next-keymap-path variable is used to link key presses (known as prefix keys since they prefix the actual, command-invoking, binding) to a new keymap environment which will be used to resolve the next key press. This method allows key sequences of an arbitrary length to be used.

The best way to explain this is probably with an example. Consider the following,

(setq entry-keymap (make-keylist))
(bind-keys entry-keymap
 "Ctrl-x" '(setq next-keymap-path '(second-keymap)))

(setq second-keymap (make-keylist))
(bind-keys second-keymap
 "Ctrl-j" 'some-command)

Two keymaps are created, the first of which, entry-keymap, would be placed in the keymap-path list. When Ctrl-x is typed the associated command would be invoked, installing the next piece of the chain, the second-keymap into the next-keymap-path variable.

So, after Ctrl-x is typed the keymap environment will be the list of keymaps (second-keymap), subsequently typing Ctrl-j would then invoke the command some-command.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.24.6 Standard Keymaps

Several keymaps are predefined by Jade.

global-keymap

This keymap is the root of the global keymap structure; all buffers which allow themselves to be edited have this keymap in their keymap-path.

ctrl-x-keymap

This is linked to the global-keymap via the key Ctrl-x.

ctrl-x-4-keymap

The keymap for the global prefix Ctrl-x 4.

ctrl-x-5-keymap

The keymap for the global prefix Ctrl-x 5.

user-keymap

This keymap is only to be bound by the user, not by programmers! It’s linked to the global prefix Ctrl-c and is intended to allow users to bind unmodified keys (modified keys with the prefix Ctrl-c are usually bound to by modes) to commands which don’t have bindings by default.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25 Event Loop

Whenever Jade is not executing a command it is sitting in the event loop. This is where the editor waits for any input events which the window system sends it, invokes the commands they resolve to and then redraws all the editor windows to reflect the modifications made to any buffers.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.1 Event Loop Actions

When Jade appears to be doing nothing it is probably sitting in the event loop waiting for input to arrive. When an input event arrives from the window system it is processed according to its type.

If the input event is a keyboard or mouse button event it is converted into a Lisp input event (see section Input Events) and the current keymap environment is searched for a binding of that event (see section Key Lookup). If a binding of the event is found it defines a command (see section Commands) to be invoked, the call-command function (see section Calling Commands) is used to do this.

When no binding of a key or mouse button event exists the hook, unbound-key-hook, is evaluated; if this returns nil and the event is a keyboard event and no prefix keys (see section Prefix Keys) preceded it the key is inserted into the current buffer before the cursor.

If the event was not a keyboard or mouse button event the event loop will deal with it itself; these events are generally things which should be transparent to Lisp programs (i.e. window exposure notification, etc…).

One exception is the event sent when a window should be closed (i.e. hitting the close-window gadget in Intuition, or sending a window the delete-window atom in X), the hook window-closed-hook is called. By default this hook is setup to invoke the close-window command (as bound to Ctrl-x 0).

Another function of the event loop is to wait for input from any of the subprocesses currently executing (see section Processes); whenever input is pending in a subprocess’s standard output channel it is copied to the process objects’s output stream.

After processing an event or piece of subprocess output the event loop will redisplay any part of any window which needs to be updated; this may be necessary if a window is now displaying a different part of a buffer, or if the part of the buffer it is displaying has been modified. See section Rendering.

Normally Jade will ‘sleep’ while it’s waiting for input, however after every second it spends asleep the event loop will wake up and try to do a sequence of operations; for more details see Idle Actions.

Hook: unbound-key-hook

The hook called when an unbound input event is received.

Hook: window-closed-hook

The hook called when an event is received telling Jade to close a window; the current window is the one which should be closed.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.2 Commands

A command is a Lisp function which may be called interactively, that is, either as a binding of an input event or by name (with the Meta-x key sequence).

Commands are defined in the same way as functions, using the defun special form; the body forms of a command must contain an interactive declaration. This shows that the function may be called interactively part and tells the call-command function how to compute the argument values to apply to the command.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.2.1 Interactive Declarations

When you define a command (using the defun special form in the same way you would define a function) the first of its body forms (after the optional documentation string) must be an interactive declaration.

This form looks like a call to the special form interactive, in actual fact this special form always returns nil and has no side-effects. The only effect of this form is to show the call-command function, which invokes commands, that this function definition is actually a command (i.e. it may be called interactively). The second element of the declaration form (after the interactive symbol) defines how the argument values applied to the command are computed.

The structure of an interactive declaration, then, is:

(interactive [calling-spec])

When a command is defined this is how it is defined with the interactive declaration:

(defun some-command (arg1)
  "Optional documentation string."
  (interactive …)
  …

The calling-spec form defines the argument values applied to the command when it is called interactively, it may be one of,

Some example interactive declarations,

;; No arguments, but the function may be called
;; as a command.
(interactive)

;; One argument, an existing buffer
(interactive "bBuffer to kill:")

;; If buffer isn't read-only, three arguments:
;; nil, a Lisp object and t.
(interactive "*\nxLisp form:\nt")

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.2.2 Prefix Arguments

When the you invoke a command it is often useful to be able to specify arguments which the command will act on. Prefix arguments are used for this purpose. They are called prefix arguments since they are entered before the command is invoked, and therefore prefix the command with an argument. Prefix arguments are usually integers.

The easiest way for a command to access these arguments is through its interactive declaration (see section Interactive Declarations) and the ‘N’, ‘p’ and ‘P’ code letters.

The two variables prefix-arg and current-prefix-arg are used to store prefix arguments. Whenever a command is invoked the value of prefix-arg is moved to current-prefix-arg and prefix-arg set to nil. This allows commands to set the prefix argument of the next command by assigning a value to the prefix-arg variable.

These variables store an object known as the raw prefix argument, when a command is called it normally uses the numeric prefix argument, this is an integer created from the raw argument using the following rules,

The prefix-numeric-argument function is used to convert the raw argument into a numeric value.

Function: prefix-numeric-argument raw-arg

Returns the numeric value of the raw prefix argument raw-arg.

Variable: prefix-arg

The value of the raw prefix argument used by the next command to be invoked.

Variable: current-prefix-arg

The value of the raw prefix argument of the current command.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.2.3 Calling Commands

When a command is to be invoked, the call-command function is used. This builds a list of argument values to apply to the command (using its interactive declaration) then calls the command.

Function: commandp object

This function returns t if its argument may be called interactively. If object is a function (i.e. a symbol or a lambda-expression) it is a command if it contains an interactive declaration (see section Interactive Declarations).

The only other object which is a command is a function call form; the use of these types of commands is discouraged but they can be useful sometimes.

(commandp 'setq)
    ⇒ nil

(commandp 'isearch-forward)
    ⇒ t

(commandp '(setq x 20))
    ⇒ t
Command: call-command command &optional prefix-arg

This function calls the command command interactively. See the documentation of commandp above for what constitutes a command.

If the prefix-argument is non-nil it defines the value of the current-prefix-arg variable for this command, normally the value of this variable would be taken from the global prefix-arg variable.

When called interactively, this function will prompt for a command to invoke. This function is bound to the key sequence Meta-x.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.2.4 Example Commands

This is a couple of simple commands, taken from the source code of Jade.

(defun backward-kill-word (count)
  "Kill COUNT words backwards."
  (interactive "p")
  (kill-area (forward-word (- count)) (cursor-pos)))
(defun find-file (name)
  "Sets the current buffer to that containing the file NAME, if
NAME is unspecified it will be prompted for. If the file is not
already in memory `open-file' will be used to load it."
  (interactive "FFind file: ")
  (goto-buffer (open-file name)))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.3 Event Loop Information

Variable: this-command

This variable contains the value of the command currently being executed.

Variable: last-command

Holds the previously executed command.

Function: current-event

Returns the event which caused this command to be invoked.

Function: current-event-string

Returns a string which is the ‘cooked’ representation of the current event.

Function: last-event

Returns the event which caused the previous command.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.4 Recursive Edits

Entering a recursive edit basically means to recursively call the event loop from a Lisp program, this latest instance of the event loop will work like the normal event loop (the top level event loop) until it is exited, at which point the Lisp program will regain control.

Recursive edits should be used sparingly since they can be very confusing for the user; they are mainly used to implement interactive user interfaces in the middle of a Lisp program or command. This can be achieved by installing a special set of key bindings for the duration of the recursive edit.

When programming with recursive edits a lot of care should be used; if proper cautions aren’t taken an abnormal exit from a recursive error can wreak havoc.

Note that throw and catch (see section Catch and Throw) can be used through recursive edits with no problems; the recursive edit will automatically be aborted.

Command: recursive-edit

Enter a new level of recursive editing.

Function: recursion-depth

This function returns the number of recursive edits currently in progress. When in the top level this will return zero.

Command: top-level

Abort all recursive edits, control will be passed straight back to the top level event loop.

Command: abort-recursive-edit &optional edit-value

This function aborts the outermost recursive edit (but never the top level) returning edit-value (or nil) from the instance of the recursive-edit function which invoked this recursive edit.

When using recursive edits it is important to remember that the buffer and window configuration that existed when the edit was entered may not still exist when the recursive edit terminates. This means that some care has to be taken when installing and removing buffer-local values of variables. For example, the ask-y-or-n function, which uses a recursive edit, does something like this:

(let
    ;; First save the old values of the variables to be altered.
    ;; The variables can't be directly bound to since this doesn't
    ;; work properly with buffer-local variables :-(
    ((old-u-k-h unbound-key-hook)
     (old-k-p keymap-path)
     (old-buf (current-buffer)))
  ;; Now install the new values
  (setq unbound-key-hook (cons #'(lambda ()
                                   (beep)
                                   t)
                               nil)
        keymap-path '(y-or-n-keymap)
        status-line-cursor t)
  ;; This is the important bit; ensure that the old values will
  ;; be reinstated even if an abnormal exit occurs. Also note
  ;; that they are always set in the original buffer.
  (unwind-protect
      (catch 'ask
        (recursive-edit))
    (with-buffer old-buf
      (setq keymap-path old-k-p
            unbound-key-hook old-u-k-h
            status-line-cursor nil)))))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.5 Reading Events

Most of the time it is unnecessary to read events manually; usually a special-purpose keymap will be sufficient. However it is possible to read single events from a Lisp program.

Function: read-event &optional prompt-string

Read the next input event from the current window and return it. If the optional string prompt-string is defined it is a one-line message to display while waiting for the event.

Note that this function isn’t very efficient when used heavily; it uses a recursive edit and the unbound-key-hook to read the event. If possible use a keymap instead.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.25.6 Idle Actions

When a second goes by with no input events arriving, the editor assumes that is has idle time available, and tries to use this period to do non-essential tasks. These tasks include things like garbage collection and auto-saving modified files.

Whenever idle time is detected one of the following tasks is performed. They are listed in order of preference; once one of these has been done Jade will again sleep until an input event is received or another second elapses, whichever happens soonest.

  1. If prefix keys have been entered and are outstanding their names will be printed in the status line. See section Prefix Keys.
  2. If any buffers are ready to be auto-saved (i.e. enough time since their last auto-save has elapsed) one of these buffers will be auto-saved. Only one buffer is ever saved in each idle period. @xref{Auto-Saving Files}.
  3. If the total size of the data objects allocated since the last garbage collection is greater than the value of the idle-gc-threshold variable then the garbage collector is invoked.
    Variable: idle-garbage-threshold

    The number of bytes of Lisp data which must have been allocated since the last garbage collection for the garbage collector to be called in an idle period.

    It is a good idea to set this variable much lower than the value of the gc-threshold variable since garbage collections happening while Jade is idle should usually be unnoticeable.

    See section Garbage Collection.

  4. If none of the other tasks have been performed the idle-hook hook is dispatched. I’m not sure what this hook could be used for but you never know…

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.26 Editing Files

The main function of Jade is editing files of text; buffers (see section Buffers) are used to contain files to be edited. When the buffer is displayed in a window (see section Windows) the user can edit the file interactively using the keyboard and mouse.

This chapter documents the Lisp interface to all this; for the user’s perspective see @ref{Loading and Saving Files}.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.26.1 Reading Files Info Buffers

Before a file can be edited it must be read into a buffer, this buffer can then be modified and later saved over the original contents of the file. Note that editing a buffer makes no changes to the contents of the file on disk; the buffer will have to be written back to the file on the disk first. See section Writing Buffers.

Function: open-file file-name

This function returns a buffer containing the contents of the file called file-name.

If an existing buffer contains the file called file-name that buffer is returned. Otherwise a new buffer is created and the file read into it.

When the file has successfully been read into the new buffer any local variables defined at the end of the file are processed (@pxref{File Variables}) and the function init-mode is used to try to install a major mode for the new buffer. See section Installing Modes.

If file may not be written to the buffer is marked to be read-only.

Note that the hook, read-file-hook, can be used to read the contents of the file into the buffer if necessary. See the documentation of this hook for more details.

Hook: read-file-hook

This hook is called by the open-file function when it wants to read a file into a buffer. If the hook returns a non-nil value open-file assumes that one member of the hook was successful in reading the file, otherwise the file will be read verbatim into the buffer.

The hook is called with two arguments: the name of the file and the buffer to read it into respectively.

If any members of the hook decide to read the file they’re responsible for setting the buffer-file-name component of the buffer and the buffer’s buffer-file-modtime variables to suitable values.

See the ‘gzip.jl’ file in the Lisp library directory for an example of how this hook can be used (in this case to automatically decompress gzip’ed files).

Function: read-buffer file-or-name &optional buffer

Replaces all text contained by the buffer by the contents of the file file-or-name. This can be either a Lisp file object, in which case bytes will be read until the end of the file is reached, or the name of a file to read.

The following commands are used to read a file into a buffer then display that buffer in the current buffer.

Command: find-file file-name

Display a buffer containing the file file-name in the current window.

When called interactively file-name will be prompted for.

Command: find-alternate-file file-name

Replace the current buffer with one displaying the file file-name. What actually happens is that the current buffer is killed and a new one created.

When called interactively this function will prompt for its argument.

Command: find-file-read-only file-name

Display a buffer containing file-name in the current window. The buffer will be read-only.

This will prompt for its argument when called interactively.

There is also a command to insert the contents of a file into a buffer.

Command: insert-file file-name &optional buffer

This command inserts the contents of the file file-name into the buffer buffer (or the current buffer).

The hook insert-file-hook is called with file-name as an argument to try and insert the file (into the current buffer at the current position). If this hook returns nil (i.e. none of the functions in the hook inserted the file) it will be inserted normally.

If called interactively, file-name will be prompted for.

Hook: insert-file-hook

Hook used to insert a file (given as the hook’s argument) into the current buffer at the current cursor position.

Command: revert-buffer &optional buffer

Reloads the contents of the buffer from the file it was originally loaded from; if any unsaved modifications will be lost the user is asked for confirmation.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.26.2 Writing Buffers

After a buffer containing a file has been edited it must be written back to a file on disk, otherwise the modifications will disappear when Jade is exited!

Function: write-buffer &optional file-name buffer

The primitive to save a buffer’s contents. The contents of the buffer buffer (or the current buffer) is written to the file file-name (or the buffer-file-name component of the buffer).

Function: write-buffer-area start-pos end-pos file-name &optional buffer

Writes the region of text from start-pos up to, but not including, end-pos to the file file-name.

Function: write-file buffer &optional file-name

Writes the contents of the buffer buffer to a file on disk. If the optional argument file-name is defined it names the file to write to. Otherwise, the value of the buffer’s buffer-file-name component is used.

The hook write-file-hook is used to try and write the file, if this fails (i.e. the hook returns nil) the buffer is saved normally.

A backup may be made of the file to be overwritten (see section Making Backups) and the protection-modes of the overwritten file will be preserved if possible.

Hook: write-file-hook

This hook is called by the write-file function when a buffer is to be saved. If no member of the hook actually writes the buffer to a file (i.e. the hook returns nil) write-file will do it itself in a standard way.

The hook function is responsible for creating any required backup file (use the function backup-file, see section Making Backups) and resetting the protection-modes of the new file to their original value.

See the file ‘gzip.jl’ in the Lisp library directory for an example, it uses it to compress certain files automatically.

Remember to make sure that if a member of the hook writes the buffer it returns a non-nil value!

The following code fragment defines a function which does what the default action of write-file is,

(defun write-file-default-action (buffer name)
  (let
      ((modes (when (file-exists-p name) (file-modes name))))
    (backup-file name)
    (when (write-buffer name buffer)
      (when modes
        (set-file-modes name modes))
       t)))

The following commands call the write-file function to write out a buffer, they also update the various variables containing information about the state of the buffer. It is normally unnecessary to call write-file yourself; these commands should suffice.

Command: save-file &optional buffer

This command writes the buffer to the file that it was loaded from and then updates all the necessary buffer-local variables.

If the file on disk has been modified since it was read into the buffer the user is asked if they really want to save it (and risk losing a version of the file).

If no modifications have been made to the file since it was last saved it won’t be saved again.

Any auto-saved version of the file is deleted.

Command: save-file-as new-name &optional buffer

This command saves the buffer buffer (or the current buffer) to the file called new-name. The buffer-file-name is set to new-name and all the necessary buffer-local variables are updated.

If an auto-saved version of file-name exists it is deleted.

When called interactively new-name will be prompted for.

Command: save-some-buffers

For each buffer which contains unsaved modifications the user is asked whether or not to save the buffer.

t is returned if no unsaved modifications exist in any buffers (i.e. the user replied ‘yes’ to all files which could be saved).

Command: save-and-quit

Calls save-some-buffers then quits Jade (after asking the user if any unsaved buffers may be discarded).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.26.3 Buffer Date Stamps

When a file is read into a buffer its (the file’s) time of last modification is recorded, this can later be used to see if the file (on disk) has been modified since it was loaded into a buffer.

Variable: buffer-file-modtime

This buffer-local variable contains the file-modtime of the file stored in the buffer when it (the file) was last read from disk.

See section File Information.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.26.4 Buffer Modification Counts

Two buffer-local variables are used to record the modification count (see section Buffer Attributes) of a buffer when it is saved.

Variable: last-save-changes

A buffer-local variable containing the number of modifications made to the buffer the last time it was saved (either auto-saved or by the user).

Variable: last-user-save-changes

This buffer-local variable holds the number of modifications made to the buffer when it was last saved by the user.

Variable: last-save-time

A buffer-local variable holding the system time (from the current-time function) from when the buffer was last saved (auto-saved or by the user).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.26.5 Making Backups

For details of the variables which control whether and how backup files are made see @ref{Backup Files}.

Function: backup-file file-name

When necessary, make a backup of the file file-name. This should be called when the file file-name is about to be overwritten.

Note that this function doesn’t define whether or not the file file-name will still exist when this function returns. Sometimes it will, sometimes it won’t…


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.26.6 Controlling Auto-Saves

For the documentation of the variables controlling the making of auto-save files see @ref{Auto-Saving Files}.

Function: make-auto-save-name file-name

Returns a string naming the file which should hold the auto-saved version of the file file-name.

(make-auto-save-name "/tmp/foo")
    ⇒ "/tmp/#foo#"
Function: auto-save-function buffer

This function is called automatically whenever a buffer (buffer) needs to be auto-saved.

It firstly tries to use the auto-save-hook hook to auto-save the file, if this fails (i.e. the hook returns nil) it is done manually (using the write-buffer function).

Hook: auto-save-hook

Called by auto-save-function (with the buffer as an argument) when a buffer is to be auto-saved.

Command: delete-auto-save-file &optional buffer

This command deletes the auto-saved version of the buffer, if one exists.

Function: auto-save-file-newer-p file-name

This function returns t when there is an auto-saved version of the file called file-name which is newer than file-name.

Command: recover-file &optional buffer

If an auto-saved version of the buffer exists it is read into the buffer, overwriting its current contents. If any changes to the buffer will be lost the user is asked for confirmation.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27 Text

This chapter describes all the functions used for editing and referencing the text stored in a buffer.

Note that where a command has a count argument specifying the number of items to process; this argument will normally use the numeric value of the prefix argument when the function is called interactively.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.1 Buffer Contents

Function: get-char &optional pos buffer

Returns the character at position pos (or the cursor position) in the specified buffer.

Function: set-char character &optional pos buffer

Sets the character at position pos (or the cursor) in the buffer buffer (or the current buffer) to the character character, then returns character.

Function: copy-area start-pos end-pos &optional buffer

This function creates and returns a string containing the contents of the buffer buffer (or the current buffer) between the two positions start-pos (inclusive) and end-pos (exclusive).

Function: copy-block

If a block is marked in the current window returns a string containing the text marked then unmark the block, otherwise returns nil.

If the marked block is rectangular the copy-rect function (see section Rectangular Editing is used to get the string.

Function: clear-buffer &optional buffer

Removes all text from the specified buffer. No precautions are taken against losing any unsaved modifications that the buffer might contain!


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.2 Insertion Functions

Note that the format function can be used to provide formatted insertion; simply give it a suitable output stream. See section Streams.

Command: insert string &optional pos buffer

Inserts the string string into the specified buffer at the cursor position (or pos, if defined).

Returns the position of the first character after the end of the inserted text.

When called interactively the string to insert is prompted for.

Command: insert-block &optional pos

If a block is marked in the current window, the text it contains is inserted at the position pos (or the cursor) and the block is unmarked.

If the marked block is rectangular the block is copied and inserted as a rectangle.

Command: yank &optional dont-yank-block

Inserts a string before the cursor. If a block is marked in the current buffer and dont-yank-block is nil insert the text in the block. Else yank the last killed text. See section Kill Functions.

When called interactively the raw prefix arg is used as the value of the dont-yank-block argument.

Command: yank-to-mouse

Moves the cursor to the current position of the mouse pointer then calls the yank function.

Command: open-line count

Break the current line at the cursor, creating count new lines. The cursor is left in its original position.

Command: split-line

This function inserts a newline character (‘\n’) at the current cursor position.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.3 Deletion Functions

Function: delete-area start-pos end-pos &optional buffer

This function deletes all text starting from the position start-pos up to, but not including, the position end-pos.

If buffer is defined it specifies the buffer to delete from, usually the current buffer is used.

Function: cut-area start-pos end-pos &optional buffer

This function is a combination of the copy-area and delete-area functions; it copies the specified region then deletes it before returning the copy it made.

(cut-area start end)
≡
(let
    ((text (copy-area start end)))
  (delete-area start end)
  text)
Command: delete-block

Deletes the block marked in the current window (if one exists). This function knows about rectangular blocks.

Function: cut-block

Copies the block marked in the current window if one exists, then deletes it before returning the copied string. If the block is rectangular it is copied and cut as a rectangle.

Command: delete-char count

Deletes count characters, starting at the cursor position and working forwards.

Command: backspace-char count

Deletes the count characters preceding the cursor, if the cursor is past the end of the line, simply move count characters to the left.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.4 Kill Functions

Killing a piece of text means to delete it then store a copy of it in a special place. This string is later available to other functions, such as yank which inserts it into a buffer.

Function: kill-string string

This function adds the string string to the kill buffer. If the last command also killed something string is appended to the current value of the kill buffer.

The this-command variable is set to the value kill to flag that the current command did some killing.

Returns string.

Function: killed-string &optional depth

Returns the string in the kill buffer number depth, currently only the last kill is stored so depth must either be zero or undefined.

Command: kill-area start-pos end-pos

This command kills a region of text in the current buffer, from start-pos up to, but not including, end-pos.

When called interactively the currently marked block (if one exists) is used to provide the two arguments, then the block is unmarked.

Command: copy-area-as-kill start-pos end-pos

Similar to kill-area except that the region killed is not actually deleted from the buffer.

Command: kill-block

Kills the block marked in the current window.

Command: copy-block-as-kill

Kills the block marked in this window but doesn’t actually delete it from the buffer.

Command: kill-line &optional arg

This command kills lines from the cursor position. arg is a raw prefix argument (see section Prefix Arguments). What gets killed depends on arg,

Command: kill-whole-line count

Kills all of the count (an integer) next following lines.

Command: kill-word count

Kills count words, starting at the cursor position.

When called interactively count is the numeric prefix arg.

Command: backwards-kill-word count

Kills the count previous words, starting from the cursor.

When called interactively count is the numeric prefix arg.

Command: kill-exp &optional count

Kill count expressions from the cursor position. See section Mode-Specific Expressions.

Command: backward-kill-exp &optional count

Kills count expressions, working backwards from the cursor. See section Mode-Specific Expressions.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.5 Transpose Functions

Transposing two regions of text in a buffer means to swap their positions.

Function: transpose-items forward-item-fun backward-item-fun count

This function transposes the areas defined by the functions forward-item-fun and backward-item-fun (these functions must work in the style of forward-word and backward-word respectively).

What actually happens is that the item before the cursor is dragged forward over the next count items.

Command: transpose-words count

Uses transpose-items with each item being a word.

When called interactively, count is the value of the numeric prefix argument.

Command: transpose-chars count

Transposes characters.

Command: transpose-exps count

If the major mode in the current buffer has installed functions which define expressions then this command transposes expressions. See section Mode-Specific Expressions.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.6 Indentation Functions

Function: indent-pos &optional pos buffer

This function returns the glyph position (see section Glyph Positions) of the first character in the line pointed to by pos (or the cursor) which is not a TAB or SPC character.

Function: set-indent-pos indent-pos &optional buffer only-spaces

Sets the indentation of the line pointed to by pos to the column pointed to by pos by putting the optimal sequence of TAB and SPC characters at the start of the line.

If the only-spaces argument is non-nil no TAB characters will be used.

Command: indent-to column &optional only-spaces

This function inserts enough TAB and SPC characters to move the cursor to glyph column column.

If the only-spaces argument is non-nil no TAB characters are used.

Note that column counts from zero.

When called interactively the column argument is either the numeric value of the prefix argument or, if no prefix argument has been entered, the result of prompting for a number.

Command: tab-with-spaces

This command inserts enough spaces at the cursor position to move the cursor to the next tab stop.

Some major modes provide their own method of indentation (for example Lisp mode will indent Lisp programs in the proper style), see Mode-Specific Indentation.

Command: indent-line

If the current buffer has a method for indentation installed, use it to indent the current line to its correct depth.

Command: newline-and-indent

Insert a newline character, then indent the new line; if no function for indenting lines has been installed in this buffer a single TAB character is inserted.

Command: indent-area start-pos end-pos

Uses the buffer’s indentation method to indent all lines in the specified region to their correct depth.

When called interactively the currently-marked block is used to get the values of the two arguments, the block is then unmarked.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.7 Translation Functions

Function: translate-area start-pos end-pos translation-table &optional buffer

This function applies the mapping translation-table to each character in the region starting at the position start-pos up to, but not including, end-pos.

translation-table is a string, each character represents the mapping for an ASCII character of that character’s position in the string. If the string is less than 256 characters in length any undefined characters will remain unchanged (i.e. a translation-table of ‘’ would leave the region unaltered).

Function: translate-string string translation-table

This function uses a similar method to that used in the translate-area function. Instead of applying the mapping to a region of a buffer it applies it to the string string. string is returned (after being modified).

Note that the string really is modified, no copy is made!

(translate-string "abc" upcase-table)
    ⇒ "ABC"
Variable: upcase-table

This is a 256-character long string which may be used as a translation table to convert from lower-case to upper-case with the functions translate-string and translate-area.

Variable: downcase-table

Similar to upcase-table except that it is used to convert from upper-case to lower-case.

The following functions use the translation functions and the two translation tables described above.

Command: upcase-area start-pos end-pos &optional buffer

Makes all alphabetic characters in the specified region of text upper-case.

When called interactively uses the block marks for its arguments; note that this won’t work properly with rectangular blocks.

Command: downcase-area start-pos end-pos &optional buffer

Similar to upcase-area but makes all alphabetic characters lower-case.

Command: upcase-word count

For the next count words starting at the cursor position, make their alphabetic characters upper-case.

Command: downcase-word count

Does the opposite of upcase-word, makes words lower-case!

Command: capitalize-word

The first character of this word (normally the one under the cursor) is made upper-case, the rest lower.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.8 Searching and Matching Functions

The most powerful of the searching and matching functions are those using regular expressions, for details of the regexp syntax used by Jade see @ref{Regular Expressions}.

Note that the regexp matcher does not work across lines, at the moment no regexp may span more than one line. Also the regexp routines choke on NUL bytes; hopefully I’ll correct these problems soon…


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.8.1 Searching Buffers

Function: find-next-regexp regexp &optional pos buffer ignore-case

This function returns the position of the next substring in the buffer matching the regular expression string regexp. It starts searching at pos, or the cursor position if pos is undefined.

If no match of the regexp occurs before the end of the buffer nil is returned.

If the ignore-case argument is non-nil then the case of matched strings is ignored (note that character ranges are still case-significant).

Function: find-prev-regexp regexp &optional pos buffer ignore-case

Similar to find-next-regexp except this searches in the opposite direction, from pos (or the cursor) to the start of the buffer.

Function: find-next-string string &optional pos buffer

Scans forwards from pos (or the cursor), in buffer (or the current buffer), looking for a match with the string string. Returns the position of the next match or nil.

Note that matches can’t span more than one line.

Function: find-prev-string string &optional pos buffer

A backwards-searching version of find-next-string.

Function: find-next-char character &optional pos buffer

Search forwards for an occurrence of the character character and returns its position, or nil if no occurrence exists.

Function: find-prev-char character &optional pos buffer

This function searches backwards for an occurrence of the character character.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.8.2 String Matching

Function: looking-at regexp &optional pos buffer ignore-case

Returns t if the regular expression regexp matches the text at position pos in the buffer buffer (or the current buffer).

Only the text from pos to the end of the line is matched against.

Function: regexp-match regexp string &optional ignore-case

This function returns t if the regular expression regexp matches the string string.

Note that the match is unanchored so if you want test for a match of the whole of string use the ‘^’ and ‘$’ regexp meta-characters. For example,

(regexp-match "(a|b)+" "fooabababar")
    ⇒ t

(regexp-match "^(a|b)+$" "fooabababar")
    ⇒ nil

(regexp-match "^(a|b)+$" "ababbabba")
    ⇒ t

When the ignore-case argument is non-nil the case of strings being matched is insignificant (except in character ranges).

Function: regexp-expand regexp string template &optional ignore-case

This function matches the regular expression regexp against the string string, if the match is successful a string is created by expanding the template string template.

For details of what meta-characters are allowed in template see @ref{Regular Expressions}.

(regexp-expand "^([a-z]+):([0-9]+)$"
               "foobar:42"
               "The \\1 is \\2.")
    ⇒ "The foobar is 42."
Function: regexp-match-line regexp &optional line-pos buffer ignore-case

This function is similar to regexp-match, instead of explicitly supplying the string to match against it is one whole line of the specified buffer, the line pointed to by line-pos (or the line that the cursor is on).

t is returned if the match is successful.

Function: regexp-expand-line regexp template &optional line-pos buffer ignore-case

As regexp-match-line is similar to regexp-match, this function is similar to regexp-expand.

The whole of the line at the position line-pos (or the cursor) is matched with the regular expression regexp. If the match is successful the template is used to expand a string which is returned.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.8.3 Replacing Strings

Function: replace-regexp regexp template &optional pos buffer ignore-case

If a substring of the buffer at pos (or the cursor) matches the regular expression regexp the text that matched is replaced with the result of expanding the template string template.

For details about templates see @ref{Regular Expressions}.

nil is returned if the match failed, and therefore no replacement occurred.

Function: replace-string old-string new-string &optional pos buffer

If a substring of the buffer at pos (or the cursor) matches the string old-string it is replaced by the string new-string.

If the match fails nil is returned, otherwise some non-nil value.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.8.4 Regexp Functions

It is often useful to construct regular expressions by concatenating several strings together; the problem with doing this is you may not know if a string contains any characters which the regexp compiler reacts specially to (i.e. ‘*’, ‘|’, …). Obviously these characters should be protected by a backslash, the following function will do this for you.

Function: regexp-quote string

This function returns a new version of the string string, any characters in string which are regexp meta-characters are quoted with a backslash.

If the string contains no meta-characters the original string is returned, without being copied.

(regexp-quote "foo*bar+baz")
    ⇒ "foo\\*bar\\+baz"

Note that in the above example the backslashes in the returned string are only single backslashes; the print functions print a single backslash character as ‘\\’ so they can be read back in.

This function is usually used when a part of a regexp being constructed is unknown at compile time, often provided by the user.

As the section describing regexp syntax notes, the strings that parenthesised expressions match are recorded, the following two functions allow Lisp programs to access the positions of these strings.

Function: match-start &optional expression-index

This function returns the position which the parenthesised expression number expression-index started at in the last successful regexp match.

If expression-index is nil or zero the start of the whole string matched is returned instead.

The returned value will either be a position object if the last match was in a buffer, or an integer if the last match was in a string (i.e. regexp-match).

(regexp-match "foo(bar)" "xyzfoobarsaalsd")
    ⇒ t
(match-start)
    ⇒ 3
(match-start 1)
    ⇒ 6
Function: match-end &optional expression-index

Return the position which the parenthesised expression number expression-index ended at in the last successful regexp match.

If expression-index is nil or zero the end of the whole match is returned instead.

The returned value will either be a position object if the last match was in a buffer, or an integer if the last match was in a string (i.e. regexp-match).

(regexp-match "foo(bar)" "xyzfoobarsaalsd")
    ⇒ t
(match-end)
    ⇒ 9
(match-end 1)
    ⇒ 9

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.9 Rectangular Editing

These functions are used to manipulate rectangular regions of buffers. Two position objects are used to define a rectangle, these represent opposite corners of the rectangle. Note that the corner on the right hand side of the rectangle specifies the column after the last column included in the rectangle.

Function: delete-rect start-pos end-pos &optional buffer

This function deletes a rectangle, defined by start-pos and end-pos, from the specified buffer.

Function: copy-rect start-pos end-pos &optional buffer

Returns a string containing the rectangle of text defined by the two positions start-pos and end-pos. Any TAB characters are expanded to SPC characters, newline characters mark the end of each line in the rectangle.

Function: cut-rect start-pos end-pos &optional buffer

A combination of the copy-rect and delete-rect functions; it makes a copy of the rectangle’s contents which is returned after the rectangle is deleted from the buffer.

Command: insert-rect string &optional pos buffer

Inserts the string string into the buffer at the specified position, treating string as a rectangle of text. This means that each successive line of string (separated by newline characters) is inserted at the same column in successive lines.

If the end of the buffer is reached and there is still some of the string left to insert extra lines are created at the end of the buffer.

Command: yank-rectangle &optional dont-yank-block

This function is similar to the yank function (see section Insertion Functions), except that it uses the insert-rect function to insert the piece of text.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.10 Controlling Undo

For the description of one part of controlling the undo feature, the maximum size of the undo-list, see @ref{Undo}.

Variable: buffer-record-undo

A buffer-local variable which, when set to nil, stops any undo-information being recorded for the buffer.

When a buffer is created, this variable is always set to t.

Variable: buffer-undo-list

This buffer-local variable stores the actual list of undo-information; each element defines one modification to the buffer.

Don’t try to be clever and access the contents of this list; the structure may well change in future revisions of Jade.

The only thing you’re allowed to do is set it to nil, this clears all undo-information for the buffer.

Command: undo

Undo every change to the contents of the buffer back to the previous command. Successive calls to this command work backwards through the buffer’s undo-list.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.27.11 Miscellaneous Text Functions

Function: empty-line-p &optional pos buffer

This function returns t if the line pointed to by pos (or by the cursor) consists totally of TAB or SPC characters.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.28 Writing Modes

Modes are used to customise individual buffers so that the text it contains can be edited in a special way. Each buffer has a single Major mode, tailoring the buffer to the type of file contained in it (i.e. C source code uses c-mode). @xref{Editing Modes}.

Minor modes provide individual features which may be enabled and disabled individually, each buffer may have any number of minor modes enabled at once. @xref{Minor Modes}.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.28.1 Writing Major Modes

Each major mode must define a command whose name ends in ‘-mode’ (i.e. c-mode, lisp-mode, etc…). This command is called when the major mode is to be installed in the current buffer. It’s first action must be to check for an already installed mode and remove it. The following code fragment does this,

(when major-mode-kill
  (funcall major-mode-kill))

All major modes must do this!

Now the major mode is free to install itself; generally this will entail setting the buffer-local values of the mode-name, major-mode, major-mode-kill and keymap-path variables. For example the lisp-mode sets these variables as follows,

(setq mode-name "Lisp"
      major-mode 'lisp-mode
      major-mode-kill 'lisp-mode-kill
      keymap-path (cons 'lisp-mode-keymap keymap-path))

Note how the major mode’s own keymap (with all the mode’s local key bindings installed in it) is consed onto the front of the keymap-path; this ensures that mode-local bindings take precedence over bindings in the global keymaps.

After installing itself a major mode should call a hook (generally called x-mode-hook where x is the name of the mode) to allow customisation of the mode itself.

The major-mode-kill variable holds a function to be called when the major mode is to be removed from the current buffer; basically it should remove its keymap and set all the mode-local variables to nil. For example the lisp-mode-kill function does the following to negate the effects of the code fragment above,

(setq keymap-path (delq 'lisp-mode-keymap keymap-path)
      major-mode nil
      major-mode-kill nil
      mode-name nil)
Variable: major-mode

This buffer-local variable contains the symbol whose function definition was used to install the buffer’s major mode (i.e. c-mode, etc…).

When it is nil the buffer uses the ‘generic’ mode; this is simply the bog standard editor.

Variable: major-mode-kill

This buffer-local variable contains the function which should be called to remove the buffer’s currently installed major-mode.

Note that the kill-buffer function calls this (if it’s non-nil) just before destroying a buffer; so if necessary, an error signalled within this function will prevent a buffer being killed.

Variable: mode-name

A buffer-local variable containing the ‘pretty’ name of the buffer’s major mode, a string which will be printed in the status line.

Many modes bind commands to keys with the prefix Ctrl-c, to save each mode creating a new root keymap the buffer-local variable ctrl-c-keymap exists.

Variable: ctrl-c-keymap

This buffer-local variable can be used by major modes to hang their keymap for the Ctrl-c prefix from. Simply set this variable to the keymap your mode wants to be installed after a Ctrl-c prefix.

The definitions for many different types of modes can be found in Jade’s lisp directory.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.28.2 Installing Modes

Before a major mode can be used to edit a buffer with it must be installed in that buffer. The most straightforward method of doing this is simply to invoke the mode’s command which does this (i.e. c-mode).

It could be a bit annoying to have to this every time a new buffer is created so the mode-alist variable allows major modes to be installed automatically, when the buffer is opened.

Function: init-mode buffer &optional string

This function attempts to install a major mode into buffer. If the major-mode variable is non-nil it defines the function to call to install the mode; this function will be called.

Otherwise the mode-alist variable is searched; each regular expression is matched against a string, when a match occurs the associated function is called to install the mode.

The string matched against is defined by the first of the following choices which is not nil or undefined.

  1. The value of the optional string argument.
  2. The word specified on the first line of the buffer bracketed by the string ‘-*-’. For example if the first line contained the string ‘-*-Text-*-’ the string ‘Text’ would be used.
  3. The value of the variable mode-name.
  4. The name of the file being edited in the buffer.

Note that each match is case-insensitive.

Variable: mode-alist

An association list (see section Association Lists) defining regular expressions which associate with a particular major mode.

When the init-mode function matches a regular expression to the string it is using to find the mode for the buffer the associated mode is installed.

For example, mode-alist could be,

(("\\.(c|h)$|^c(|-mode)$" . c-mode)
 ("\\.jl$|^lisp(|-mode)$" . lisp-mode)
 ("\\.(text|doc|txt|article|letter)$" . text-mode)
 ("^(text(|-mode)|(.*/|)draft)$" . text-mode)
 ("^indented-text(|-mode)$" . indented-text-mode)
 ("\\.[s]$|^asm(|-mode)$" . asm-mode)
 ("\\.[S]$|^asm-cpp(|-mode)$" . asm-cpp-mode)
 ("\\.texi(|nfo)|^texinfo(|-mode)$" . texinfo-mode))
Function: kill-mode &optional buffer

This function removes the major mode currently installed in the specified buffer.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.28.3 Writing Minor Modes

Minor modes are generally harder to write properly than major modes since they have to peacefully coexist with all the other minor modes which may also be enabled in a buffer.

Generally each minor mode maintains a buffer-local variable saying whether or not it’s installed in the buffer. The minor mode’s function usually toggles the mode on or off depending on the state of this variable.

There are two functions which must be used to install and remove a minor mode — add-minor-mode and remove-minor-mode, see their documentation for details.

Each buffer has a keymap containing the bindings of all the minor modes enabled in the buffer (the variable minor-mode-keymap). These bindings have to be added when the mode is enabled and removed when it is disabled.

Variable: minor-mode-list

This buffer-local variable is a list of all the minor modes enabled in a buffer.

Variable: minor-mode-names

This buffer-local variable contains a list of strings, each string names one of the minor modes currently enabled in the buffer.

Variable: minor-mode-keymap

A buffer-local keymap to be used by minor-modes. This is only created the first time a minor mode calls add-minor-mode in the buffer.

Function: add-minor-mode mode name &optional no-keymap

This function installs a minor mode (the symbol mode) into the current buffer. All minor modes should call this before doing anything drastic.

name is the string to be displayed in the status line as the name of this minor mode.

When no-keymap is nil or undefined this function ensures that the minor-mode-keymap variable has a valid value in this buffer.

Function: remove-minor-mode mode name

Removes a minor mode from the current buffer, the mode and name arguments must have the same value as the arguments given to add-minor-mode when the mode was enabled.

The following code fragment is an example minor mode taken from Jade’s source code.

(provide 'fill-mode)

(defvar fill-column 72
  "Position at which the text filling commands break lines.")

(defvar fill-mode-p nil)
(make-variable-buffer-local 'fill-mode-p)

;;;###autoload
(defun fill-mode ()
  "Minor mode for automatically filling lines, i.e. word-wrapping.
This makes the SPC key checks if the cursor is past the fill-column. If
so, the next line is started."
  (interactive)
  (if fill-mode-p
      (progn
        (setq fill-mode-p nil)
        (remove-minor-mode 'fill-mode "Fill")
        (unbind-keys minor-mode-keymap "SPC"))
    (add-minor-mode 'fill-mode "Fill")
    (setq fill-mode-p t)
    (bind-keys minor-mode-keymap
      "SPC" 'fill-mode-spc)))

(defun fill-mode-spc ()
  (interactive)
  (when (> (pos-col (cursor-pos)) fill-column)
    (let
        ((pos (cursor-pos)))
      (set-pos-col pos (1+ fill-column))
      (setq pos (unless (word-start pos) (forward-word -1 pos)))
      (insert "\n" pos)
      (let
          ((end (left-char 1 (copy-pos pos))))
        (when (equal (get-char end) ?\ )
          (delete-area end pos)))))
  (insert " "))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.28.4 Mode-Specific Indentation

Some major modes provide functions which manage the indentation of the buffer they are installed in. These modes are usually those which are designed for a particular programming language; for example C mode understands how to indent C source and Lisp mode knows about Lisp code.

To simplify matters there is a unified interface to the indentation process; each major mode simply sets the value of a buffer-local variable to the function used to indent a line in that buffer. This variable is then referenced by the functions which provide indentation.

Variable: mode-indent-line

This buffer-local variable should contain a function when the buffer’s major mode provides special indentation.

The function should take one optional argument, the position of the line to indent. If the value of this argument is nil the current line should be indented. The function should set the indentation of the line to the correct depth then return the glyph position (see section Glyph Positions) of the first non-whitespace character.

For example Lisp mode sets this variable to lisp-indent-line, this function is defined as,

(defun lisp-indent-line (&optional pos)
  (set-indent-pos (lisp-indent-pos (or pos (cursor-pos)))))

Where the function lisp-indent-pos calculates the proper indentation for the line pointed to by its argument.

For the functions dealing with indentation see Indentation Functions.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.28.5 Mode-Specific Expressions

Most programming use the concept of an expression, Jade allows major modes to define two functions which define the syntax of an expression in a particular programming language. Commands exist which use these functions to allow the manipulation of expressions as entities in a buffer, much like words.

Variable: mode-forward-exp

This buffer-local variable contains a function which calculates the position of the end of an expression in that language.

The lambda-list of the function (i.e. its arguments) must be (&optional count pos). count is the number of expressions to move forwards over (default is one), pos is the position to start from (default is the cursor position).

The function should return the position of the character following the end of count expressions starting from pos.

Variable: mode-backward-exp

Similar to mode-forward-exp but works backwards from the character after the expression (at pos) to the start of the previous count expressions.

These functions can often be quite complex but their structure is usually the same; these two examples are taken from the Lisp mode,

(defun lisp-forward-sexp (&optional number pos)
  "Return the position of the NUMBER'th next s-expression from POS."
  (unless number
    (setq number 1))
  (while (> number 0)
    ;; Move pos over one expression
    …
    (setq number (1- number)))
  pos)

(defun lisp-backward-sexp (&optional number orig-pos)
  "Return the position of the NUMBER'th previous s-expression
from ORIG-POS."
  (unless number
    (setq number 1))
  (unless orig-pos 
    (setq orig-pos (cursor-pos)))
  (let
      ((pos (copy-pos orig-pos)))
    (while (> number 0)
       ;; Move pos backwards over one expression
       …
      (setq number (1- number)))
    pos))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.28.6 Mode-Specific Comments

When you wish to enter a comment in a piece of source code Jade has a command to do this (insert-comment); each major mode which wishes to allow comments (created by this command) must give the following variable a suitable function.

Variable: mode-comment-fun

This buffer-local variable contains the function to call when a comment is to be entered, basically the insert-comment command just calls this function.

Function: find-comment-pos

This function moves the cursor to a suitable position for inserting a comment in the current line.

Variable: comment-column

Buffer-local variable containing the canonical column number which comments should begin at (used by the find-comment-pos function). If the line extends past this column the next tab stop after the end of the line is used instead.

The following function is an example of what is needed in the mode-comment-fun variable; it is used by the C mode.

(defun c-insert-comment ()
  (interactive)
  (find-comment-pos)
  (insert "/*  */")
  (goto-left-char 3))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.29 Prompting

The most common way to ask the user for a response is to encode the question in the command’s interactive declaration (see section Interactive Declarations), sometimes this is inconvenient; functions are available which have the same effect as the code letters in an interactive declaration.

The following two functions don’t have an equivalent code for the interactive declaration.

Function: y-or-n-p question

This function prompts the user for a single key response to the string question asking a question which can be answered yes or no.

Returns t when question is answered with a y and nil when n is typed.

Function: yes-or-no-p question

Similar to y-or-n-p but the answer must be either the word ‘yes’ or the word no entered in full. This function should be used when a mistyped answer could be catastrophic (i.e. losing changes to a buffer).

Returns t for ‘yes’, nil for anything else.

The following functions are the functions used by the call-command function to resolve interactive arguments.

Note that these function don’t return the string entered (except for prompt-for-string) — they return some Lisp object which the string entered represents somehow.

Function: prompt-for-file &optional prompt existing start

Prompts for the name of a file. prompt is the string to display at the head of the prompt, when existing is non-nil only files which actually exist are allowed to be entered. The start argument may be a string defining the starting contents of the prompt.

Function: prompt-for-directory &optional prompt existing start

Prompts for the name of a directory, all arguments are similar to in the prompt-for-file function.

Function: prompt-for-buffer &optional prompt existing default

This function prompts for a buffer object, if existing is non-nil the buffer selected must exist, otherwise the buffer will be created if it doesn’t already exist. default is the value to return if the user enters the null string, if nil the current buffer is returned.

Note that this returns the actual buffer, not its name as a string.

Function: prompt-for-symbol &optional prompt predicate

Prompt for a symbol, prompt is displayed at the head of the prompt buffer. If the predicate argument is defined it is a predicate function; only symbols which when applied to the function predicate return non-nil will be allowed to be entered.

Function: prompt-for-lisp &optional prompt

Prompt for and return a Lisp object.

Function: prompt-for-function &optional prompt

Prompts for a function.

(prompt-for-function prompt)
≡
(prompt-for-symbol prompt 'functionp)
Function: prompt-for-variable &optional prompt

Prompts for a variable (a symbol whose value is not void).

(prompt-for-variable prompt)
≡
(prompt-for-symbol prompt 'boundp)
Function: prompt-for-command &optional prompt

Prompts for a command (a function which may be called interactively).

(prompt-for-command prompt)
≡
(prompt-for-symbol prompt 'commandp)
Function: prompt-for-string &optional prompt

Prompt for a string, whatever string is entered is returned as-is.

Function: prompt-for-number &optional prompt

Prompts for a number which is then returned.

The following function is useful when a number of options have to be chosen between, for example the menu command in Info-mode uses this function.

Function: prompt-from-list option-list prompt &optional start

Returns a selected choice from the list of options (strings) option-list. prompt is the title displayed, start the optional starting choice.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30 Files

Jade allows you to manipulate files in the operating system’s filing system; a special type of Lisp object, a file object, is used to represent files which have been opened for reading or writing (through the streams mechanism, see section Streams).

Names of files are represented by strings, the syntax of file names is defined by the underlying operating system: Jade simply treats it as a string.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.1 File Names

A file name is a string identifying an individual file (or directory) in the filing system (i.e. the disk). The exact syntax of file names depends on the operating system.

Function: file-name-directory file-name

This function returns the directory part of the file name string file-name. This is the substring of file-name defining the directory containing the file.

(file-name-directory "/tmp/foo")
    ⇒ "/tmp/"

(file-name-directory "foo")
    ⇒ ""

(file-name-directory "foo/bar/")
    ⇒ "/foo/bar/"
Function: file-name-nondirectory file-name

Returns the substring of the file name file-name which is not the directory part.

(file-name-nondirectory "/tmp/foo")
    ⇒ "foo"

(file-name-nondirectory "foo")
    ⇒ "foo"

(file-name-nondirectory "foo/bar/")
    ⇒ ""
Function: file-name-concat &rest parts

This function returns a file name constructed by concatenating each of the parts of the file name together. Each part is separated by the necessary string (i.e. ‘/’ on Unix) when necessary. Note that each part may contain more than one component of the file name.

(file-name-concat "/tmp" "foo" "bar")
    ⇒ "/tmp/foo/bar"

(file-name-concat "/tmp/" "foo/" "bar")
    ⇒ "/tmp/foo/bar"

(file-name-concat "/tmp/foo" "bar")
    ⇒ "/tmp/foo/bar"
Function: expand-file-name file-name &optional make-absolute

This function expands the string file-name into a valid file name. Currently it only checks for a leading tilde character (‘~’) when running on Unix, if one is found it’s expanded to the user’s home directory.

When the optional argument make-absolute is non-nil file-name is altered so that it is not relative to the current working directory. Generally this involves prefixing it by the absolute name of the current directory.

(expand-file-name "~/src")
    ⇒ "/home/jsh/src"

(expand-file-name "foo.c" t)
    ⇒ "/var/src/jade/foo.c"
Function: tmp-file-name

This function returns the name of a file which, when created, may be used for temporary storage. Each time this function is called a unique name is computed.

(tmp-file-name)
    ⇒ "/tmp/00088aaa"

(tmp-file-name)
    ⇒ "/tmp/00088baa"

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.2 File Objects

A file object is a Lisp object which represents a file in the filing system. Any file object may be used as a stream (either input or output) to access the contents of the file serially, Streams.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.2.1 Creating File Objects

Function: open file-name mode-string &optional file-object

This function opens the file called file-name (see section File Names) and returns the file’s object.

The mode-string argument is a string defining the access modes used to open the file with; this string is passed as-is to the C library’s fopen() function. Usually one of the following strings is used,

r

Open an existing file for reading only.

w

Open the file for writing only, if the file exists it is truncated to zero length. Otherwise a new file is created.

a

Open the file for appending to, i.e. writing to the end of the file. If the file doesn’t exist it is created.

Other options exist; consult a C library manual for details.

When the file-object argument is defined it should be a file object, the file it points to will be closed and the new file will be opened on this object.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.2.2 Destroying File Objects

The easiest way to close a file is simply to eliminate all references to it, subsequently the garbage collector will close it for you. It is better to close files explicitly though since only a limited number of files may be opened concurrently.

Function: close file-object

This function closes the file pointed to by the file object file-object.

Until a new file is opened on file-object any read/write accesses to it are illegal and an error will be signalled.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.2.3 File Object Predicates

Function: filep object

This function returns t when its argument is a file object.

Function: file-bound-p file-object

Returns t when the file object file-object is currently bound to a physical file (i.e. the close function hasn’t been called on it yet).

Function: file-eof-p file-object

This function returns t when the current position of the file object file-object is the end of the file (i.e. when reading a character from the file would return nil).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.2.4 Functions on File Objects

Function: flush-file file-object

This function flushes any buffered output to the file object file-object to disk.

Note that when using a file which was opened with the ‘+’ option it’s necessary to call this function when switching from reading to writing or vice versa.

Function: file-binding file-object

Returns the name of the file which the file object file-object is currently bound to.

Function: read-file-until file-object regexp &optional ignore-case

This function reads lines from the file object file-object until a line matching the regular expression regexp is found. The matching line is returned, or nil if the end of the file is reached.

When the ignore-case option is non-nil all regexp matching is done case-insignificantly (except for matching ranges).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.3 File Information

A number of functions exist which when given the name of a file return some information about that file.

Function: file-exists-p file-name

Returns t when a file file-name exists.

Function: file-regular-p file-name

Returns t when the file file-name is a ‘normal’ file. This means that it isn’t a directory, device, symbolic link or whatever.

Function: file-directory-p file-name

Returns t when the file file-name is a directory.

Function: file-symlink-p file-name

Returns t when the file file-name is a symbolic link.

Function: file-readable-p file-name

Returns t when the file file-name is readable.

Function: file-writable-p file-name

Returns t when the file file-name is writable.

Function: file-owner-p file-name

Returns t when the ownership of the file file-name is the same as that of any files written by the editor.

Note that currently this always returns t in the Amiga version.

Function: file-nlinks file-name

Returns the number of hard links pointing to the file file-name. If file-name has only one name the number will be one.

Note that this always returns one in the Amiga version of Jade.

Function: file-modes file-name

This function returns the access permissions of the file file-name. This will be an integer whose format is undefined; it differs from operating system to operating system.

Function: set-file-modes file-name modes

This function sets the access permissions of the file file-name to the integer modes (as returned by the file-modes function).

Function: file-modtime file-name

Returns the system time at the last modification to the file file-name, this will be an integer. See section System Time.

Function: file-newer-than-file-p file-name1 file-name2

This function returns t if the file file-name1 was modified more recently than the file file-name2 was.

(file-newer-than-file-p file1 file2)
≡
(> (file-modtime file1) (file-modtime file2))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.4 Manipulating Files

Command: delete-file file-name

This function deletes the file called file-name. When called interactively file-name is prompted for.

Command: rename-file file-name new-name

This function attempts to change the name of the file new-name to new-name.

This won’t work from one file system to another or if a file called new-name already exists, in these cases an error is signalled.

This prompts for its arguments when called interactively.

Command: copy-file file-name destination-name

Creates a new copy of the file file-name with the name destination-name.

The access modes of the new file will be the same as those of the original file.

The arguments are prompted for when this function is called interactively.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.5 Reading Directories

Function: directory-files directory-name

This function returns a list of the names of all files in the directory whose file name is directory-name. The names in the list will be relative to the directory directory-name, any directories in the list will have a ‘/’ character appended to them.

(directory-files "/tmp/foo"
    ⇒ ("bar" "subdir/" "xyz" "." "..")

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.30.6 Reading and Writing Files

Function: read-file file-name

This function returns a string containing the contents of the file called file-name.

Function: write-file file-name contents

This function creates or overwrites the file called file-name with the string contents as its contents.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.31 Processes

When running on a Unix-style operating system (i.e. the X11 version) Jade allows you to launch and control an arbitrary number of subprocesses. These subprocesses can run either synchronously or asynchronously in respect to the editor; data can be sent to the stdin channel and any output from the process is automatically written to a programmer-defined Lisp stream.

Currently there is no way to manipulate subprocesses in the Amiga version of Jade (sorry!).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.31.1 Process Objects

A process object is a type of Lisp object used to provide a link between a ‘physical’ process running in the operating system and Jade’s Lisp system. Each process object consists of a number of components (references to other Lisp objects); these components are used when the object is used to run a subprocess.

Process objects which aren’t currently being used to run a subprocess store the exit value of the last subprocess which was run on that object.

Function: processp object

This function returns t when its argument is a process object.

The programmer-accessible components of a process object are,

Output stream

A normal Lisp output stream (see section Output Streams), all data which the subprocess outputs to its stdout channel is copied to this output stream. See section Process I/O.

State change function

A Lisp function, called each time the state of the subprocess being run on the object changes. See section Process States.

Program name

The name of the program (a string) to execute when the subprocess is created.

Program arguments

A list of strings defining the arguments which the program executed is given.

Directory

When a subprocess is started its current working directory is set to the directory named by this component of its process object.

Connection type

Asynchronous subprocesses (see section Asynchronous Processes) use this component to decide how to connect to the I/O channels of the subprocess. Current options include pseudo-terminals and pipes.

Function: make-process &optional output-stream state-function directory program args

This functions creates and returns a new process object. No subprocess will be started.

The optional arguments are used to define the values of the components of the new process object, any undefined components will be set to default or null values.

For each component of a process object two functions exist; one to read the component’s value in a specific process object, the other to set the component’s value.

Function: process-prog process

Returns the value of the program name component of the process object process.

Function: set-process-prog process prog-name

Sets the value of the program name component of the process object process to the string prog-name, then returns prog-name.

Function: process-args process

Returns the value of the program arguments component of the process object process.

Function: set-process-args process arg-list

Sets the value of the program arguments component of the process object process to the list arg-list, then returns arg-list.

Function: process-dir process

Returns the value of the directory component of the process object process.

Function: set-process-directory process directory

Sets the value of the directory component of the process object process to the string directory, then returns directory.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.31.2 Asynchronous Processes

An asynchronous process is one that runs in parallel with the editor, basically this means that once the subprocess has been started (by the start-process function) Jade will carry on as normal.

The event loop checks for output from asynchronous processes, any found is copied to the process’ output stream, and calls the the process’ state change function when necessary (see section Process States).

When using asynchronous processes you have a choice as to the Unix mechanism used to connect the stdin, stdout and stderr streams of the subprocess to Jade’s process (note that whatever the choice stdout and stderr always go to the same place).

The two options currently available are pipes or pseudo-terminals; in general pseudo-terminals should only be used to provide a direct interface between the user and a process (i.e. the ‘*shell*’ buffer) since they allow job control to work properly. At other times pipes will be more efficient and are used by default.

Function: start-process &optional process-object program &rest args

This function starts an asynchronous subprocess running on the process object process-object. If process-object is undefined a new process object is created (by calling the function make-process with all arguments undefined).

The function always returns the process object which the subprocess has been started on. If for some reason the subprocess can’t be created an error of type process-error is signalled.

The optional argument program is a string defining the name of the program to execute, it will be searched for in all the directories in the PATH environment variable. The args are strings to pass to the subprocess as its arguments.

When defined, the optional arguments overrule the values of the related components of the process object.

The following example runs the ls program asynchronously, its output is inserted into the current buffer.

(let
    ((process (make-process (current-buffer))))
  (start-process process "ls" "-s"))

Note that when Jade terminates it kills all of its asynchronous subprocesses which are still running without warning.

Function: process-connection-type process

Returns the value of the connection type component of the process object process. See the documentation of the set-process-connection-type function for the values this may take.

Function: set-process-connection-type process symbol

Sets the value of the connection type component of the process object process to symbol, then returns symbol.

symbol should be one of the following symbols,

pty

Use pseudo-terminals to connect to subprocesses running asynchronously on this process object.

pipe

Use standard Unix pipes to connect, this is the default value of this component.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.31.3 Synchronous Processes

When a synchronous process is started Jade waits for it to terminated before continuing; they are usually used when a Lisp program must invoke an external program as part of its function, i.e. the auto-compression feature runs the compression program gzip synchronously when it needs to compress a buffer.

Unlike asynchronous processes their is no choice between pipes and pseudo-terminals for connecting to a subprocess. Instead, it is possible to link the stdin channel of a synchronous process to a named file.

Function: run-process &optional process-object input-file-name program &rest args

This function starts a process running on the process object process-object. If process-object is undefined a new process object is created by calling the make-process function.

If defined, the string input-file-name names the file to connect to the standard input of the subprocess, otherwise the subprocess’ input comes from the null device (‘/dev/null’).

The optional arguments program and args define the name of the program to invoke and any arguments to pass to it. The program will be searched for in all directories listed in the PATH environment variable.

If any of the optional parameters are unspecified they should have been set in the process-object prior to calling this function.

After successfully creating the new subprocess, this function simply copies any output from the process to the output stream defined by the output stream component of the process object. When the subprocess exits its exit-value is returned (an integer). Note that the exit-value is the value returned by the process-exit-value function, see Process Information.

If, for some reason, the new subprocess can’t be created an error of type process-error is signalled.

The following function definition is taken from the ‘gzip.jl’ file, it shows how the run-process function can be used to uncompress a file into a buffer.

;; Uncompress FILE-NAME into the current buffer
(defun gzip-uncompress (file-name)
  (let
      ((proc (make-process (current-buffer))))
    (message (concat "Uncompressing `" file-name "'") t)
    ;; gunzip can do .Z files as well
    (unless (zerop (run-process proc nil "gunzip" "-c" file-name))
      (signal 'file-error (list "Can't gunzip file" file-name)))))

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.31.4 Process I/O

It is only possible for lisp programs to explicitly send input data to asynchronous processes (by the time it’s possible to call a function to send data to a synchronous process, the process will already have terminated!). Simply use the process object which an asynchronous process is running on as a normal Lisp input stream, any strings or characters written to the stream will immediately be copied to the stdin channel of the subprocess.

With synchronous processes, the only control over input data possible is by giving the run-process function the name of a file containing the subprocess’ input data.

Output data from subprocesses is handled the same way by both asynchronous and synchronous processes: it is simply copied to the stream defined by the output stream component of the subprocess’ process object.

Function: process-output-stream process

Returns the value of the output stream component of the process object process.

Function: set-process-output-stream process stream

Sets the value of the output stream component of the process object process to the stream stream, then returns stream.

See section Streams.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.31.5 Process States

Each process object has a state associated with it; this depends on the status of the subprocess currently running on the process object (or not as the case may be).

The possible states are,

running

This state means that the subprocess using this process object is currently running, i.e. it hasn’t been stopped.

stopped

Means that the subprocess has been temporarily suspended from running.

unused

This means that the process object is free to have a new subprocess created on it.

Predicates exist which test whether a given process object is in one of these states.

Function: process-running-p process-object

Returns t when process-object is in the running state.

Function: process-stopped-p process-object

Returns t when process-object is in the stopped state.

Function: process-in-use-p process-object

Returns t when process-object is not in the unused state.

The following two functions are used to stop and then subsequently continue a process running.

Function: stop-process process-object &optional whole-group

This function suspends execution of the subprocess running on the process object process-object.

If whole-group is non-nil all subprocesses in the process group of process-object are stopped.

Function: continue-process process-object &optional whole-group

Use this function to continue a subprocess executing after it has been stopped (by the stop-process function).

If whole-group is non-nil all subprocesses in the process group of process-object are continued.

The state change function component of a process object defines a function which will be called each time the state of the process object changes. If your program needs to be informed when an asynchronous process terminates this function is the way to do it.

Function: process-function process

Returns the value of the state change function component of the process object process.

Function: set-process-function process function

Sets the value of the state change function component of the process object process to the function function, then returns function.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.31.6 Signalling Processes

Function: signal-process process-object signal-number &optional whole-group

If the process object process-object is being used to run an asynchronous subprocess send the signal numbered signal-number to it.

When the optional argument whole-group is non-nil the signal is also sent to all processes in the process group of the subprocess.

The following functions use the signal-process function to send some common signals to processes.

Function: interrupt-process process-object &optional whole-group

Sends the SIGINT signal to process-object.

(interrupt-process process-object whole-group)
≡
(signal-process process-object SIGINT whole-group)
Function: kill-process process-object &optional whole-group

Sends the SIGKILL signal to the process-object.

(kill-process process-object whole-group)
≡
(signal-process process-object SIGKILL whole-group)

Note that the functions stop-process and continue-process also send signals to the subprocess.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.31.7 Process Information

Function: process-id process-object

This function returns the operating-system identifier associated with the subprocess currently running on the process object process-object.

Function: process-exit-value process-object

Returns the integer representing the return code of the last subprocess to be run on process-object.

If no subprocess has been run on process-object, process-object is currently in the running state or the last subprocess exited abnormally (i.e. from a terminal signal) nil is returned.

Function: process-exit-status process-object

This function returns the integer that was the exit status of the last subprocess which was run on the process object process-object.

Note that the exit status is not the value given to the exit function in a C program, use the process-exit-value to access this value.

If no process has been run on process-object, or the process is currently in the running state nil is returned.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.31.8 Interactive Processes

The Shell mode is usually used to run a shell process in a buffer (with the shell command, @pxref{Shell}) but in actual fact it is capable of running (nearly) any type of interactive process. For example the gdb interface (@pxref{Debugging Programs}) uses the Shell mode to handle its user interaction.

The following buffer-local variables control the Shell mode.

Variable: shell-program

This variable defines the name of the program to execute. By default it is the user’s shell.

Variable: shell-program-args

A list of arguments which should be given to the process when it is started.

Variable: shell-prompt-regexp

This regular expression must match the prompt that the process emits each time it waits for input. Its standard value of ‘^[^]#$%>)]*[]#$%>)] *’ will need to be tailored to the program that you are executing.

Variable: shell-callback-function

Every time the state of the subprocess changes (see section Process States) this function is called in the context of the process’ buffer.

Variable: shell-output-stream

All output from the subprocess is copied to this output stream. If it is nil all output goes to the end of the process’ buffer.

Note that this variable is only referenced when the process is started.

To use the Shell mode to create an interface with a program simply use the following steps.

  1. Select the buffer which you want to run the subprocess in. The value of the buffer-file-name attribute of the buffer defines the working directory of the subprocess.
  2. Set the variables described above to suitable values.
  3. Call the shell-mode function.
  4. Reset the values of the mode-name and major-mode if necessary and install your own keymaps.

    Remember that commands essential to the Shell mode (and hence your program) are contained in the two keymaps shell-keymap and shell-ctrl-c-keymap. If you need to bind your own commands to either of these prefixes make copies of these keymaps (using the function copy-sequence) and bind to the copies.

    For example the gdb interface installs its own key bindings from the Ctrl-c prefix by doing the following in its initialisation.

    (defvar gdb-ctrl-c-keymap (copy-sequence shell-ctrl-c-keymap))
    (bind-keys gdb-ctrl-c-keymap
     ;; Gdb mode `Ctrl-c' prefix bindings follow
     …
    
Function: shell-mode

This function installs the Shell mode and starts a subprocess running in the current buffer.

The variables shell-program, shell-program-args, shell-prompt-regexp, shell-callback-function and shell-output-stream control the program executed and how it will execute.

The process object created is stored in the buffer-local variable shell-process.

Variable: shell-process

This buffer-local variable contains the process object which the Shell mode started running in this buffer. If it is nil no such process exists.

Variable: shell-keymap

The root keymap of the Shell mode.

Variable: shell-ctrl-c-keymap

The keymap containing the key bindings of the commands in Shell mode with a prefix of Ctrl-c.

See the Lisp program ‘gdb.jl’ for an example of how to use the Shell mode as the user interface with an external program.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.32 Miscellaneous Functions

This section of the manual documents functions and features which don’t comfortably fit elsewhere in this manual.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.32.1 System Information

Function: x11-p

This function returns t when Jade is running on the X11 window system.

Function: unix-p

This function returns t when Jade is running on a variant of the Unix operating system.

Function: amiga-p

This function returns t when Jade is running on an Amiga.

Function: system-name

This function returns a string naming the host that Jade is running on. When possible this will include the name of the domain as well.

In the Amiga version of Jade the environment variable HOSTNAME is assumed to contain the host’s name.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.32.2 User Information

Function: user-login-name

This function returns a string containing the login name of the user.

In the Amiga version this is taken from the environment variable USERNAME.

(user-login-name)
    ⇒ "jsh"
Function: user-real-name

This function returns a string containing the ‘real’ name of the user; the format of the string will depend on the host system.

In the Amiga version this is taken from the REALNAME environment variable.

(user-real-name)
    ⇒ "John Harper"
Function: user-home-directory

This function returns the name of the user’s home directory terminated by a slash character (‘/’).

The first place this is looked for is in the HOME environment variable; if this variable doesn’t exist we either use the ‘SYS:’ logical device in AmigaDOS or consult the passwd file when in Unix.

(user-home-directory)
    ⇒ "/home/jsh/"

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.32.3 Environment Variables

Function: getenv variable-name

This function returns the value (a string) of the environment variable called variable-name. If the specified variable doesn’t exist nil is returned.

(getenv "OSTYPE")
    ⇒ "Linux"
Function: setenv variable-name new-value

This function sets the value of the environment variable called variable-name to new-value. new-value can either be a string containing the new contents of the variable or nil, in which case the environment variable is deleted.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.32.4 System Time

No matter what operating system Jade is running on it always an integer to store a time value. Generally this will be the number of seconds since some previous date.

The only thing a Lisp program is allowed to assume about a time value is that as time passes the time value increases. This means that it’s possible to compare two time values and know which is the newer.

Function: current-time

Returns an integer denoting the current time.

(current-time)
    ⇒ 780935736
Function: current-time-string

This function returns a string stating the current time and date in a fixed format. An example of the format is,

Fri Sep 30 15:20:56 1994

Each field will always be in the same place, for example,

Thu Sep  1 12:13:14 1994
(current-time-string)
    ⇒ "Fri Sep 30 15:20:56 1994"

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.32.5 Revision Information

Function: major-version-number

This function returns a number defining the major version of the editor.

(major-version-number)
    ⇒ 3
Function: minor-version-number

Returns a number defining the minor version of the editor.

(minor-version-number)
    ⇒ 2

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.33 Debugging

When you have written a Lisp program you will have to debug it (unless all your programs work first time?). There are two main classes of errors; syntax errors and semantic errors.

Syntax errors occur when the text you’ve typed out to represent your program is not a valid representation of a Lisp object (since a program is simply an ordered set of Lisp objects). When you try to load your program the Lisp reader will find the syntax error and tell you about, unfortunately though it probably won’t be able to tell you exactly where the error is.

The most common source of syntax errors is too few or too many parentheses; the Ctrl-Meta-f and Ctrl-Meta-b commands can be used to show the structure of the program as the Lisp reader sees it.

Semantic errors are what we normally call bugs — errors in logic, the program is syntactically correct but doesn’t do what you want it to. For these types of errors Jade provides a simple debugger which allows you to single step through the Lisp forms of your program as they are being evaluated.

There are several ways to enter the Lisp debugger; functions can be marked so that they cause the debugger to be entered when they are called, breakpoints can be written in functions or it can be called explicitly with a form to step through.

Command: trace symbol

This command marks the symbol symbol so that each time the function stored in the function cell of symbol is called the debugger is entered immediately.

When called interactively symbol is prompted for.

Command: untrace symbol

The opposite of trace — unmarks the symbol.

Function: break

This function causes the debugger to be entered immediately. By putting the form (break) at suitable points in your program simple breakpoints can be created.

Command: step form

This function invokes the debugger to step through the form form.

When called interactively form is prompted for.

Whenever the Lisp debugger is entered the form waiting to be evaluated is printed at the bottom of the buffer, at this point the special debugger commands available are,

Ctrl-c Ctrl-s

Step into the current form; this means that in a list form the debugger is used to evaluated each argument in turn.

Ctrl-c Ctrl-i

Ignore the current form; makes the current form immediately return nil.

Ctrl-c Ctrl-n

Continue evaluating forms normally until the next form at the current level is entered, then re-enter the debugger.

Ctrl-c Ctrl-r

Continue execution normally. Note that this command is the one to use when an error has been trapped.

Ctrl-c Ctrl-b

Print a backtrace of the current Lisp call stack, note that calls of primitive functions aren’t currently recorded in this stack.

Ctrl-c Ctrl-x

Prompt for a Lisp form, evaluate it and return this value as the result of the current form.

After the form has been evaluated (i.e. after you’ve typed one of the commands above) the value of the form is printed in the buffer, prefixed by the string ‘=> ’.

Note that it is also possible to make certain types of errors invoke the debugger immediately they are signalled, see Errors.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.34 Tips

This section of the manual gives advice about programming in Jade.

Obviously there is no need to religiously follow every single one, but following these tips will make your programs easier to read and (hopefully) more efficient overall.

For advice on getting the most out of the compiler, see Compilation Tips.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.34.1 Comment Styles

As already described, single-line comments in Lisp are introduced by a semi-colon (‘;’) character. By convention a different number of semi-colons is used to introduce different types of comments,

;

A comment referring to the line of Lisp code that it occurs on, comments of this type are usually indented to the same depth, on the right of the Lisp code. When editing in Lisp mode the command Meta-; can be used to insert a comment of this type.

For example,

(defconst op-call 0x08)	        ;call (stk[n] stk[n-1] ... stk[0])
                                ; pops n values, replacing the
                                ; function with the result.
(defconst op-push 0x10)	        ;pushes constant # n
;;

Comments starting with two semi-colons are written on a line of their own and indented to the same depth as the next line of Lisp code. They describe the following lines of code.

For example,

;; Be sure to remove any partially written dst-file.
(let
    ((fname (concat file-name ?c)))
  (when (file-exists-p fname)
    (delete-file fname)))

Comments of this type are also placed before a function definition to describe the function. This saves wasting memory with a documentation string in a module’s internal functions.

For example,

;; Compile a form which occurred at the `top-level' into a
;; byte code form.
;; defuns, defmacros, defvars, etc... are treated specially.
;; require forms are evaluated before being output uncompiled;
;; this is so any macros are brought in before they're used.
(defun comp-compile-top-form (form)
  …
;;;

This type of comment always starts in the first column of the line, they are used to make general comments about a program and don’t refer to any function or piece of code in particular.

For example,

;;; Notes:
;;;
;;; Instruction Encoding
;;; ====================
;;; Instructions which get an argument (with opcodes of zero up to
…
;;;;

Each program should have a comment of this type as its first line, the body of the comment is the name of the file, two dashes and a brief description of what the program does. They always start in the first column.

For example,

;;;; compiler.jl -- Simple compiler for Lisp files/forms

If you adhere to these standards the indentation functions provide by the Lisp mode will indent your comments to the correct depth.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.34.2 Program Layout

The layout that I have used for all the Lisp programs included with Jade is as follows, obviously this isn’t ideal but it seems ok.

  1. The first line of the file is the header comment, including the name of the file and its general function.
  2. Copyright banner.
  3. Any require forms needed followed by a provide form for this module. The require forms should be before the provide in case the required modules aren’t available.
  4. Variable and constant definitions. As a variable is defined any initialisation it needs is done immediately afterwards. For example a keymap is defined with defvar then initialised with the bind-keys function.

    For example,

    (defvar debug-buffer (make-buffer "*debugger*")
      "Buffer to use for the Lisp debugger.")
    (set-buffer-special debug-buffer t)
    (add-buffer debug-buffer)
    
    (defvar debug-ctrl-c-keymap (make-keylist)
      "Keymap for debugger's ctrl-c prefix.")
    (bind-keys debug-ctrl-c-keymap
      "Ctrl-s" 'debug-step
      …
    
  5. Finally the functions which make up the program, it often improves readability if the entry points to the program are defined first.

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.34.3 General Tips

The following are some general items of advice; you don’t have to follow them but they are the result of experience!


[Top] [Contents] [Index] [ ? ]

Footnotes

(1)

Actually buffer-local variables complicate matters but you’ll learn about that later.


[Top] [Contents] [Index] [ ? ]

About This Document

This document was generated on September 19, 2022 using texi2html 5.0.

The buttons in the navigation panels have the following meaning:

Button Name Go to From 1.2.3 go to
[ << ] FastBack Beginning of this chapter or previous chapter 1
[ < ] Back Previous section in reading order 1.2.2
[ Up ] Up Up section 1.2
[ > ] Forward Next section in reading order 1.2.4
[ >> ] FastForward Next chapter 2
[Top] Top Cover (top) of document  
[Contents] Contents Table of contents  
[Index] Index Index  
[ ? ] About About (help)  

where the Example assumes that the current position is at Subsubsection One-Two-Three of a document of the following structure:


This document was generated on September 19, 2022 using texi2html 5.0.