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

# 14. Input/Output

This chapter describes the procedures that are used for input and output (I/O). The chapter first describes ports and how they are manipulated, then describes the I/O operations. Finally, some low-level procedures are described that permit the implementation of custom ports and high-performance I/O.

> 14.1 Ports |  |
> 14.2 File Ports |  |
> 14.3 String Ports |  |
> 14.4 Input Procedures |  |
> 14.5 Output Procedures |  |
> 14.6 Format |  |
> 14.7 Custom Output |  |
> 14.8 Prompting |  |
> 14.9 Port Primitives |  |

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

## 14.1 Ports

Scheme uses ports for I/O. A port, which can be treated like any other Scheme object, serves as a source or sink for data. A port must be open before it can be read from or written to. The standard I/O port, `console-i/o-port`, is opened automatically when you start Scheme. When you use a file for input or output, you need to explicitly open and close a port to the file (with procedures described in this chapter). Additional procedures let you open ports to strings.

Many input procedures, such as `read-char` and `read`, read data from the current input port by default, or from a port that you specify. The current input port is initially `console-i/o-port`, but Scheme provides procedures that let you change the current input port to be a file or string.

Similarly, many output procedures, such as `write-char` and `display`, write data to the current output port by default, or to a port that you specify. The current output port is initially `console-i/o-port`, but Scheme provides procedures that let you change the current output port to be a file or string.

All ports read or write only ASCII characters.

Every port is either an input port, an output port, or both. The following predicates distinguish all of the possible cases.

procedure+: port? object
  Returns `#t` if object is a port, otherwise returns `#f`.

procedure: input-port? object
  Returns `#t` if object is an input port, otherwise returns `#f`. Any object satisfying this predicate also satisfies `port?`.

procedure: output-port? object
  Returns `#t` if object is an output port, otherwise returns `#f`. Any object satisfying this predicate also satisfies `port?`.

procedure+: i/o-port? object
  Returns `#t` if object is both an input port and an output port, otherwise returns `#f`. Any object satisfying this predicate also satisfies `port?`, `input-port?`, and `output-port?`.

procedure+: guarantee-port object
procedure+: guarantee-input-port object
procedure+: guarantee-output-port object
procedure+: guarantee-i/o-port object
  These procedures check the type of object, signalling an error of type
  `condition-type:wrong-type-argument` if it is not a port, input port, output port, or I/O port, respectively. Otherwise they return object.

The next five procedures return the runtime system's standard ports. All of the standard ports are dynamically bound by the REP loop; this means that when a new REP loop is started, for example by an error, each of these ports is dynamically bound to the I/O port of the REP loop. When the REP loop exits, the ports revert to their original values.

procedure: current-input-port
  Returns the current input port. This is the default port used by many input procedures. Initially, `current-input-port` returns the value of `console-i/o-port`.

procedure: current-output-port
  Returns the current output port. This is the default port used by many output procedures. Initially, `current-output-port` returns the value of `console-i/o-port`.

procedure+: notification-output-port
  Returns an output port suitable for generating "notifications", that is, messages to the user that supply interesting information about the execution of a program. For example, the `load` procedure writes messages to this port informing the user that a file is being loaded. Initially, `notification-output-port` returns the value of `console-i/o-port`.

procedure+: trace-output-port
  Returns an output port suitable for generating "tracing" information about a program's execution. The output generated by the `trace` procedure is sent to this port. Initially, `trace-output-port` returns the value of `console-i/o-port`.

procedure+: interaction-i/o-port
  Returns an I/O port suitable for querying or prompting the user. The standard prompting procedures use this port by default (see section 14.8 Prompting). Initially, `interaction-i/o-port` returns the value of `console-i/o-port`.

procedure+: with-input-from-port input-port thunk
procedure+: with-output-to-port output-port thunk
procedure+: with-notification-output-port output-port thunk
procedure+: with-trace-output-port output-port thunk
procedure+: with-interaction-i/o-port i/o-port thunk
  Thunk must be a procedure of no arguments. Each of these procedures binds one of the standard ports to its first argument, calls thunk with no arguments, restores the port to its original value, and returns the result that was yielded by thunk. This temporary binding is performed the same way as dynamic binding of a variable, including the behavior in the presence of continuations (see section 2.3 Dynamic Binding).

  `with-input-from-port` binds the current input port, `with-output-to-port` binds the current output port, `with-notification-output-port` binds the "notification" output port, `with-trace-output-port` binds the "trace" output port, and `with-interaction-i/o-port` binds the "interaction" I/O port.

procedure+: set-current-input-port! input-port
procedure+: set-current-output-port! output-port
procedure+: set-notification-output-port! output-port
procedure+: set-trace-output-port! output-port
procedure+: set-interaction-i/o-port! i/o-port
  Each of these procedures alters the binding of one of the standard ports and returns an unspecified value. The binding that is modified corresponds to the name of the procedure.

variable+: console-i/o-port
  `console-i/o-port` is an I/O port that communicates with the "console". Under unix, the console is the controlling terminal of the Scheme process. Under Windows and OS/2, the console is the window that is created when Scheme starts up.

  This variable is rarely used; instead programs should use one of the standard ports defined above. This variable should not be modified.

procedure+: close-port port
  Closes port and returns an unspecified value. If port is a file port, the file is closed.

procedure: close-input-port port
  Closes port and returns an unspecified value. Port must be an input port or an I/O port; if it is an I/O port, then only the input side of the port is closed.

procedure: close-output-port port
  Closes port and returns an unspecified value. Port must be an output port or an I/O port; if it is an I/O port, then only the output side of the port is closed.

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

## 14.2 File Ports

Before Scheme can access a file for reading or writing, it is necessary to open a port to the file. This section describes procedures used to open ports to files. Such ports are closed (like any other port) by `close-port`. File ports are automatically closed if and when they are reclaimed by the garbage collector.

Before opening a file for input or output, by whatever method, the filename argument is converted to canonical form by calling the procedure `merge-pathnames` with filename as its sole argument. Thus, filename can be either a string or a pathname, and it is merged with the current pathname defaults to produce the pathname that is then opened.

Any file can be opened in one of two modes, normal or binary. Normal mode is for accessing text files, and binary mode is for accessing other files. Unix does not distinguish these modes, but Windows and OS/2 do: in normal mode, their file ports perform newline translation, mapping between the carriage-return/linefeed sequence that terminates text lines in files, and the `#\newline` that terminates lines in Scheme. In binary mode, such ports do not perform newline translation. Unless otherwise mentioned, the procedures in this section open files in normal mode.

