1

I am running zsh inside of tmux with prezto, and a basic expect script is exiting improperly:

set timeout -1
spawn $env(SHELL)
expect  -regex ".*"
send "echo 'foo'\r"
expect -regex ".*foo.*\r"
send "^D"
expect eof

What happens is the foo is output and expected, the script exits... but the prompt exposed afterwards is broken until I press CTRL-C on the keyboard. At that point, a % is printed and the next line appears:

❯ ./modified-autoexpect-recording.exp
spawn /bin/zsh
echo 'foo'
❯ echo 'foo'
foo
~/ < ... fancy stuff ... ❯  ^C%  # this was a manual CTRL-C event from a broken prompt
~/ < ... fancy stuff ... ❯       # this is working

A straight autoexpect result produces the same problem. One of the things I noticed is:

~/long/path/here ❯ ^C%              
~/lo/pa/here ❯ # after exiting the frozen prompt

An end to end AutoExpect example:

$: autoexpect
$: echo 'foo'
foo
$:[CTRL-D]
$: ./script.exp
$:[CTRL-C]%
$: # prompt works

Behavior remains constant across the following modifications:

# changes at beginning
set log_user 0
set stty sane

changes at end

send -- '^D' # -> send -- \x04

It definitely has something to do with the custom prompt's path getting abbreviated.

I am happy to change my prompt system, but ideally expect just works w/ some mods.


I am reviewing Don's book (O'Reilly), so maybe the answer is there. In the meantime, are there any tricks to have an expect program exit robustly?

Chris
  • 961
  • 7
  • 20
  • Try log_user 0 at the start of the expect script to stop it copying data it read from the child to the terminal you are in, as it may include some escape sequences. – meuh Mar 03 '23 at 17:04
  • The expect may have effectively done $ stty -echo. You can undo that with $ stty sane. – J_H Mar 03 '23 at 17:49
  • although both fixes did not work, that's probably what is happening, adding details. – Chris Mar 03 '23 at 18:40
  • 2
    I assume the ^D was ineffective, and you're still expecting eof. Try send \x04 – glenn jackman Mar 03 '23 at 18:45
  • 1
    Also expect -regex ".*" is extremely permissive. It is expecting to see zero or more of any characters. You might want to match your prompt more precisely expect -re { $} – glenn jackman Mar 03 '23 at 18:48
  • 1
    Similarly expect -regex ".*foo.*\r" matches the "foo" in echo 'foo', so the ^D is being send quite early. – glenn jackman Mar 03 '23 at 18:49
  • @glennjackman I'll adjust the original autoexpect result from the ^D – Chris Mar 03 '23 at 18:50
  • 1
    Your next step: run with internal tracing on. You have an infinite timeout, and the program is hanging, so there must be a pattern that is not matching. Add exp_internal 1 to the top of the script. The output is quite verbose. Look for "does this pattern match this buffer, yes or no" – glenn jackman Mar 04 '23 at 16:43
  • @glennjackman thank you for the coaching, have to find a time to try – Chris Mar 07 '23 at 14:15

0 Answers0