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.
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.
#t
if object is a port, otherwise returns
#f
.
#t
if object is an input port, otherwise returns
#f
. Any object satisfying this predicate also satisfies
port?
.
#t
if object is an output port, otherwise returns
#f
. Any object satisfying this predicate also satisfies
port?
.
#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?
.
condition-type:wrong-type-argument
if it is not an 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.
current-input-port
returns the
value of console-i/o-port
.
current-output-port
returns the
value of console-i/o-port
.
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
.
trace
procedure is sent to this port. Initially, trace-output-port
returns the value of console-i/o-port
.
interaction-i/o-port
returns the
value of console-i/o-port
.
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.
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 MS-DOS, the console is a combination of the
keyboard and the display. Under Windows, 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.
For compatibility with old code, console-input-port
and
console-output-port
are synonyms for this variable.
close-input-port
and
close-output-port
are synonyms for close-port
that are
defined for compatibility with standard Scheme.
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. Some operating systems, e.g. unix, do
not distinguish these modes. MS-DOS is an example of an operating
system that does distinguish these modes: in normal mode, MS-DOS
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, MS-DOS ports do not perform newline translation. Unless
otherwise mentioned, the procedures in this section open files in normal
mode.
condition-type:file-operation-error
is
signalled.
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.
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.
open-input-file
, open-output-file
, and
open-i/o-file
, respectively.
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.(20)
call-with-input-file
and
call-with-output-file
, respectively.
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.
with-input-from-file
and
with-output-to-file
, respectively.
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.
0
and
end defaults to (string-length string)
.
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)
with-string-output-port
returns the accumulated output to the
port as a newly allocated string.
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)))
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")
#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)))
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.
In MIT Scheme, if input-port is an interactive input port and no
characters are immediately available, read-char
will hang waiting
for input.
In MIT Scheme, if input-port is an interactive input port and no
characters are immediately available, peek-char
will hang waiting
for input.
#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
.(22)
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.
#t
if object is an end-of-file object; otherwise
returns #f
.
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.
read-string
returns the characters, up to but excluding the
terminating character, as a newly allocated string. However, if end of
file was encountered before any characters were read, read-string
returns an end-of-file object.
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))))))))))
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-output-flush
. If so, then that operation is
invoked to flush the buffer. At present, only the console port defines
discretionary-output-flush
; 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.
write-char
, except that it is usually much faster.
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.
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.(23)
(write-char #\newline output-port)
.
newline
. In either case,
fresh-line
performs discretionary output flushing and returns an
unspecified value.
write
, except that it writes an end-of-line to
output-port before writing object's representation. This
procedure performs discretionary output flushing and returns an
unspecified value.
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.
2
, 8
, 10
,
or 16
; the default is 10
. If *unparser-radix*
is
not 10
, numbers are prefixed to indicate their radix.
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 ...)"
#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)"
#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...\""
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.
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.(24)
format
is a run-time-loadable option. To use it, execute
(load-option 'format)
once before calling it.
~
) 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 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
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
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.
~%
#\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 make the control string look nicer in the middle of a program.
~~
~n~
outputs n tildes.
~newline
@
, 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.
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 Records), vectors that have special tags in their zero-th elements (see section Vectors), and pairs that have special tags in their car fields (see section Lists). There is a different procedure for specifying the written representation of each of these types.
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.
#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
,(25) 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:
"#["
,
name, " "
, and hash.
The following procedure is useful for writing more general kinds of unparser methods.
with-current-unparser-state
.
The port passed to procedure should only be used within the dynamic extent of procedure.
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 must be an I/O port if given. If not given, this port
defaults to the value of (interaction-i/o-port)
; this is
initially the console I/O port.
The required argument prompt must be a string.
The prompt string is formed by appending a space to prompt, unless prompt already ends in a space or is an empty string.
The default behavior of this procedure is to print two newlines, the current REP loop "level number", a space, 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.
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 similar rubbish.
This is the procedure called by debug
and where
to read
the user's commands.
The prompt string is formed by appending a space to prompt, unless prompt already ends in a space or is an empty string.
The default behavior of this procedure is to print two newlines, the current REP loop "level number", a space, 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.
The prompt string is formed by appending a colon and a space to prompt, unless prompt already ends in a space.
The default behavior of this procedure is to print two newlines 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.
prompt-for-expression
to read an expression, then evaluates the
expression using environment; if environment is not given,
the REP loop environment is used.
The prompt string is formed by appending the string " (y or n)? "
to prompt, unless prompt already ends in a space.
The default behavior of this procedure is to print two newlines 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.
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.
Typically the names are symbols, but any object that can be
discriminated by eq?
may be used.
The operations are divided into two classes:
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.
The procedures in this section provide means for constructing ports with custom operations, accessing their operations, and manipulating their internal state.
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
, peek-char
,
and char-ready?
; for output ports, either write-char
or
write-substring
; I/O ports must supply the minimum
operations for both input and output.
port/copy
is normally used to speed up creation of ports. This
is done by creating a template using one of the port constructors
make-input-port
, make-output-port
, or
make-i/o-port
, as appropriate; a dummy state component is
supplied for the template. Then port/copy
is used to make a copy
of the template, supplying the copy with the correct state. This is
useful because the port constructors are somewhat slow, as they must
parse the operations list, provide defaulting for missing
operations, etc.
For compatibility with old code, input-port/copy
and
output-port/copy
are synonyms for this procedure.
For compatibility with old code, input-port/state
and
output-port/state
are synonyms for this procedure.
For compatibility with old code, set-input-port/state!
and
set-output-port/state!
are synonyms for this procedure.
#f
.
For compatibility with old code, input-port/operation
and
output-port/operation
are similar to port/operation
. They
differ in that they translate certain old operation names to new
equivalents before calling port/operation
.
input-port/custom-operation
and
output-port/custom-operation
are synonyms for
input-port/operation
and output-port/operation
,
respectively.
port
. The list is not newly allocated and must not be
modified.
For compatibility with old code, input-port/operation-names
and
output-port/operation-names
are synonyms for this procedure.
eof-object?
. This
is sometimes useful when building input ports.
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.
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.
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.
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.
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.
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.
This section describes the standard operations on input ports.
#f
is returned;
otherwise the operation hangs until input is available.
read-char
.
read-char
.
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.
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.
input-port/operation
on the respective operation
name:
(input-port/operation/read-char input-port) (input-port/operation input-port 'read-char)
(input-port/read-string input-port char-set) ((input-port/operation/read-string input-port) input-port char-set)
This section describes the standard operations on output ports. Following that, some useful custom operations are described.
This operation, if defined, is normally identical to
flush-output
. However, it is not normally defined, and even when
it is, it is invoked at different times (see section Output Procedures).
output-port/operation
on the respective operation
name:
(output-port/operation/write-char output-port) (output-port/operation output-port 'write-char)
(output-port/write-char output-port char) ((output-port/operation/write-char output-port) output-port char)
The following custom operations are generally useful.
#f
is returned.
#f
is returned.
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 79
).
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.
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.