29.2. Gray streams

29.2.1. Overview
29.2.2. Class EXT:FILL-STREAM

29.2.1. Overview

This interface permits the definition of new classes of streams, and programming their behavior by defining methods for the elementary stream operations. It is based on the proposal STREAM-DEFINITION-BY-USER:GENERIC-FUNCTIONS of David N. Gray to X3J13 and is supported by most Common Lisp implementations currently in use.

All symbols defined by this interface, starting with the prefix FUNDAMENTAL- or STREAM-, are exported from the package GRAY and EXT:RE-EXPORTed from EXT.

Defined classes

GRAY:FUNDAMENTAL-STREAM
This is a superclass of all user-defined streams. It is a subclass of STREAM and of STANDARD-OBJECT. Its metaclass is STANDARD-CLASS.
GRAY:FUNDAMENTAL-INPUT-STREAM
This is a superclass of all user-defined input STREAMs. It is a subclass of GRAY:FUNDAMENTAL-STREAM. The built-in function INPUT-STREAM-P returns true on instances of this class. This means that when you define a new stream class capable of doing input, you have to make it a subclass of GRAY:FUNDAMENTAL-INPUT-STREAM.
GRAY:FUNDAMENTAL-OUTPUT-STREAM
This is a superclass of all user-defined output STREAMs. It is a subclass of GRAY:FUNDAMENTAL-STREAM. The built-in function OUTPUT-STREAM-P returns true on instances of this class. This means that when you define a new stream class capable of doing output, you have to make it a subclass of GRAY:FUNDAMENTAL-OUTPUT-STREAM.
GRAY:FUNDAMENTAL-CHARACTER-STREAM
This is a superclass of all user-defined streams whose STREAM-ELEMENT-TYPE is CHARACTER. It is a subclass of GRAY:FUNDAMENTAL-STREAM. It defines a method on STREAM-ELEMENT-TYPE that returns CHARACTER.
GRAY:FUNDAMENTAL-BINARY-STREAM
This is a superclass of all user-defined streams whose STREAM-ELEMENT-TYPE is a subtype of INTEGER. It is a subclass of GRAY:FUNDAMENTAL-STREAM. When you define a subclass of GRAY:FUNDAMENTAL-BINARY-STREAM, you have to provide a method on STREAM-ELEMENT-TYPE.
GRAY:FUNDAMENTAL-CHARACTER-INPUT-STREAM
This is a convenience class inheriting from both GRAY:FUNDAMENTAL-CHARACTER-STREAM and GRAY:FUNDAMENTAL-INPUT-STREAM.
GRAY:FUNDAMENTAL-CHARACTER-OUTPUT-STREAM
This is a convenience class inheriting from both GRAY:FUNDAMENTAL-CHARACTER-STREAM and GRAY:FUNDAMENTAL-OUTPUT-STREAM.
GRAY:FUNDAMENTAL-BINARY-INPUT-STREAM
This is a convenience class inheriting from both GRAY:FUNDAMENTAL-BINARY-STREAM and GRAY:FUNDAMENTAL-INPUT-STREAM.
GRAY:FUNDAMENTAL-BINARY-OUTPUT-STREAM
This is a convenience class inheriting from both GRAY:FUNDAMENTAL-BINARY-STREAM and GRAY:FUNDAMENTAL-OUTPUT-STREAM.

General generic functions defined on streams

(STREAM-ELEMENT-TYPE stream)

Returns the stream's element type, normally a subtype of CHARACTER or INTEGER.

The method for GRAY:FUNDAMENTAL-CHARACTER-STREAM returns CHARACTER.

((SETF STREAM-ELEMENT-TYPE) new-element-type stream)

Changes the stream's element type.

The default method SIGNALs an ERROR.

This function is a CLISP extension (see Section 21.3.1, “Function STREAM-ELEMENT-TYPE).

(CLOSE stream &KEY :ABORT)

Closes the stream and flushes any associated buffers.

When you define a primary method on this function, do not forget to CALL-NEXT-METHOD.

(OPEN-STREAM-P stream)

Returns true before the stream has been closed, and NIL after the stream has been closed.

You do not need to add methods to this function.

(GRAY:STREAM-POSITION stream position)

Just like FILE-POSITION, but NIL position means inquire.

You must define a method for this function.

