mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 20:00:19 +02:00
132 lines
4.7 KiB
Text
132 lines
4.7 KiB
Text
@node Other Unix
|
|
@chapter Other Unix-specific facilities
|
|
|
|
@menu
|
|
* Expect:: Expect, for pattern matching from a port.
|
|
@end menu
|
|
|
|
@node Expect
|
|
@section Expect: Pattern Matching from a Port
|
|
|
|
@code{expect} is a macro for selecting actions based on the output from
|
|
a port. The name comes from a tool of similar functionality by Don Libes.
|
|
Actions can be taken when a particular string is matched, when a timeout
|
|
occurs, or when end-of-file is seen on the port. The @code{expect} macro
|
|
is described below; @code{expect-strings} is a front-end to @code{expect}
|
|
based on regexec @xref{Regular expressions}.
|
|
|
|
Using these macros requires for now:
|
|
@smalllisp
|
|
(load-from-path "ice-9/expect")
|
|
@end smalllisp
|
|
|
|
@defun expect-strings clause @dots{}
|
|
By default, @code{expect-strings} will read from the current input port.
|
|
The first term in each clause consists of an expression evaluating to
|
|
a string pattern (regular expression). As characters
|
|
are read one-by-one from the port, they are accumulated in a buffer string
|
|
which is matched against each of the patterns. When a
|
|
pattern matches, the remaining expression(s) in
|
|
the clause are evaluated and the value of the last is returned. For example:
|
|
|
|
@smalllisp
|
|
(with-input-from-file "/etc/passwd"
|
|
(lambda ()
|
|
(expect-strings
|
|
("^nobody" (display "Got a nobody user.\n")
|
|
(display "That's no problem.\n"))
|
|
("^daemon" (display "Got a daemon user.\n")))))
|
|
@end smalllisp
|
|
|
|
The regular expression is compiled with the @code{REG_NEWLINE} flag, so
|
|
that the @code{^} and @code{$} anchors will match at any newline, not
|
|
just at the start
|
|
and end of the string.
|
|
|
|
There are two other ways to write a clause:
|
|
|
|
The expression(s) to evaluate on a match
|
|
can be omitted, in which case the result of the match
|
|
(converted to strings, as obtained from regexec with @var{match-pick}
|
|
set to @code{""}) will be returned if the pattern matches.
|
|
|
|
The symbol @code{=>} can be used to indicate that there is a single
|
|
expression to evaluate on a match, which must be a
|
|
procedure which will accept the result of a successful match (converted
|
|
to strings, as obtained from regexec with @var{match-pick} set to
|
|
@code{""}). E.g.,
|
|
|
|
@smalllisp
|
|
("^daemon" => write)
|
|
("^d\\(aemon\\)" => (lambda args (map write args)))
|
|
("^da\\(em\\)on" => (lambda (all sub)
|
|
(write all)
|
|
(write sub)))
|
|
@end smalllisp
|
|
|
|
The order of the substrings corresponds to the order in which the
|
|
opening brackets occur in the regular expression.
|
|
|
|
A number of variables can be used to control the behaviour
|
|
of @code{expect} (and @code{expect-strings}).
|
|
By default they are all bound at the top level to
|
|
the value @code{#f}, which produces the default behaviour.
|
|
They can be redefined at the
|
|
top level or locally bound in a form enclosing the @code{expect} expression.
|
|
|
|
@table @code
|
|
@item expect-port
|
|
A port to read characters from, instead of the current input port.
|
|
@item expect-timeout
|
|
@code{expect} will terminate after this number of
|
|
seconds, returning @code{#f} or the value returned by
|
|
@code{expect-timeout-proc}.
|
|
@item expect-timeout-proc
|
|
A procedure called if timeout occurs. The procedure takes a single argument:
|
|
the accumulated string.
|
|
@item expect-eof-proc
|
|
A procedure called if end-of-file is detected on the input port. The
|
|
procedure takes a single argument: the accumulated string.
|
|
@item expect-char-proc
|
|
A procedure to be called every time a character is read from the
|
|
port. The procedure takes a single argument: the character which was read.
|
|
@end table
|
|
|
|
Here's an example using all of the variables:
|
|
|
|
@smalllisp
|
|
(let ((expect-port (open-input-file "/etc/passwd"))
|
|
(expect-timeout 1)
|
|
(expect-timeout-proc
|
|
(lambda (s) (display "Times up!\n")))
|
|
(expect-eof-proc
|
|
(lambda (s) (display "Reached the end of the file!\n")))
|
|
(expect-char-proc display))
|
|
(expect-strings
|
|
("^nobody" (display "Got a nobody user\n"))))
|
|
@end smalllisp
|
|
@end defun
|
|
|
|
@defun expect clause @dots{}
|
|
@code{expect} is used in the same way as @code{expect-strings},
|
|
but tests are specified not as patterns, but as procedures. The
|
|
procedures are called in turn after each character is read from the
|
|
port, with the value of the accumulated string as the argument. The
|
|
test is successful if the procedure returns a non-false value.
|
|
|
|
If the @code{=>} syntax is used, then if the test succeeds it must return
|
|
a list containing the arguments to be provided to the corresponding
|
|
expression.
|
|
|
|
In the following example, a string will only be matched at the beginning
|
|
of the file:
|
|
@smalllisp
|
|
(let ((expect-port (open-input-file "/etc/passwd")))
|
|
(expect
|
|
((lambda (s) (string=? s "fnord!"))
|
|
(display "Got a nobody user!\n"))))
|
|
@end smalllisp
|
|
|
|
The control variables described for @code{expect-strings} can also
|
|
be used with @code{expect}.
|
|
@end defun
|