diff options
Diffstat (limited to 'doc/ref/expect.texi')
-rw-r--r-- | doc/ref/expect.texi | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/doc/ref/expect.texi b/doc/ref/expect.texi new file mode 100644 index 000000000..140fd477e --- /dev/null +++ b/doc/ref/expect.texi @@ -0,0 +1,147 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Expect +@section Expect + +The macros in this section are made available with: + +@lisp +(use-modules (ice-9 expect)) +@end lisp + +@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 (see the regular expression documentation). + +@defmac 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: + +@lisp +(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 lisp + +The regular expression is compiled with the @code{REG_NEWLINE} flag, so +that the ^ and $ 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 +can be omitted, in which case the result of the regular expression match +(converted to strings, as obtained from regexec with match-pick set to "") +will be returned if the pattern matches. + +The symbol @code{=>} can be used to indicate that the expression is a +procedure which will accept the result of a successful regular expression +match. E.g., + +@lisp +("^daemon" => write) +("^d(aemon)" => (lambda args (for-each write args))) +("^da(em)on" => (lambda (all sub) + (write all) (newline) + (write sub) (newline))) +@end lisp + +The order of the substrings corresponds to the order in which the +opening brackets occur. + +A number of variables can be used to control the behaviour +of @code{expect} (and @code{expect-strings}). +Most have default top-level bindings 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 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 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. +@item expect-strings-compile-flags +Flags to be used when compiling a regular expression, which are passed +to @code{make-regexp} @xref{Regexp Functions}. The default value +is @code{regexp/newline}. +@item expect-strings-exec-flags +Flags to be used when executing a regular expression, which are +passed to regexp-exec @xref{Regexp Functions}. +The default value is @code{regexp/noteol}, which prevents @code{$} +from matching the end of the string while it is still accumulating, +but still allows it to match after a line break or at the end of file. +@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-compile-flags (logior regexp/newline regexp/icase)) + (expect-strings-exec-flags 0)) + (expect-strings + ("^nobody" (display "Got a nobody user\n")))) +@end smalllisp +@end defmac + +@defmac 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 two arguments: the value of the accumulated string and +a flag to indicate whether end-of-file has been reached. The flag +will usually be @code{#f}, but if end-of-file is reached, the procedures +are called an additional time with the final accumulated string and +@code{#t}. + +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: + +@lisp +(let ((expect-port (open-input-file "/etc/passwd"))) + (expect + ((lambda (s eof?) (string=? s "fnord!")) + (display "Got a nobody user!\n")))) +@end lisp + +The control variables described for @code{expect-strings} also +influence the behaviour of @code{expect}, with the exception of +variables whose names begin with @code{expect-strings-}. +@end defmac |