generic functions for character input

(GRAY:STREAM-READ-CHAR stream)

If a character was pushed back using GRAY:STREAM-UNREAD-CHAR, returns and consumes it. Otherwise returns and consumes the next character from the stream. Returns :EOF if the end-of-stream is reached.

You must define a method for this function.

(GRAY:STREAM-UNREAD-CHAR stream char)

Pushes char, which must be the last character read from the stream, back onto the front of the stream.

You must define a method for this function.

(GRAY:STREAM-READ-CHAR-NO-HANG stream)

Returns a character or :EOF, like GRAY:STREAM-READ-CHAR, if that would return immediately. If GRAY:STREAM-READ-CHAR's value is not available immediately, returns NIL instead of waiting.

The default method simply calls GRAY:STREAM-READ-CHAR; this is sufficient for streams whose GRAY:STREAM-READ-CHAR method never blocks.

(GRAY:STREAM-PEEK-CHAR stream)

If a character was pushed back using GRAY:STREAM-UNREAD-CHAR, returns it. Otherwise returns the next character from the stream, avoiding any side effects GRAY:STREAM-READ-CHAR would do. Returns :EOF if the end-of-stream is reached.

The default method calls GRAY:STREAM-READ-CHAR and GRAY:STREAM-UNREAD-CHAR; this is sufficient for streams whose GRAY:STREAM-READ-CHAR method has no side-effects.

(GRAY:STREAM-LISTEN stream)

If a character was pushed back using GRAY:STREAM-UNREAD-CHAR, returns it. Otherwise returns the next character from the stream, if already available. If no character is available immediately, or if end-of-stream is reached, returns NIL.

The default method calls GRAY:STREAM-READ-CHAR-NO-HANG and GRAY:STREAM-UNREAD-CHAR; this is sufficient for streams whose GRAY:STREAM-READ-CHAR method has no side-effects.

(GRAY:STREAM-READ-CHAR-WILL-HANG-P stream)

Returns NIL if GRAY:STREAM-READ-CHAR will return immediately. Otherwise it returns true.

The default method calls GRAY:STREAM-READ-CHAR-NO-HANG and GRAY:STREAM-UNREAD-CHAR; this is sufficient for streams whose GRAY:STREAM-READ-CHAR method has no side-effects.

This function is a CLISP extension (see EXT:READ-CHAR-WILL-HANG-P).

(GRAY:STREAM-READ-CHAR-SEQUENCE stream sequence &OPTIONAL [start [end]])

Fills the subsequence of sequence specified by :START and :END with characters consecutively read from stream. Returns the index of the first element of sequence that was not updated (= end, or < end if the stream reached its end).

sequence is an ARRAY of CHARACTERs, i.e. a STRING. start is a nonnegative INTEGER and defaults to 0. end is a nonnegative INTEGER or NIL and defaults to NIL, which stands for (LENGTH sequence).

The default method repeatedly calls GRAY:STREAM-READ-CHAR; this is always sufficient if speed does not matter.

This function is a CLISP extension (see EXT:READ-CHAR-SEQUENCE).

(GRAY:STREAM-READ-LINE stream)

