The expect module handles simple expect(1)-like behaviour. The two main functions are exp-case and exp-send.

One difference in behaviour from expect(1) is that exp-timeout is -1 by default (as Don Libes has said he should have done himself).

import expect

spawn nslookup

 (:re "> $" #t))

;; add a \r to the end of the sent string
exp-send "server" :cr #t

 (:re "> $" #t))

exp-send "www.google.com.\r"

ipv4_addrs := #n
ipv6_addrs := #n

;; wait for the answer section
 ("answer:" #t))

 (:re "Address:[[:space:]]+([.:[:xdigit:]]+)" {
   addr := nth r.1 0
    ("*.*" {
      ipv4_addrs = pair addr ipv4_addrs
    ("*:*" {
      ipv6_addrs = pair addr ipv6_addrs
 (:re "> $" {
   exp-send "exit\r"

if (not (null? ipv4_addrs)) {
  printf "the IPv4 addrs are %s\n" ipv4_addrs

if (not (null? ipv6_addrs)) {
  printf "the IPv6 addrs are %s\n" ipv6_addrs
$ idio simple-expect
spawn nslookup
Default server:

Non-authoritative answer:
Name:   www.google.com
Name:   www.google.com
Address: 2a00:1450:4009:818::2004
the IPv4 addrs are ("")
the IPv6 addrs are ("2a00:1450:4009:818::2004")


spawn runs its arguments as a command in a pseudo-terminal device and sets spawn-id.

exp-case has exp-case-before and exp-case-after siblings.

The clauses to these are

  • (str-kw* str body) where str-kw can be:

    • :re to treat str as a regexp

    • :gl to treat str as a glob-style pattern

    • :ex to treat str as an exact string

    • :icase to use a case-insensitive match

  • (term-kw body) where term-kw can be:

    • :eof to match if End of File is indicated

    • :timeout to match if the timeout is reached

    • :all to always match

If a match occurs the body is invoked with spawn-id, r (the REG_VERBOSE regexec results) and prefix (the contents of spawn-id’s buffer before the match) variables in scope.

exp-continue and exp-break are available in body.

exp-wait will try to drain spawn-id and potentially call exp-close.

Last built at 2023-11-09T07:11:43Z+0000 from 77077af (dev) for Idio 0.3