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