Reads a line of characters, and return two values: the line (a STRING, without the terminating #\Newline character), and a BOOLEAN value which is true if the line was terminated by end-of-stream instead of #\Newline.

The default method repeatedly calls GRAY:STREAM-READ-CHAR; this is always sufficient.

(GRAY:STREAM-CLEAR-INPUT stream)

Clears all pending interactive input from the stream, and returns true if some pending input was removed.

The default method does nothing and returns NIL; this is sufficient for non-interactive streams.

generic functions for character output

(GRAY:STREAM-WRITE-CHAR stream char)

Writes char.

You must define a method for this function.

(GRAY:STREAM-LINE-COLUMN stream)

Returns the column number where the next character would be written (0 stands for the first column), or NIL if that is not meaningful for this stream.

You must define a method for this function.

(GRAY:STREAM-START-LINE-P stream)

Returns true if the next character would be written at the start of a new line.

The default method calls GRAY:STREAM-LINE-COLUMN and compares its result with 0; this is sufficient for streams whose GRAY:STREAM-LINE-COLUMN never returns NIL.

(GRAY:STREAM-WRITE-CHAR-SEQUENCE stream sequence &OPTIONAL [start [end]])

Outputs the subsequence of sequence specified by :START and :END to stream.

sequence is an ARRAY of CHARACTERs, i.e. a STRING. start is a nonnegative INTEGER and defaults to 0. end is a nonnegative integer or NIL and defaults to NIL, which stands for (LENGTH sequence).

The default method repeatedly calls GRAY:STREAM-WRITE-CHAR; this is always sufficient if speed does not matter.

This function is a CLISP extension (see EXT:WRITE-CHAR-SEQUENCE).

(GRAY:STREAM-WRITE-STRING stream string &OPTIONAL [start [end]])

Outputs the subsequence of string specified by :START and :END to stream. Returns string.

string is a string. start is a nonnegative integer and default to 0. end is a nonnegative integer or NIL and defaults to NIL, which stands for (LENGTH string).

The default method calls GRAY:STREAM-WRITE-CHAR-SEQUENCE; this is always sufficient.

(GRAY:STREAM-TERPRI stream)

Outputs a #\Newline character.

The default method calls GRAY:STREAM-WRITE-CHAR; this is always sufficient.

(GRAY:STREAM-FRESH-LINE stream)

Possibly outputs a #\Newline character, so as to ensure that the next character would be written at the start of a new line. Returns true if it did output a #\Newline character.

The default method calls GRAY:STREAM-START-LINE-P and then GRAY:STREAM-TERPRI if necessary; this is always sufficient.

(GRAY:STREAM-FINISH-OUTPUT stream)

Ensures that any buffered output has reached its destination, and then returns.

The default method does nothing.

(GRAY:STREAM-FORCE-OUTPUT stream)

Brings any buffered output on its way towards its destination, and returns without waiting until it has reached its destination.

The default method does nothing.

(GRAY:STREAM-CLEAR-OUTPUT stream)

Attempts to discard any buffered output which has not yet reached its destination.

The default method does nothing.

(GRAY:STREAM-ADVANCE-TO-COLUMN stream column)

Ensures that the next character will be written at least at column.

The default method outputs an appropriate amount of space characters; this is sufficient for non-proportional output.

generic functions for binary input

(GRAY:STREAM-READ-BYTE stream)

Returns and consumes the next integer from the stream. Returns :EOF if the end-of-stream is reached.

You must define a method for this function.

(GRAY:STREAM-READ-BYTE-LOOKAHEAD stream)

To be called only if stream's STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8). Returns T if GRAY:STREAM-READ-BYTE would return immediately with an INTEGER result. Returns :EOF if the end-of-stream is already known to be reached. If GRAY:STREAM-READ-BYTE's value is not available immediately, returns NIL instead of waiting.

You must define a method for this function.

This function is a CLISP extension (see EXT:READ-BYTE-LOOKAHEAD).

(GRAY:STREAM-READ-BYTE-WILL-HANG-P stream)

To be called only if stream's STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8). Returns NIL if GRAY:STREAM-READ-BYTE will return immediately. Otherwise it returns true.

The default method calls GRAY:STREAM-READ-BYTE-LOOKAHEAD; this is always sufficient.

This function is a CLISP extension (see EXT:READ-BYTE-WILL-HANG-P).

(GRAY:STREAM-READ-BYTE-NO-HANG stream)

To be called only if stream's STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8). Returns an INTEGER or :EOF, like GRAY:STREAM-READ-BYTE, if that would return immediately. If GRAY:STREAM-READ-BYTE's value is not available immediately, returns NIL instead of waiting.

The default method calls GRAY:STREAM-READ-BYTE if GRAY:STREAM-READ-BYTE-LOOKAHEAD returns true; this is always sufficient.

This function is a CLISP extension (see EXT:READ-BYTE-NO-HANG).

(GRAY:STREAM-READ-BYTE-SEQUENCE stream sequence &OPTIONAL [start [end [no-hang [interactive]]]])

Fills the subsequence of sequence specified by :START and :END with integers consecutively read from stream. Returns the index of the first element of sequence that was not updated (= end, or < end if the stream reached its end).

sequence is an ARRAY of INTEGERs. start is a nonnegative INTEGER and defaults to 0. end is a nonnegative INTEGER or NIL and defaults to NIL, which stands for (LENGTH sequence). If no-hang is true, the function should avoid blocking and instead fill only as many elements as are immediately available. If no-hang is false and interactive is true, the function can block for reading the first byte but should avoid blocking for any further bytes.

The default method repeatedly calls GRAY:STREAM-READ-BYTE; this is always sufficient if speed does not matter.

This function is a CLISP extension (see EXT:READ-BYTE-SEQUENCE).

generic functions for binary output

(GRAY:STREAM-WRITE-BYTE stream integer)

Writes integer.

You must define a method for this function.

(GRAY:STREAM-WRITE-BYTE-SEQUENCE stream sequence &OPTIONAL [start [end [no-hang [interactive]]]])

Outputs the subsequence of sequence specified by :START and :END to stream

sequence is an ARRAY of INTEGERs. start is a nonnegative INTEGER and defaults to 0. end is a nonnegative INTEGER or NIL and defaults to NIL, which stands for (LENGTH sequence). If no-hang is true, the function should avoid blocking and instead output only as many elements as it can immediately proceed. If no-hang is false and interactive is true, the function can block for writing the first byte but should avoid blocking for any further bytes.

The default method repeatedly calls GRAY:STREAM-WRITE-BYTE; this is always sufficient if speed does not matter.

This function is a CLISP extension (see EXT:WRITE-BYTE-SEQUENCE).

29.2.2. Class EXT:FILL-STREAM

As an example of the use of GRAY STREAMs, CLISP offers an additional class, EXT:FILL-STREAM. An instance of this class is a “formattingSTREAM, which makes the final output to the underlying stream look neat: indented and filled. An instance of EXT:FILL-STREAM is created like this:

(MAKE-INSTANCE 'EXT:FILL-STREAM :stream stream
               [:text-indent symbol-or-number]
               [:sexp-indent symbol-or-number-or-function])

where

stream
is the target STREAM where the output actually goes.
symbol-or-number
is the variable whose value is the INTEGER text indentation or the indentation itself (defaults to 0).
symbol-or-number-or-function

When FORMAT writes an S-expression to a EXT:FILL-STREAM using ~S, and the expression's printed representation does not fit on the current line, it is printed on separate lines, ignoring the prescribed text indentation and preserving spacing. When this argument is non-NIL, the S-expression is indented by:

T
the text indentation above;
SYMBOL
SYMBOL-VALUE is the indentation;
INTEGER
the indentation itself;
FUNCTION
called with one argument, the text indentation, and the value is used as S-expression indentation; thus IDENTITY is equivalent to T above.

Defaults to CUSTOM:*FILL-INDENT-SEXP*, whose initial value is 1+.

Warning

Note that, due to buffering, one must call FORCE-OUTPUT when done with the EXT:FILL-STREAM (and before changing the indent variable). The former is done automatically by the macro (with-fill-stream (fill target-stream ...) ...).

Example 29.1. Example of EXT:FILL-STREAM usage

(defvar *my-indent-level*)
(with-output-to-string (out)
  (let ((*print-right-margin* 20)
        (*print-pretty* t)
        (*my-indent-level* 2))
    (with-fill-stream (fill out :text-indent '*my-indent-level*)
      (format fill "~%this is some long sentence which will      be broken at spaces")
      (force-output fill)
      (let ((*my-indent-level* 5))
        (format fill "~%and    properly indented to the level specified by the ~S argument which can be a ~S or an ~S - cool!"
                :TEXT-INDENT 'symbol 'integer))
      (format fill "~%Don't forget  to call ~S on it, and/or use ~S   Pretty formatting of the  S-expressions    printed with ~~S is  preserved: ~S"
              'force-output 'with-fill-stream '(defun foo (x y z) (if x (+ y z) (* y z)))))))
⇒ "
  this is some long
  sentence which
  will be broken at
  spaces
     and properly
     indented to
     the level
     specified by
     the :TEXT-INDENT
     argument which
     can be a
SYMBOL
     or an INTEGER
     - cool!
  Don't forget to
  call FORCE-OUTPUT
  on it, and/or use
WITH-FILL-STREAM
  Pretty formatting
  of the
  S-expressions
  printed with ~S
  is preserved:
(DEFUN FOO (X Y Z)
 (IF X (+ Y Z)
  (* Y Z)))
"


These notes document CLISP version 2.41Last modified: 2006-10-13