interact

Summary

Interact is an Expect command which gives control of the current process to the user, so that keystrokes are sent to the current process, and the stdout and stderr of the current process are returned.

Interact is quite amazing. [Elaborate]

Documentation

interact options ,cotse.com
expect
The interact command is described on the Expect manpage
Exiting from interact (Expect) ,Well House Consultants ,2005-05-02

Description

While there is Expect for languages other than Tcl, in the sense that a few other languages have extensions that (partially) manage ptys and demand-response dialogues, I know of no other that offers interact's functionality. On the other hand, interact is part of the evidence that most programmers don't know what Expect can do for them; only a tiny minority of Expect scripts appear to invoke interact.


To further elaborate, interact can be thought of as Expect's expect command's big brother. Libes created it (like the expect command) such that it is actually an event loop. When executed, interact returns control of the spawned process to a user (yes, or a program) but allows you to match on tty events (such as eof) or data so that the Expect script resumes control and performs whatever actions defined for the match. As interact will watch input and output at the same time, it is possible to set it to watch keyboard input for a signal, a predefined key sequence, and execute a Tcl procedure corresponding to it - like maybe save all input and output data to a file from then on.

The interact and expect command structures are similar as are their functionality. The major difference is that interact sets up a background matching event loop. expect blocks foreground processing (and ignores user input) during it's matching event loop. interact also has a set of switches that allow programmers to spawn two sessions and connect their ptys, thus letting them drive each other. An example of this is Don Libes' kibitz (and xkibitz) that come packaged with the Expect extension.

Examples

An example of use from the Expect man page :

"For example, the following command runs interact with the following string-body pairs defined:

  • When ^Z is pressed, Expect is suspended. (The -reset flag restores the terminal modes.)
  • When ^A is pressed, the user sees "you typed a control-A" and the process is sent a ^A.
  • When $ is pressed, the user sees the date.
  • When ^C is pressed, Expect exits.
  • If "foo" is entered, the user sees "bar".
  • When ~~ is pressed, the Expect interpreter runs interactively."
set CTRLZ \032
interact {
    -reset $CTRLZ {exec kill -STOP [pid]}
    \001   {send_user "you typed a control-A\n";
            exp_send "\001"
           }
    $      {send_user "The date is [exec date]."}
    \003   exit
    foo    {send_user "bar"}
    ~~
}

Here's another example, showing off some more of interact's capabilities. This came from a chat discussion about changing the timeout of an interactive session on the fly.

package require Expect

proc now {} { clock seconds }
set start_time [now]

proc tick {} {
    global start_time
    expr {[clock seconds]-$start_time}
}

puts "Use +/- to alter the timeout, control-D to exit"

spawn tclsh

# not $timeout, because it's special to expect even if not to interact
set time_out 1

while {1} {
    puts "\[Timeout is: $time_out\]"
    interact {
        timeout $time_out { puts "\[tick [tick]\]" }
        + { incr time_out; return }
        -- - { incr time_out -1; return }
        -o eof {
            puts "We're done here"
            break
        }
    }
}

puts "Phew, that's over"