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