procedure: open-input-file filename
  Takes a filename referring to an existing file and returns an input port capable of delivering characters from the file. If the file cannot be opened, an error of type `condition-type:file-operation-error` is signalled.

procedure: open-output-file filename [append?]
  Takes a filename referring to an output file to be created and returns an output port capable of writing characters to a new file by that name. If the file cannot be opened, an error of type `condition-type:file-operation-error` is signalled.

  The optional argument append? is an MIT Scheme extension. If append? is given and not `#f`, the file is opened in append mode. In this mode, the contents of the file are not overwritten; instead any characters written to the file are appended to the end of the existing contents. If the file does not exist, append mode creates the file and writes to it in the normal way.

procedure+: open-i/o-file filename
  Takes a filename referring to an existing file and returns an I/O port capable of both reading and writing the file. If the file cannot be opened, an error of type `condition-type:file-operation-error` is signalled.

  This procedure is often used to open special files. For example, under unix this procedure can be used to open terminal device files, PTY device files, and named pipes.

procedure+: open-binary-input-file filename
procedure+: open-binary-output-file filename [append?]
procedure+: open-binary-i/o-file filename
  These procedures open files in binary mode. In all other respects they are identical to `open-input-file`, `open-output-file`, and `open-i/o-file`, respectively.

procedure+: close-all-open-files
  This procedure closes all file ports that are open at the time that it is called, and returns an unspecified value.

procedure: call-with-input-file filename procedure
procedure: call-with-output-file filename procedure
  These procedures call procedure with one argument: the port obtained by opening the named file for input or output, respectively. If the file cannot be opened, an error of type `condition-type:file-operation-error` is signalled. If procedure returns, then the port is closed automatically and the value yielded by procedure is returned. If procedure does not return, then the port will not be closed automatically unless it is reclaimed by the garbage collector.(16)

procedure+: call-with-binary-input-file filename procedure
procedure+: call-with-binary-output-file filename procedure
  These procedures open files in binary mode. In all other respects they are identical to `call-with-input-file` and `call-with-output-file`, respectively.

procedure: with-input-from-file filename thunk
procedure: with-output-to-file filename thunk
  Thunk must be a procedure of no arguments. The file is opened for input or output, an input or output port connected to it is made the default value returned by `current-input-port` or `current-output-port`, and the thunk is called with no arguments. When the thunk returns, the port is closed and the previous default is restored. `with-input-from-file` and `with-output-to-file` return the value yielded by thunk. If an escape procedure is used to escape from the continuation of these procedures, their behavior is implementation-dependent; in that situation MIT Scheme leaves the files open.

procedure+: with-input-from-binary-file filename thunk
procedure+: with-output-to-binary-file filename thunk
  These procedures open files in binary mode. In all other respects they are identical to `with-input-from-file` and `with-output-to-file`, respectively.

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

## 14.3 String Ports

This section describes the simplest kinds of ports: input ports that read their input from given strings, and output ports that accumulate their output and return it as a string. It also describes "truncating" output ports, which can limit the length of the resulting string to a given value.

procedure+: string->input-port string [start [end]]
  Returns a new string port that delivers characters from string. The optional arguments start and end may be used to specify that the string port delivers characters from a substring of string; if not given, start defaults to `0` and end defaults to `(string-length string)`.

procedure+: with-input-from-string string thunk
  Thunk must be a procedure of no arguments. `with-input-from-string` creates a new input port that reads from string, makes that port the current input port, and calls thunk. When thunk returns, `with-input-from-string` restores the previous current input port and returns the result yielded by thunk.

      (with-input-from-string "(a b c) (d e f)" read)  =>  (a b c)

  Note: this procedure is equivalent to:

      (with-input-from-port (string->input-port string) thunk)

procedure+: with-string-output-port procedure
  Procedure is called with one argument, an output port. The value yielded by procedure is ignored. When procedure returns, `with-string-output-port` returns the port's accumulated output as a newly allocated string.

