elisp @@ macro
[bpt/guile.git] / doc / ref / expect.texi
CommitLineData
2da09c3f
MV
1@c -*-texinfo-*-
2@c This is part of the GNU Guile Reference Manual.
3@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004
4@c Free Software Foundation, Inc.
5@c See the file guile.texi for copying conditions.
6
a0e07ba4 7@node Expect
3229f68b 8@section Expect
a0e07ba4
NJ
9
10The macros in this section are made available with:
11
aba0dff5 12@lisp
a0e07ba4 13(use-modules (ice-9 expect))
aba0dff5 14@end lisp
a0e07ba4
NJ
15
16@code{expect} is a macro for selecting actions based on the output from
17a port. The name comes from a tool of similar functionality by Don Libes.
18Actions can be taken when a particular string is matched, when a timeout
19occurs, or when end-of-file is seen on the port. The @code{expect} macro
20is described below; @code{expect-strings} is a front-end to @code{expect}
21based on regexec (see the regular expression documentation).
22
23@defmac expect-strings clause @dots{}
24By default, @code{expect-strings} will read from the current input port.
25The first term in each clause consists of an expression evaluating to
26a string pattern (regular expression). As characters
27are read one-by-one from the port, they are accumulated in a buffer string
28which is matched against each of the patterns. When a
29pattern matches, the remaining expression(s) in
30the clause are evaluated and the value of the last is returned. For example:
31
aba0dff5 32@lisp
a0e07ba4
NJ
33(with-input-from-file "/etc/passwd"
34 (lambda ()
35 (expect-strings
36 ("^nobody" (display "Got a nobody user.\n")
37 (display "That's no problem.\n"))
38 ("^daemon" (display "Got a daemon user.\n")))))
aba0dff5 39@end lisp
a0e07ba4
NJ
40
41The regular expression is compiled with the @code{REG_NEWLINE} flag, so
42that the ^ and $ anchors will match at any newline, not just at the start
43and end of the string.
44
45There are two other ways to write a clause:
46
47The expression(s) to evaluate
48can be omitted, in which case the result of the regular expression match
49(converted to strings, as obtained from regexec with match-pick set to "")
50will be returned if the pattern matches.
51
52The symbol @code{=>} can be used to indicate that the expression is a
53procedure which will accept the result of a successful regular expression
54match. E.g.,
55
aba0dff5 56@lisp
a0e07ba4 57("^daemon" => write)
6dccc950
MD
58("^d(aemon)" => (lambda args (for-each write args)))
59("^da(em)on" => (lambda (all sub)
60 (write all) (newline)
61 (write sub) (newline)))
aba0dff5 62@end lisp
a0e07ba4
NJ
63
64The order of the substrings corresponds to the order in which the
65opening brackets occur.
66
67A number of variables can be used to control the behaviour
68of @code{expect} (and @code{expect-strings}).
69Most have default top-level bindings to the value @code{#f},
70which produces the default behaviour.
71They can be redefined at the
72top level or locally bound in a form enclosing the expect expression.
73
74@table @code
75@item expect-port
76A port to read characters from, instead of the current input port.
77@item expect-timeout
78@code{expect} will terminate after this number of
79seconds, returning @code{#f} or the value returned by expect-timeout-proc.
80@item expect-timeout-proc
81A procedure called if timeout occurs. The procedure takes a single argument:
82the accumulated string.
83@item expect-eof-proc
84A procedure called if end-of-file is detected on the input port. The
85procedure takes a single argument: the accumulated string.
86@item expect-char-proc
87A procedure to be called every time a character is read from the
88port. The procedure takes a single argument: the character which was read.
89@item expect-strings-compile-flags
90Flags to be used when compiling a regular expression, which are passed
91to @code{make-regexp} @xref{Regexp Functions}. The default value
92is @code{regexp/newline}.
93@item expect-strings-exec-flags
94Flags to be used when executing a regular expression, which are
95passed to regexp-exec @xref{Regexp Functions}.
96The default value is @code{regexp/noteol}, which prevents @code{$}
97from matching the end of the string while it is still accumulating,
98but still allows it to match after a line break or at the end of file.
99@end table
100
101Here's an example using all of the variables:
102
103@smalllisp
104(let ((expect-port (open-input-file "/etc/passwd"))
105 (expect-timeout 1)
106 (expect-timeout-proc
107 (lambda (s) (display "Times up!\n")))
108 (expect-eof-proc
109 (lambda (s) (display "Reached the end of the file!\n")))
110 (expect-char-proc display)
111 (expect-strings-compile-flags (logior regexp/newline regexp/icase))
112 (expect-strings-exec-flags 0))
113 (expect-strings
114 ("^nobody" (display "Got a nobody user\n"))))
115@end smalllisp
116@end defmac
117
118@defmac expect clause @dots{}
119@code{expect} is used in the same way as @code{expect-strings},
120but tests are specified not as patterns, but as procedures. The
121procedures are called in turn after each character is read from the
122port, with two arguments: the value of the accumulated string and
123a flag to indicate whether end-of-file has been reached. The flag
124will usually be @code{#f}, but if end-of-file is reached, the procedures
125are called an additional time with the final accumulated string and
126@code{#t}.
127
128The test is successful if the procedure returns a non-false value.
129
130If the @code{=>} syntax is used, then if the test succeeds it must return
131a list containing the arguments to be provided to the corresponding
132expression.
133
134In the following example, a string will only be matched at the beginning
135of the file:
136
aba0dff5 137@lisp
a0e07ba4
NJ
138(let ((expect-port (open-input-file "/etc/passwd")))
139 (expect
140 ((lambda (s eof?) (string=? s "fnord!"))
141 (display "Got a nobody user!\n"))))
aba0dff5 142@end lisp
a0e07ba4
NJ
143
144The control variables described for @code{expect-strings} also
145influence the behaviour of @code{expect}, with the exception of
146variables whose names begin with @code{expect-strings-}.
147@end defmac