procedure+: with-output-to-string thunk
  Thunk must be a procedure of no arguments. `with-output-to-string` creates a new output port that accumulates output, makes that port the default value returned by `current-output-port`, and calls thunk with no arguments. When thunk returns, `with-output-to-string` restores the previous default and returns the accumulated output as a newly allocated string.

      (with-output-to-string
        (lambda ()
          (write 'abc)))                    =>  "abc"

  Note: this procedure is equivalent to:

      (with-string-output-port
       (lambda (port)
         (with-output-to-port port thunk)))

procedure+: with-output-to-truncated-string k thunk
  Similar to `with-output-to-string`, except that the output is limited to k characters. If thunk attempts to write more than k characters, it will be aborted by invoking an escape procedure that returns from `with-output-to-truncated-string`.

  The value of this procedure is a pair; the car of the pair is `#t` if thunk attempted to write more than k characters, and `#f` otherwise. The cdr of the pair is a newly allocated string containing the accumulated output.

  This procedure is helpful for displaying circular lists, as shown in this example:

      (define inf (list 'inf))
      (with-output-to-truncated-string 40
        (lambda ()
          (write inf)))                       =>  (#f . "(inf)")
      (set-cdr! inf inf)
      (with-output-to-truncated-string 40
        (lambda ()
          (write inf)))
              =>  (#t . "(inf inf inf inf inf inf inf inf inf inf")

procedure+: write-to-string object [k]
  Writes object to a string output port, and returns the resulting newly allocated string. If k is supplied and not `#f`, this procedure is equivalent to

      (with-output-to-truncated-string k
        (lambda ()
          (write object)))

  otherwise it is equivalent to

      (with-output-to-string
       (lambda ()
         (write object)))

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

## 14.4 Input Procedures

This section describes the procedures that read input. Input procedures can read either from the current input port or from a given port. Remember that to read from a file, you must first open a port to the file.

Input ports can be divided into two types, called interactive and non-interactive. Interactive input ports are ports that read input from a source that is time-dependent; for example, a port that reads input from a terminal or from another program. Non-interactive input ports read input from a time-independent source, such as an ordinary file or a character string.

All optional arguments called input-port, if not supplied, default to the current input port.

procedure: read-char [input-port]
  Returns the next character available from input-port, updating input-port to point to the following character. If no more characters are available, an end-of-file object is returned.

  In MIT Scheme, if input-port is an interactive input port and no characters are immediately available, `read-char` will hang waiting for input, even if the port is in non-blocking mode.

procedure: peek-char [input-port]
  Returns the next character available from input-port, without updating input-port to point to the following character. If no more characters are available, an end-of-file object is returned.(17)

  In MIT Scheme, if input-port is an interactive input port and no characters are immediately available, `peek-char` will hang waiting for input, even if the port is in non-blocking mode.

procedure: char-ready? [input-port]
  Returns `#t` if a character is ready on input-port and returns `#f` otherwise. If `char-ready?` returns `#t` then the next `read-char` operation on input-port is guaranteed not to hang. If input-port is a file port at end of file then `char-ready?` returns `#t`.(18)

procedure: read [input-port]
  Converts external representations of Scheme objects into the objects themselves. `read` returns the next object parsable from input-port, updating input-port to point to the first character past the end of the written representation of the object. If an end of file is encountered in the input before any characters are found that can begin an object, `read` returns an end-of-file object. The input-port remains open, and further attempts to read will also return an end-of-file object. If an end of file is encountered after the beginning of an object's written representation, but the written representation is incomplete and therefore not parsable, an error is signalled.

procedure: eof-object? object
  Returns `#t` if object is an end-of-file object; otherwise returns `#f`.

procedure+: read-char-no-hang [input-port]
  If input-port can deliver a character without blocking, this procedure acts exactly like `read-char`, immediately returning that character. Otherwise, `#f` is returned, unless input-port is a file port at end of file, in which case an end-of-file object is returned. In no case will this procedure block waiting for input.

procedure+: read-string char-set [input-port]
  Reads characters from input-port until it finds a terminating character that is a member of char-set (see section 5.6 Character Sets) or encounters end of file. The port is updated to point to the terminating character, or to end of file if no terminating character was found. `read-string` returns the characters, up to but excluding the terminating character, as a newly allocated string.

  This procedure ignores the blocking mode of the port, blocking unconditionally until it sees either a delimiter or eof of file. If end of file is encountered before any characters are read, an end-of-file object is returned.

  On many input ports, this operation is significantly faster than the following equivalent code using `peek-char` and `read-char`:

      (define (read-string char-set input-port)
        (let ((char (peek-char input-port)))
          (if (eof-object? char)
              char
              (list->string
               (let loop ((char char))
                 (if (or (eof-object? char)
                         (char-set-member? char-set char))
                     '()
                     (begin
                       (read-char input-port)
                       (cons char
                             (loop (peek-char input-port))))))))))

procedure+: read-line [input-port]
  `read-line` reads a single line of text from input-port, and returns that line as a newly allocated string. The `#\newline` terminating the line, if any, is discarded and does not appear in the returned string.

  This procedure ignores the blocking mode of the port, blocking unconditionally until it has read an entire line. If end of file is encountered before any characters are read, an end-of-file object is returned.

procedure+: read-string! string [input-port]
procedure+: read-substring! string start end [input-port]
  `read-string!` and `read-substring!` fill the specified region of string with characters read from input-port until the region is full or else there are no more characters available from the port. For `read-string!`, the region is all of string, and for `read-substring!`, the region is that part of string specified by start and end.

  The returned value is the number of characters filled into the region. However, there are several interesting cases to consider:

  - If `read-string!` (`read-substring!`) is called when input-port is at "end-of-file", then the returned value is `0`. Note that "end-of-file" can mean a file port that is at the file's end, a string port that is at the string's end, or any other port that will never produce more characters.

  - If input-port is an interactive port (e.g. a terminal), and one or more characters are immediately available, the region is filled using the available characters. The procedure then returns immediately, without waiting for further characters, even if the number of available characters is less than the size of the region. The returned value is the number of characters actually filled in.

  - If input-port is an interactive port and no characters are immediately available, the result of the operation depends on the blocking mode of the port. If the port is in non-blocking mode, `read-string!` (`read-substring!`) immediately returns the value `#f`. Otherwise, the operation blocks until a character is available. As soon as at least one character is available, the region is filled using the available characters. The procedure then returns immediately, without waiting for further characters, even if the number of available characters is less than the size of the region. The returned value is the number of characters actually filled in.

  The importance of `read-string!` and `read-substring!` are that they are both flexible and extremely fast, especially for large amounts of data.

The following variables may be dynamically bound to change the behavior of the `read` procedure.

variable+: *parser-radix*
  This variable defines the radix used by the reader when it parses numbers. This is similar to passing a radix argument to `string->number`. The value of this variable must be one of `2`, `8`, `10`, or `16`; any other value is ignored, and the reader uses radix `10`.

  Note that much of the number syntax is invalid for radixes other than `10`. The reader detects cases where such invalid syntax is used and signals an error. However, problems can still occur when `*parser-radix*` is set to `16`, because syntax that normally denotes symbols can now denote numbers (e.g. `abc`). Because of this, it is usually undesirable to set this variable to anything other than the default.

  The default value of this variable is `10`.

variable+: *parser-canonicalize-symbols?*
  This variable controls how the parser handles case-sensitivity of symbols. If it is bound to its default value of `#t`, symbols read by the parser are converted to lower case before being interned. Otherwise, symbols are interned without case conversion.

  In general, it is a bad idea to use this feature, as it doesn't really make Scheme case-sensitive, and therefore can break features of the Scheme runtime that depend on case-insensitive symbols.

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

## 14.5 Output Procedures

Output ports may or may not support buffering of output, in which output characters are collected together in a buffer and then sent to the output device all at once. (Most of the output ports implemented by the runtime system support buffering.) Sending all of the characters in the buffer to the output device is called flushing the buffer. In general, output procedures do not flush the buffer of an output port unless the buffer is full.

However, the standard output procedures described in this section perform what is called discretionary flushing of the buffer. Discretionary output flushing works as follows. After a procedure performs its output (writing characters to the output buffer), it checks to see if the port implements an operation called `discretionary-flush-output`. If so, then that operation is invoked to flush the buffer. At present, only the console port defines `discretionary-flush-output`; this is used to guarantee that output to the console appears immediately after it is written, without requiring calls to `flush-output`.

All optional arguments called output-port, if not supplied, default to the current output port.

procedure: write-char char [output-port]
  Writes char (the character itself, not a written representation of the character) to output-port, performs discretionary output flushing, and returns an unspecified value.

procedure+: write-string string [output-port]
  Writes string to output-port, performs discretionary output flushing, and returns an unspecified value. This is equivalent to writing the contents of string, one character at a time using `write-char`, except that it is usually much faster.

procedure+: write-substring string start end [output-port]
  Writes the substring defined by string, start, and end to output-port, performs discretionary output flushing, and returns an unspecified value. This is equivalent to writing the contents of the substring, one character at a time using `write-char`, except that it is usually much faster.

procedure: write object [output-port]
  Writes a written representation of object to output-port, and returns an unspecified value. If object has a standard external representation, then the written representation generated by `write` shall be parsable by `read` into an equivalent object. Thus strings that appear in the written representation are enclosed in doublequotes, and within those strings backslash and doublequote are escaped by backslashes. `write` performs discretionary output flushing and returns an unspecified value.

procedure: display object [output-port]
  Writes a representation of object to output-port. Strings appear in the written representation as if written by `write-string` instead of by `write`. Character objects appear in the representation as if written by `write-char` instead of by `write`. `display` performs discretionary output flushing and returns an unspecified value.(19)

procedure: newline [output-port]
  Writes an end-of-line to output-port, performs discretionary output flushing, and returns an unspecified value. Equivalent to `(write-char #\newline output-port)`.

procedure+: fresh-line [output-port]
  Most output ports are able to tell whether or not they are at the beginning of a line of output. If output-port is such a port, this procedure writes an end-of-line to the port only if the port is not already at the beginning of a line. If output-port is not such a port, this procedure is identical to `newline`. In either case, `fresh-line` performs discretionary output flushing and returns an unspecified value.

procedure+: write-line object [output-port]
  Like `write`, except that it writes an end-of-line to output-port after writing object's representation. This procedure performs discretionary output flushing and returns an unspecified value.

procedure+: flush-output [output-port]
  If output-port is buffered, this causes the contents of its buffer to be written to the output device. Otherwise it has no effect. Returns an unspecified value.

procedure+: beep [output-port]
  Performs a "beep" operation on output-port, performs discretionary output flushing, and returns an unspecified value. On the console port, this usually causes the console bell to beep, but more sophisticated interactive ports may take other actions, such as flashing the screen. On most output ports, e.g. file and string output ports, this does nothing.

procedure+: clear [output-port]
  "Clears the screen" of output-port, performs discretionary output flushing, and returns an unspecified value. On a terminal or window, this has a well-defined effect. On other output ports, e.g. file and string output ports, this does nothing.

procedure+: pp object [output-port [as-code?]]
  `pp` prints object in a visually appealing and structurally revealing manner on output-port. If object is a procedure, `pp` attempts to print the source text. If the optional argument as-code? is true, `pp` prints lists as Scheme code, providing appropriate indentation; by default this argument is false. `pp` performs discretionary output flushing and returns an unspecified value.

The following variables may be dynamically bound to change the behavior of the `write` and `display` procedures.

variable+: *unparser-radix*
  This variable specifies the default radix used to print numbers. Its value must be one of the exact integers `2`, `8`, `10`, or `16`; the default is `10`. If `*unparser-radix*` is not `10`, numbers are prefixed to indicate their radix.

variable+: *unparser-list-breadth-limit*
  This variable specifies a limit on the length of the printed representation of a list or vector; for example, if the limit is `4`, only the first four elements of any list are printed, followed by ellipses to indicate any additional elements. The value of this variable must be an exact non-negative integer, or `#f` meaning no limit; the default is `#f`.

      (fluid-let ((*unparser-list-breadth-limit* 4))
        (write-to-string '(a b c d)))
                                      => "(a b c d)"
      (fluid-let ((*unparser-list-breadth-limit* 4))
        (write-to-string '(a b c d e)))
                                      => "(a b c d ...)"

variable+: *unparser-list-depth-limit*
  This variable specifies a limit on the nesting of lists and vectors in the printed representation. If lists (or vectors) are more deeply nested than the limit, the part of the representation that exceeds the limit is replaced by ellipses. The value of this variable must be an exact non-negative integer, or `#f` meaning no limit; the default is `#f`.

      (fluid-let ((*unparser-list-depth-limit* 4))
        (write-to-string '((((a))) b c d)))
                                      => "((((a))) b c d)"
      (fluid-let ((*unparser-list-depth-limit* 4))
        (write-to-string '(((((a)))) b c d)))
                                      => "((((...))) b c d)"

variable+: *unparser-string-length-limit*
  This variable specifies a limit on the length of the printed representation of strings. If a string's length exceeds this limit, the part of the printed representation for the characters exceeding the limit is replaced by ellipses. The value of this variable must be an exact non-negative integer, or `#f` meaning no limit; the default is `#f`.

      (fluid-let ((*unparser-string-length-limit* 4))
        (write-to-string "abcd"))
                                      => "\"abcd\""
      (fluid-let ((*unparser-string-length-limit* 4))
        (write-to-string "abcde"))
                                      => "\"abcd...\""

variable+: *unparse-with-maximum-readability?*
  This variable, which takes a boolean value, tells the printer to use a special printed representation for objects that normally print in a form that cannot be recognized by `read`. These objects are printed using the representation `#@n`, where n is the result of calling `hash` on the object to be printed. The reader recognizes this syntax, calling `unhash` on n to get back the original object. Note that this printed representation can only be recognized by the Scheme program in which it was generated, because these hash numbers are different for each invocation of Scheme.

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

## 14.6 Format

The procedure `format` is very useful for producing nicely formatted text, producing good-looking messages, and so on. MIT Scheme's implementation of `format` is similar to that of Common Lisp, except that Common Lisp defines many more directives.(20)

`format` is a run-time-loadable option. To use it, execute

    (load-option 'format)

once before calling it.

procedure+: format destination control-string argument ...
  Writes the characters of control-string to destination, except that a tilde (`~`) introduces a format directive. The character after the tilde, possibly preceded by prefix parameters and modifiers, specifies what kind of formatting is desired. Most directives use one or more arguments to create their output; the typical directive puts the next argument into the output, formatted in some special way. It is an error if no argument remains for a directive requiring an argument, but it is not an error if one or more arguments remain unprocessed by a directive.

  The output is sent to destination. If destination is `#f`, a string is created that contains the output; this string is returned as the value of the call to `format`. In all other cases `format` returns an unspecified value. If destination is `#t`, the output is sent to the current output port. Otherwise, destination must be an output port, and the output is sent there.

  This procedure performs discretionary output flushing (see section 14.5 Output Procedures).

  A `format` directive consists of a tilde (`~`), optional prefix parameters separated by commas, optional colon (`:`) and at-sign (`@`) modifiers, and a single character indicating what kind of directive this is. The alphabetic case of the directive character is ignored. The prefix parameters are generally integers, notated as optionally signed decimal numbers. If both the colon and at-sign modifiers are given, they may appear in either order.

  In place of a prefix parameter to a directive, you can put the letter ``V'` (or ``v'`), which takes an argument for use as a parameter to the directive. Normally this should be an exact integer. This feature allows variable-width fields and the like. You can also use the character ``#'` in place of a parameter; it represents the number of arguments remaining to be processed.

  It is an error to give a format directive more parameters than it is described here as accepting. It is also an error to give colon or at-sign modifiers to a directive in a combination not specifically described here as being meaningful.

  `~A`
    The next argument, which may be any object, is printed as if by `display`. `~mincolA` inserts spaces on the right, if necessary, to make the width at least mincol columns. The `@` modifier causes the spaces to be inserted on the left rather than the right.

  `~S`
    The next argument, which may be any object, is printed as if by `write`. `~mincolS` inserts spaces on the right, if necessary, to make the width at least mincol columns. The `@` modifier causes the spaces to be inserted on the left rather than the right.

  `~%`
    This outputs a `#\newline` character. `~n%` outputs n newlines. No argument is used. Simply putting a newline in control-string would work, but `~%` is often used because it makes the control string look nicer in the middle of a program.

  `~~`
    This outputs a tilde. `~n~` outputs n tildes.

  `~newline`
    Tilde immediately followed by a newline ignores the newline and any following non-newline whitespace characters. With an `@`, the newline is left in place, but any following whitespace is ignored. This directive is typically used when control-string is too long to fit nicely into one line of the program:

        (define (type-clash-error procedure arg spec actual)
          (format
           #t
           "~%Procedure ~S~%requires its %A argument ~
            to be of type ~S,~%but it was called with ~
            an argument of type ~S.~%"
           procedure arg spec actual))

        (type-clash-error 'vector-ref
                          "first"
                          'integer
                          'vector)

        prints

        Procedure vector-ref
        requires its first argument to be of type integer,
        but it was called with an argument of type vector.

    Note that in this example newlines appear in the output only as specified by the `~%` directives; the actual newline characters in the control string are suppressed because each is preceded by a tilde.

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

## 14.7 Custom Output

MIT Scheme provides hooks for specifying that certain kinds of objects have special written representations. There are no restrictions on the written representations, but only a few kinds of objects may have custom representation specified for them, specifically: records (see section 10.4 Records), vectors that have special tags in their zero-th elements (see section 8. Vectors), and pairs that have special tags in their car fields (see section 7. Lists). There is a different procedure for specifying the written representation of each of these types.

procedure+: set-record-type-unparser-method! record-type unparser-method
  Changes the unparser method of the type represented by record-type to be unparser-method, and returns an unspecified value. Subsequently, when the unparser encounters a record of this type, it will invoke unparser-method to generate the written representation.

procedure+: unparser/set-tagged-vector-method! tag unparser-method
  Changes the unparser method of the vector type represented by tag to be unparser-method, and returns an unspecified value. Subsequently, when the unparser encounters a vector with tag as its zero-th element, it will invoke unparser-method to generate the written representation.

procedure+: unparser/set-tagged-pair-method! tag unparser-method
  Changes the unparser method of the pair type represented by tag to be unparser-method, and returns an unspecified value. Subsequently, when the unparser encounters a pair with tag in its car field, it will invoke unparser-method to generate the written representation.

An unparser method is a procedure that is invoked with two arguments: an unparser state and an object. An unparser method generates a written representation for the object, writing it to the output port specified by the unparser state. The value yielded by an unparser method is ignored. Note that an unparser state is not an output port, rather it is an object that contains an output port as one of its components. Application programs generally do not construct or examine unparser state objects, but just pass them along.

There are two ways to create an unparser method (which is then registered by one of the above procedures). The first, and easiest, is to use `standard-unparser-method`. The second is to define your own method using the procedure `with-current-unparser-state`. We encourage the use of the first method, as it results in a more uniform appearance for objects. Many predefined datatypes, for example procedures and environments, already have this appearance.

procedure+: standard-unparser-method name procedure
  Returns a standard unparser method. Name may be any object, and is used as the name of the type with which the unparser method is associated; name is usually a symbol. Procedure must be `#f` or a procedure of two arguments.

  If procedure is `#f`, the returned method generates an external representation of this form:

      #[name hash]

  Here name is the external representation of the argument name, as generated by `write`,(21) and hash is the external representation of an exact non-negative integer unique to the object being printed (specifically, it is the result of calling `hash` on the object). Subsequently, the expression

      #@hash

  is notation for the object.

  If procedure is supplied, the returned method generates a slightly different external representation:

      #[name hash output]

  Here name and hash are as above, and output is the output generated by procedure. The representation is constructed in three stages:

  1. The first part of the format (up to output) is written to the output port specified by the unparser state. This is `"#["`, name, `" "`, and hash.

  2. Procedure is invoked on two arguments: the object and an output port.

  3. The closing bracket is written to the output port.

The following procedure is useful for writing more general kinds of unparser methods.

procedure+: with-current-unparser-state unparser-state procedure
  This procedure calls procedure with one argument, the output port from unparser-state. Additionally, it arranges for the remaining components of unparser-state to be given to the printer when they are needed. The procedure generates some output by writing to the output port using the usual output operations, and the value yielded by procedure is returned from `with-current-unparser-state`.

  The port passed to procedure should only be used within the dynamic extent of procedure.

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

## 14.8 Prompting

This section describes procedures that prompt the user for input. Why should the programmer use these procedures when it is possible to do prompting using ordinary input and output procedures? One reason is that the prompting procedures are more succinct. However, a second and better reason is that the prompting procedures can be separately customized for each user interface, providing more natural interaction. The interfaces for Edwin and for GNU Emacs have already been customized in this fashion; because Edwin and Emacs are very similar editors, their customizations provide very similar behavior.

Each of these procedure accepts an optional argument called port, which if given must be an I/O port. If not given, this port defaults to the value of `(interaction-i/o-port)`; this is initially the console I/O port.

procedure+: prompt-for-command-expression prompt [port]
  Prompts the user for an expression that is to be executed as a command. This is the procedure called by the REP loop to read the user's expressions.

  If prompt is a string, it is used verbatim as the prompt string. Otherwise, it must be a pair whose car is `standard` and whose cdr is a string; in this case the prompt string is formed by prepending to the string the current REP loop "level number" and a space. Also, a space is appended to the string, unless it already ends in a space or is an empty string.

  The default behavior of this procedure is to print a fresh line, a newline, and the prompt string; flush the output buffer; then read an object and return it.

  Under Edwin and Emacs, before the object is read, the interaction buffer is put into a mode that allows expressions to be edited and submitted for input using specific editor commands. The first expression that is submitted is returned as the value of this procedure.

procedure+: prompt-for-command-char prompt [port]
  Prompts the user for a single character that is to be executed as a command; the returned character is guaranteed to satisfy `char-graphic?`. If at all possible, the character is read from the user interface using a mode that reads the character as a single keystroke; in other words, it should not be necessary for the user to follow the character with a carriage return or something similar.

  This is the procedure called by `debug` and `where` to read the user's commands.

  If prompt is a string, it is used verbatim as the prompt string. Otherwise, it must be a pair whose car is `standard` and whose cdr is a string; in this case the prompt string is formed by prepending to the string the current REP loop "level number" and a space. Also, a space is appended to the string, unless it already ends in a space or is an empty string.

  The default behavior of this procedure is to print a fresh line, a newline, and the prompt string; flush the output buffer; read a character in raw mode, echo that character, and return it.

  Under Edwin and Emacs, instead of reading a character, the interaction buffer is put into a mode in which graphic characters submit themselves as input. After this mode change, the first such character submitted is returned as the value of this procedure.

procedure+: prompt-for-expression prompt [port]
  Prompts the user for an expression.

  The prompt string is formed by appending a colon and a space to prompt, unless prompt already ends in a space or is the null string.

  The default behavior of this procedure is to print a fresh line, a newline, and the prompt string; flush the output buffer; then read an object and return it.

  Under Edwin and Emacs, the expression is read in the minibuffer.

procedure+: prompt-for-evaluated-expression prompt [environment [port]]
  Prompts the user for an evaluated expression. Calls `prompt-for-expression` to read an expression, then evaluates the expression using environment; if environment is not given, the REP loop environment is used.

procedure+: prompt-for-confirmation prompt [port]
  Prompts the user for confirmation. The result yielded by this procedure is a boolean.

  The prompt string is formed by appending the string `" (y or n)? "` to prompt, unless prompt already ends in a space or is the null string.

  The default behavior of this procedure is to print a fresh line, a newline, and the prompt string; flush the output buffer; then read a character in raw mode. If the character is `#\y`, `#\Y`, or `#\space`, the procedure returns `#t`; If the character is `#\n`, `#\N`, or `#\rubout`, the procedure returns `#f`. Otherwise the prompt is repeated.

  Under Edwin or Emacs, the confirmation is read in the minibuffer.

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

## 14.9 Port Primitives

This section describes the low-level operations that can be used to build and manipulate I/O ports.

The purpose of these operations is twofold: to allow programmers to construct new kinds of I/O ports, and to provide faster I/O operations than those supplied by the standard high level procedures. The latter is useful because the standard I/O operations provide defaulting and error checking, and sometimes other features, which are often unnecessary. This interface provides the means to bypass such features, thus improving performance.

The abstract model of an I/O port, as implemented here, is a combination of a set of named operations and a state. The state is an arbitrary object, the meaning of which is determined by the operations. The operations are defined by a mapping from names to procedures.

The set of named operations is represented by an object called a port type. A port type is constructed from a set of named operations, and is subsequently used to construct a port. The port type completely specifies the behavior of the port. Port types also support a simple form of inheritance, allowing you to create new ports that are similar to existing ports.

The port operations are divided into two classes:

Standard operations
  There is a specific set of standard operations for input ports, and a different set for output ports. Applications can assume that the standard input operations are implemented for all input ports, and likewise the standard output operations are implemented for all output ports.

Custom operations
  Some ports support additional operations. For example, ports that implement output to terminals (or windows) may define an operation named `y-size` that returns the height of the terminal in characters. Because only some ports will implement these operations, programs that use custom operations must test each port for their existence, and be prepared to deal with ports that do not implement them.

> 14.9.1 Port Types |  |
> 14.9.2 Constructors and Accessors for Ports |  |
> 14.9.3 Input Port Operations |  |
> 14.9.4 Output Port Operations |  |
> 14.9.5 Blocking Mode |  |
> 14.9.6 Terminal Mode |  |

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

### 14.9.1 Port Types

The procedures in this section provide means for constructing port types with standard and custom operations, and accessing their operations.

procedure+: make-port-type operations port-type
  Creates and returns a new port type. Operations must be a list; each element is a list of two elements, the name of the operation (a symbol) and the procedure that implements it. Port-type is either `#f` or a port type; if it is a port type, any operations implemented by port-type but not specified in operations will be implemented by the resulting port type.

  Operations need not contain definitions for all of the standard operations; the procedure will provide defaults for any standard operations that are not defined. At a minimum, the following operations must be defined: for input ports, `read-char` and `peek-char`; for output ports, either `write-char` or `write-substring`. I/O ports must supply the minimum operations for both input and output.

  If an operation in operations is defined to be `#f`, then the corresponding operation in port-type is not inherited.

  If `read-char` is defined in operations, then any standard input operations defined in port-type are ignored. Likewise, if `write-char` or `write-substring` is defined in operations, then any standard output operations defined in port-type are ignored. This feature allows overriding the standard operations without having to enumerate them.

procedure+: port-type? object
procedure+: input-port-type? object
procedure+: output-port-type? object
procedure+: i/o-port-type? object
  These predicates return `#t` if object is a port type, input-port type, output-port type, or I/O-port type, respectively. Otherwise, they return `#f`.

procedure+: port-type/operations port-type
  Returns a newly allocated list containing all of the operations implemented by port-type. Each element of the list is a list of two elements -- the name and its associated operation.

procedure+: port-type/operation-names port-type
  Returns a newly allocated list whose elements are the names of the operations implemented by port-type.

procedure+: port-type/operation port-type symbol
  Returns the operation named symbol in port-type. If port-type has no such operation, returns `#f`.

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

### 14.9.2 Constructors and Accessors for Ports

The procedures in this section provide means for constructing ports, accessing the type of a port, and manipulating the state of a port.

procedure+: make-port port-type state
  Returns a new port with type port-type and the given state. The port will be an input, output, or I/O port according to port-type.

procedure+: port/type port
  Returns the port type of port.

procedure+: port/state port
  Returns the state component of port.

procedure+: set-port/state! port object
  Changes the state component of port to be object. Returns an unspecified value.

procedure+: port/operation port symbol
  Equivalent to

      (port-type/operation (port/type port) symbol)

procedure+: port/operation-names port
  Equivalent to

      (port-type/operation-names (port/type port))

procedure+: make-eof-object input-port
  Returns an object that satisfies the predicate `eof-object?`. This is sometimes useful when building input ports.

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

### 14.9.3 Input Port Operations

This section describes the standard operations on input ports. Following that, some useful custom operations are described.

operation+: input port read-char input-port
  Removes the next character available from input-port and returns it. If input-port has no more characters and will never have any (e.g. at the end of an input file), this operation returns an end-of-file object. If input-port has no more characters but will eventually have some more (e.g. a terminal where nothing has been typed recently), and it is in non-blocking mode, `#f` is returned; otherwise the operation hangs until input is available.

operation+: input port peek-char input-port
  Reads the next character available from input-port and returns it. The character is not removed from input-port, and a subsequent attempt to read from the port will get that character again. In other respects this operation behaves like `read-char`.

operation+: input port discard-char input-port
  Discards the next character available from input-port and returns an unspecified value. In other respects this operation behaves like `read-char`.

operation+: input port char-ready? input-port k
  `char-ready?` returns `#t` if at least one character is available to be read from input-port. If no characters are available, the operation waits up to k milliseconds before returning `#f`, returning immediately if any characters become available while it is waiting.

operation+: input port read-string input-port char-set
operation+: input port discard-chars input-port char-set
  These operations are like `read-char` and `discard-char`, except that they read or discard multiple characters at once. This can have a marked performance improvement on buffered input ports. All characters up to, but excluding, the first character in char-set (or end of file) are read from input-port. `read-string` returns these characters as a newly allocated string, while `discard-chars` discards them and returns an unspecified value. These operations hang until sufficient input is available, even if input-port is in non-blocking mode. If end of file is encountered before any input characters, `read-string` returns an end-of-file object.

operation+: input port read-substring input-port string start end
  Reads characters from input-port into the substring defined by string, start, and end until either the substring has been filled or there are no more characters available. Returns the number of characters written to the substring.

  If input-port is an interactive port, and at least one character is immediately available, the available characters are written to the substring and this operation returns immediately. If no characters are available, and input-port is in blocking mode, the operation blocks until at least one character is available. Otherwise, the operation returns `#f` immediately.

  This is an extremely fast way to read characters from a port.

procedure+: input-port/read-char input-port
procedure+: input-port/peek-char input-port
procedure+: input-port/discard-char input-port
procedure+: input-port/char-ready? input-port k
procedure+: input-port/read-string input-port char-set
procedure+: input-port/discard-chars input-port char-set
procedure+: input-port/read-substring input-port string start end
  Each of these procedures invokes the respective operation on input-port. For example, the following are equivalent:

      (input-port/read-char input-port)
      ((input-port/operation input-port 'read-char) input-port)

The following custom operations are implemented for input ports to files, and will also work with some other kinds of input ports:

operation+: input port eof? input-port
  Returns `#t` if input-port is known to be at end of file, otherwise it returns `#f`.

operation+: input port chars-remaining input-port
  Returns an estimate of the number of characters remaining to be read from input-port. This is useful only when input-port is a file port in binary mode; in other cases, it returns `#f`.

operation+: input port buffered-input-chars input-port
  Returns the number of unread characters that are stored in input-port's buffer. This will always be less than or equal to the buffer's size.

operation+: input port input-buffer-size input-port
  Returns the maximum number of characters that input-port's buffer can hold.

operation+: input port set-input-buffer-size input-port size
  Resizes input-port's buffer so that it can hold at most size characters. Characters in the buffer are discarded. Size must be an exact non-negative integer.

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

### 14.9.4 Output Port Operations

This section describes the standard operations on output ports. Following that, some useful custom operations are described.

operation+: output port write-char output-port char
  Writes char to output-port and returns an unspecified value.

operation+: output port write-substring output-port string start end
  Writes the substring specified by string, start, and end to output-port and returns an unspecified value. Equivalent to writing the characters of the substring, one by one, to output-port, but is implemented very efficiently.

operation+: output port fresh-line output-port
  Most output ports are able to tell whether or not they are at the beginning of a line of output. If output-port is such a port, end-of-line is written to the port only if the port is not already at the beginning of a line. If output-port is not such a port, and end-of-line is unconditionally written to the port. Returns an unspecified value.

operation+: output port flush-output output-port
  If output-port is buffered, this causes its buffer to be written out. Otherwise it has no effect. Returns an unspecified value.

operation+: output port discretionary-flush-output output-port
  Normally, this operation does nothing. However, ports that support discretionary output flushing implement this operation identically to `flush-output`.

procedure+: output-port/write-char output-port char
procedure+: output-port/write-substring output-port string start end
procedure+: output-port/fresh-line output-port
procedure+: output-port/flush-output output-port
procedure+: output-port/discretionary-flush-output output-port
  Each of these procedures invokes the respective operation on output-port. For example, the following are equivalent:

      (output-port/write-char output-port char)
      ((output-port/operation output-port 'write-char)
       output-port char)

procedure+: output-port/write-string output-port string
  Writes string to output-port. Equivalent to

      (output-port/write-substring output-port
                                   string
                                   0
                                   (string-length string))

The following custom operations are generally useful.

operation+: output port buffered-output-chars output-port
  Returns the number of unwritten characters that are stored in output-port's buffer. This will always be less than or equal to the buffer's size.

operation+: output port output-buffer-size output-port
  Returns the maximum number of characters that output-port's buffer can hold.

operation+: output port set-output-buffer-size output-port size
  Resizes output-port's buffer so that it can hold at most size characters. Characters in the buffer are discarded. Size must be an exact non-negative integer.

operation+: output port x-size output-port
  Returns an exact positive integer that is the width of output-port in characters. If output-port has no natural width, e.g. if it is a file port, `#f` is returned.

operation+: output port y-size output-port
  Returns an exact positive integer that is the height of output-port in characters. If output-port has no natural height, e.g. if it is a file port, `#f` is returned.

procedure+: output-port/x-size output-port
  This procedure invokes the custom operation whose name is the symbol `x-size`, if it exists. If the `x-size` operation is both defined and returns a value other than `#f`, that value is returned as the result of this procedure. Otherwise, `output-port/x-size` returns a default value (currently `80`).

  `output-port/x-size` is useful for programs that tailor their output to the width of the display (a fairly common practice). If the output device is not a display, such programs normally want some reasonable default width to work with, and this procedure provides exactly that.

procedure+: output-port/y-size output-port
  This procedure invokes the custom operation whose name is the symbol `y-size`, if it exists. If the `y-size` operation is defined, the value it returns is returned as the result of this procedure; otherwise, `#f` is returned.

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

### 14.9.5 Blocking Mode

An interactive port is always in one of two modes: blocking or non-blocking. This mode is independent of the terminal mode: each can be changed independent of the other. Furthermore, if it is an interactive I/O port, there are separate blocking modes for input and for output.

If an input port is in blocking mode, attempting to read from it when no input is available will cause Scheme to "block", i.e. suspend itself, until input is available. If an input port is in non-blocking mode, attempting to read from it when no input is available will cause the reading procedure to return immediately, indicating the lack of input in some way (exactly how this situation is indicated is separately specified for each procedure or operation).

An output port in blocking mode will block if the output device is not ready to accept output. In non-blocking mode it will return immediately after performing as much output as the device will allow (again, each procedure or operation reports this situation in its own way).

Interactive ports are initially in blocking mode; this can be changed at any time with the procedures defined in this section.

These procedures represent blocking mode by the symbol `blocking`, and non-blocking mode by the symbol `nonblocking`. An argument called mode must be one of these symbols. A port argument to any of these procedures may be any port, even if that port does not support blocking mode; in that case, the port is not modified in any way.

procedure+: port/input-blocking-mode port
  Returns the input blocking mode of port.

procedure+: port/set-input-blocking-mode port mode
  Changes the input blocking mode of port to be mode. Returns an unspecified value.

procedure+: port/with-input-blocking-mode port mode thunk
  Thunk must be a procedure of no arguments. `port/with-input-blocking-mode` binds the input blocking mode of port to be mode, executes thunk, restores the input blocking mode of port to what it was when `port/with-input-blocking-mode` was called, and returns the value that was yielded by thunk. This binding is performed by `dynamic-wind`, which guarantees that the input blocking mode is restored if thunk escapes from its continuation.

procedure+: port/output-blocking-mode port
  Returns the output blocking mode of port.

procedure+: port/set-output-blocking-mode port mode
  Changes the output blocking mode of port to be mode. Returns an unspecified value.

procedure+: port/with-output-blocking-mode port mode thunk
  Thunk must be a procedure of no arguments. `port/with-output-blocking-mode` binds the output blocking mode of port to be mode, executes thunk, restores the output blocking mode of port to what it was when `port/with-output-blocking-mode` was called, and returns the value that was yielded by thunk. This binding is performed by `dynamic-wind`, which guarantees that the output blocking mode is restored if thunk escapes from its continuation.

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

### 14.9.6 Terminal Mode

A port that reads from or writes to a terminal has a terminal mode; this is either cooked or raw. This mode is independent of the blocking mode: each can be changed independent of the other. Furthermore, a terminal I/O port has independent terminal modes both for input and for output.

A terminal port in cooked mode provides some standard processing to make the terminal easy to communicate with. For example, under unix, cooked mode on input reads from the terminal a line at a time and provides rubout processing within the line, while cooked mode on output might translate linefeeds to carriage-return/linefeed pairs. In general, the precise meaning of cooked mode is operating-system dependent, and furthermore might be customizable by means of operating system utilities. The basic idea is that cooked mode does whatever is necessary to make the terminal handle all of the usual user-interface conventions for the operating system, while keeping the program's interaction with the port as normal as possible.

A terminal port in raw mode disables all of that processing. In raw mode, characters are directly read from and written to the device without any translation or interpretation by the operating system. On input, characters are available as soon as they are typed, and are not echoed on the terminal by the operating system. In general, programs that put ports in raw mode have to know the details of interacting with the terminal. In particular, raw mode is used for writing programs such as text editors.

Terminal ports are initially in cooked mode; this can be changed at any time with the procedures defined in this section.

These procedures represent cooked mode by the symbol `cooked`, and raw mode by the symbol `raw`. Additionally, the value `#f` represents "no mode"; it is the terminal mode of a port that is not a terminal. An argument called mode must be one of these three values. A port argument to any of these procedures may be any port, even if that port does not support terminal mode; in that case, the port is not modified in any way.

procedure+: port/input-terminal-mode port
  Returns the input terminal mode of port.

procedure+: port/set-input-terminal-mode port mode
  Changes the input terminal mode of port to be mode. Returns an unspecified value.

procedure+: port/with-input-terminal-mode port mode thunk
  Thunk must be a procedure of no arguments. `port/with-input-terminal-mode` binds the input terminal mode of port to be mode, executes thunk, restores the input terminal mode of port to what it was when `port/with-input-terminal-mode` was called, and returns the value that was yielded by thunk. This binding is performed by `dynamic-wind`, which guarantees that the input terminal mode is restored if thunk escapes from its continuation.

procedure+: port/output-terminal-mode port
  Returns the output terminal mode of port.

procedure+: port/set-output-terminal-mode port mode
  Changes the output terminal mode of port to be mode. Returns an unspecified value.

procedure+: port/with-output-terminal-mode port mode thunk
  Thunk must be a procedure of no arguments. `port/with-output-terminal-mode` binds the output terminal mode of port to be mode, executes thunk, restores the output terminal mode of port to what it was when `port/with-output-terminal-mode` was called, and returns the value that was yielded by thunk. This binding is performed by `dynamic-wind`, which guarantees that the output terminal mode is restored if thunk escapes from its continuation.

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

This document was generated by Chris Hanson on September, 4 2000 using texi2html