Demo

Run on a loop until the program works

1
while ! make-it-run pti38 "ModuleNotFoundError:.*" "tm -w -te sps -args pip-install-from-error"; do echo "Retrying"; done

asciinema recording

Code

The invocation command

1
make-it-run pti38 "ModuleNotFoundError:.*" "sps pip-install-from-error"

shell

make-it-run

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/bin/bash
export TTY

( hs "$(basename "$0")" "$@" "#" "<==" "$(ps -o comm= $PPID)" 0</dev/null ) &>/dev/null

# command
c="$1"
# expect bad pattern
e="$2"
# fix command
fc="$3"

{ test -z "$c" || test -z "$e" || test -z "$fc"; } && exit 1

e="$(p "$e" | sed 's/\([[`;$"]\)/\\\1/g')"

x -sh "$c" -w "expect {\n-re \"$e\" { set user_input \"\$expect_out(0,string)\"; set ret [exec $fc \"\$user_input\"]; exit 1; } default { interact; }; }"

py-import-to-package Use Google to guess what the pypi package name is from its import.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
export TTY

( hs "$(basename "$0")" "$@" "#" "<==" "$(ps -o comm= $PPID)" 0</dev/null ) &>/dev/null

while [ $# -gt 0 ]; do opt="$1"; case "$opt" in
    "") { shift; }; ;;
    -u) {
        UPDATE=y
        shift
    }
    ;;

    *) break;
esac; done

export UPDATE

modulename="$@"

{
    gr python import $modulename
    gr pypi.org python import $modulename
} | grep -P "https://pypi.org/project/[a-z]" |
    sed 's=.*/project/\([^/]\+\)/\?=\1=' |
    uniqnosort | pavs

pip-install-from-error

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash
export TTY

error="$1"

library="$(p "$error" | sed "s/^.*No module named '\([^']*\)'.*/\\1/")"

# ModuleNotFoundError: No module named 'google.cloud'
library="$(py-import-to-package google.cloud | head -n 1)"
py -38 i "$library"

x – generate tcl/expect with bash

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
#!/bin/bash

aqf() { aqf-real "$@"; }
cmd() { cmd-nice "$@"; }

: ${TTY:="$(tm-tty)"}
export TTY

( hs "$(basename "$0")" "$@" "#" "<==" "$(ps -o comm= $PPID)" 0</dev/null ) &>/dev/null

# Consider using this
# man expect-lite

# Related: scripts using x
# $HOME/scripts/xs

stdin_exists() {
    ! [ -t 0 ]
}

if stdin_exists; then
    tfstdin="$(tf txt)"
    exec <`tm-tty`
fi

# example 1: this adds and starts a git commit message
# x -m "\`" -m t -m e -m v -i

PANE_ID="$(tmux display-message -p -t $TMUX_PANE '#{pane_id}' 2>/dev/null)"
WIN_ID="$(tmux display-message -p -t $TMUX_PANE '#{window_id}' 2>/dev/null)"

SHELL=zsh

input_filter() {
    # I don't want to escape \n
    sed 's/\([[`;$"]\)/\\\1/g'

    # qne
    # cat
    return 0
}

# -tmc is evil.

# Examples
# x -nto -e ยป -s "pti3\n" -e "In" -s "%matplotlib tk\n" -i
# x -nto -sh "pti3" -e "In [" -scc c -s yo -scc m -i
# x -tmc pti3 -nto -e "In [" -scc c -s yo -scc m -i
# x -h -d -tmc pti3 -nto -e "In [" -scc c -s "%matplotlib tk\n" -scc m -e "In [" -i
# x -h -d -tmc pti3 -nto -e "In [" -scc c -s "%matplotlib tk\n" -scc m -e "In [" -a
# x -d -tmc htop -e running -a

export TMUX=

tf_script="$(ux tf script exp | ds xlast 2>/dev/null || echo /dev/null)"
chmod a+x "$tf_script"

script_append_nonliteral() {
    printf -- "$1\n" >> "$tf_script"

    return 0
}


script_append() {
    # printf -- "$1" >> "$tf_script"
    # echo -e "$1" >> "$tf_script"

    lit "$1" >> "$tf_script"

    return 0
}

script_append "#!/usr/bin/expect -f"
# script_append "#!/home/shane/scripts/tm-expect -f"

timeout=3600
uses_tmux=n
debug_mode=n
tmux_command=
attach_tmux=n
print_output=n
# respawn_outer=n
while [ $# -gt 0 ]; do opt="$1"; case "$opt" in
    -d) {
        debug_mode=y
        shift
    }
    ;;

    -ub) {
        do_unbuffer=y
        do_ansi2txt=y
        shift
    }
    ;;

    -D) {
        debug_mode=n
        shift
    }
    ;;

    -vt|-vt100) {
        export TERM=vt100
        shift
    }
    ;;

    -xt) {
        export TERM=xterm
        shift
    }
    ;;

    -n|-g|-dr) { #gen
        DRY_RUN=y
        shift
    }
    ;;

    # SHELL is what is used for spawn. Therefore, it can't be an
    # arbitrary script. It must be a shell.
    -shell) {
        SHELL="$2"
        shift
        shift
    }
    ;;

    -shE|-sh|-is) {
        INIT_SPAWN="$2"
        shift
        shift
    }
    ;;

    -sh-) {
        shift

        # save args
        args=("$@")

        eval "set -- $(cmd "$@" | sed -e "s/^-- .*//"  -e "s/ -- .*//" -e "s/ --$//")"
        command_terms=("$@")
        INIT_SPAWN="$(cmd "$@")"

        # restore args
        set -- "${args[@]}"

        eval "set -- $(cmd "$@" | sed -e "s/.*-- //")"

        # cmd "$@"
        # echo "$#"
        # exit 0

        # INIT_SPAWN="$2"
        # shift
    }
    ;;

    -cd ) {
        cd "$2"
        export CWD="$1"
        shift
        shift
    }
    ;;

    -h) { # hide output until interactive
        script_append "log_user 0"
        # script_append "stty -echo"
        shift
    }
    ;;

    # This attaches the given window to a hidden tmux session
    -tma) {
        uses_tmux=y
        target="$2"
        shift
        if [ -z "$target" ]; then
            echo "No tmux target given."
            exit 1
        fi

        # Now I can tab away from it without the auto resizing not screwing
        # things up
        x="$(tmux display-message -p -t "$target" '#{window_width}')"
        y="$(tmux display-message -p -t "$target" '#{window_height}')"
        y="$(( y + 1 ))"
        : ${x:="2000"}
        : ${y:="1000"}

        tmux_attached_init=y
        script_append "log_user 0"
        shift
    }
    ;;

    # automate the current window!
    -tmw) {
        uses_tmux=y
        tmux_session="$(tm-new-hidden-link-window "$WIN_ID")"
        tmux_session_qne="$(p "$tmux_session" | input_filter)"
        tmux_attached_init=y
        shift
    }
    ;;

    -tm) {
        uses_tmux=y
        if [ -z "$PANE_ID" ]; then
            echo "No tmux pane. Can't swap pane so not trying."
            exit 1
        fi
        tmux_session="$(TMUX= tmux new -F "#{session_id}" -P -d)"
        tmux_session_qne="$(p "$tmux_session" | input_filter)"
        shift
    }
    ;;

    # This is evil. Maybe I should remove it.
    -tmc) {
        uses_tmux=y
        tmux_session="$(TMUX= tmux new -F "#{session_id}" -P -d)"
        tmux_session_qne="$(p "$tmux_session" | input_filter)"
        tmux_command="$2"
        shift
        shift
    }
    ;;

    -to) {
        timeout="$2"
        shift
        shift
    }
    ;;

    -nto|-notimeout) { # No timeout
        timeout=-1
        shift
    }
    ;;

    -zsh) {
        SHELL="zsh"
        shift
    }
    ;;

    *) break;
esac; done

if ! test "$debug_mode" = "y"; then
    exec 2>/dev/null
fi

# I should design this script first to use tmux

# The final expect script:
# script=""

read -r -d '' expect_script <<'HEREDOC'

#trap sigwinch and pass it to the child we spawned
trap {
    set rows [stty rows]
    set cols [stty columns]
    stty rows $rows columns $cols < $spawn_out(slave,name)
} WINCH

proc getctrl {char} {
    set ctrl [expr ("$char" & 01xF)]
    return $ctrl
}

set force_conservative 0
if {$force_conservative} {
    set send_slow {1 .1}
    proc send {ignore arg} {
        sleep .1
        exp_send -s -- $arg
    }
}

# For send -h
set send_human {.4 .4 .2 .5 100}
HEREDOC
script_append "$expect_script"

read -r -d '' expect_script <<HEREDOC
set ::env(PATH) "$PATH"
# This is not what you want.
# set ::env(TTY) "$TTY"
# I must set the TTY to expect's TTY
# set ::env(TTY) "$TTY"
# puts "$::env(TTY)"
unset ::env(TTY)
HEREDOC
script_append "$expect_script"

read -r -d '' expect_script <<'HEREDOC'
set timeout -1
match_max 100000
HEREDOC
script_append "$expect_script"

# script_append "set SHELL \"\$env(SHELL)\""
script_append "set SHELL $(aqf "$SHELL")"
# script_append "spawn -noecho \"\$env(SHELL)\""

# Shell must always be a real shell
# Because it's used to spawn things.
if test -z "$INIT_SPAWN"; then
    INIT_SPAWN="$SHELL"
    # So we don't have zsh starting zsh
    SHELL=sh
fi

is_stdout_pipe() {
    # If stout is a pipe
    ! test "$do_unbuffer" = "y" && [[ -p /dev/stdout ]]
}

script_append "log_user 0"
if test "$uses_tmux" = "y"; then
    # sleep
    # tmux ls > /tmp/tms.txt
    if test "$tmux_attached_init" = y; then
        # If I put this inside the expect script then how can I get this value back out?
        # Do I need it? No I don't!
        #tmux_session="$(tm-new-hidden-link-window "$target")"
        #tmux_session_qne="$(p "$tmux_session" | input_filter)"
        #script_append "spawn \"tmux\" \"attach\" \"-t\" \"$tmux_session_qne\""

        script_append "set win [exec tm-new-hidden-link-window \"$target\"]"
        script_append "spawn \"tmux\" \"attach\" \"-t\" \"\$win\""
        script_append "sleep 0.1"
    elif [ -n "$tmux_command" ]; then
            # this does what it's supposed to. the session ID is correct but
            # it must not be ready. if i call without the target, it
            # works though. how annoying.

            #script_append "spawn \"tmux\" \"respawn-pane\" \"-t\" \"${tmux_session_qne}:1.0\" \"-k\" \"$tmux_command\" \"\\;\" \"attach\" \"-t\" \"$tmux_session_qne\""

            # TODO For the moment, don't use the target. This is dodgy, I
            # know. Hmm, it's still not working.
            # script_append "spawn \"tmux\" \"respawn-pane\" \"-k\" \"$tmux_command\" \"\\;\" \"attach\" \"-t\" \"$tmux_session_qne\""

            # script_append "spawn \"tmux\" \"respawn-pane\" \"-k\" \"$tmux_command\""
        # It might be slightly more stable with the sleep here.
        script_append "sleep 0.2"
        # Write tmux explicitly instead of $SHELL
        # This way I can run the script after printing it to stdout

        # if test "$respawn_outer" = "y"; then
        script_append "spawn \"tmux\" \"respawn-pane\" \"-t\" \"$tmux_session_qne\" \"-k\" $(aqf "$tmux_command" | bs '][')"
        # fi

        # script_append "sleep 0.5"
        # Separating the 2 commands appears to make it a little more
        # stable.
        # Using \"\$SHELL\" instead of tmux appears to make no
        # difference here
        script_append "spawn \"tmux\" \"attach\" \"-t\" \"$tmux_session_qne\""

            # script_append "spawn \"tmux\" \"respawn-pane\" \"-k\" \"$tmux_command\" \"\\;\" \"attach\" \"-t\" \"$tmux_session_qne\""
            # script_append "expect -exact \"sh\""
    else
        script_append "spawn \"tmux\" \"attach\" \"-t\" \"$tmux_session_qne\""
        script_append "expect -exact \"sh\""
    fi
elif test "$INIT_SPAWN" = "zsh"; then
    # script_append "spawn \"\$env(SHELL)\""
    script_append "spawn $(aqf "$INIT_SPAWN")"
    script_append "expect -exact \"ยป\""
else
    if test -n "$tfstdin" && test -n "$INIT_SPAWN"; then
        # INIT_SPAWN="$(nsfa -E "cat $tfstdin | $INIT_SPAWN")"
        INIT_SPAWN="cat $tfstdin | $INIT_SPAWN"
    fi

    if is_stdout_pipe; then
        tfstdout="$(odn tf txt)"
        # INIT_SPAWN="$(nsfa -E "cat $tfstdin | $INIT_SPAWN")"
        INIT_SPAWN="$INIT_SPAWN > $tfstdout"
    fi

    INIT_SPAWN="$(nsfa -E "$INIT_SPAWN")"

    # script_append "spawn \"\$SHELL\""
    # This is required if I want to spawn this way:
    # x -cd "$(pwd)" -sh "racket -iI racket" -e ">" -i
    script_append "spawn $(aqf "$INIT_SPAWN")"

    # script_append "expect -exact \"\r\""
fi
script_append "log_user 1"

while [ $# -gt 0 ]; do opt="$1"; case "$opt" in
    -e) { # Expect something
        input="$(p "$2" | input_filter)"

        script_append "expect -exact \"$input\""
        shift
        shift
    }
    ;;

    -z) { # Expect something fuzzy
        input="$(p "$2" | fuzzify-regex | input_filter)"

        script_append "expect -re \"$input\""
        shift
        shift
    }
    ;;

    -raw|-w) {
        # script_append "$2"
        # I want to be able to make newlines
        script_append_nonliteral "$2"
        shift
        shift
    }
    ;;

    # Not sure if this works
    -r) { # Expect a pattern / regex
        input="$(p "$2" | input_filter)"
        # input="$2"

        script_append "expect -re \"$input\""
        shift
        shift
    }
    ;;

    -u) { # Expect user input
        input="$(p "$2" | input_filter)"

        script_append "expect_user -timeout $timeout \"$input\";"
        script_append "set user_input \"\$expect_out(0,string)\""
        script_append "send -- \"\$user_input\\r\""
        shift
        shift
    }
    ;;

    -ur) { # Expect user input matching regex
        input="$(p "$2" | input_filter)"

        # example:
        # -ur "(.*)\[\r\n]"
        # x -nto -e ยป -s "vim\n" -ur "(.*hi.*)" -i

        # script_append "send -- {getctrl {l}}"
        script_append "expect_user -timeout $timeout -re \"$input\";"
        script_append "set user_input \"\$expect_out(1,string)\"" # 1 must be capture group 1. 0 is entire string
        script_append "send -- \"\$user_input\\r\""
        shift
        shift
    }
    ;;

    -p) { # Expect user input password
        input="$(p "$2" | input_filter)"

        script_append "stty -echo"
        script_append "expect_user -timeout $timeout \"$input\""
        script_append "set user_input \"\$expect_out(1,string)\"" # 1 must be capture group 1. 0 is entire string
        script_append "send -- \"\$user_input\\r\""
        script_append "stty echo"
        shift
        shift
    }
    ;;

    # vim +/"\" F1" "$VIMCONFIG/fixkeymaps-vimrc"
    -f1) {
        script_append "send -- \\033OP"
        shift
    }
    ;;

    -f2) {
        script_append "send -- \\033OQ"
        shift
    }
    ;;

    -f3) {
        script_append "send -- \\033OR"
        shift
    }
    ;;

    -f4) {
        # send -- "OS"
        script_append "send -- \\033OS"
        shift
    }
    ;;

    -pr) { # Expect user input password matching regex
        # input="$(p "$2" | input_filter)"

        input="$2"

        # example:
        # -ur "(.*)\[\r\n]"

        script_append "stty -echo"
        script_append "expect_user -timeout $timeout -re \"$input\""
        script_append "set user_input \"\$expect_out(1,string)\"" # 1 must be capture group 1. 0 is entire string
        script_append "send -- \"\$user_input\\r\""
        script_append "stty echo"
        shift
        shift
    }
    ;;

    # For some reason this doesn't work with C-g
    -c|-scc) { # Send control character
        if test "$2" = "g"; then
            echo "C-g breaks x" 1>&2
        fi

        printf -- "%s" "$2" | grep -o . | awk 1 | while IFS=$'\n' read -r char; do
            (
            exec 0</dev/null
            script_append "send -- $(cchar $char)"
            )
        done

        # script_append "send {getctrl {$2}}"

        shift
        shift
    }
    ;;

    -0|-l0|-off) {
        script_append "log_user 0"
        shift
    }
    ;;

    -1|-l1|-on) {
        script_append "log_user 1"
        shift
    }
    ;;

    -m) { # Send meta
        char="$(p "$2" | input_filter)"
        script_append "send -- \\033$char"
        shift
        shift
    }
    ;;

    -cm) { # Send control-meta
        script_append "send -- \\033$(cchar $2)"
        shift
        shift
    }
    ;;

    -sec) { # Send escape char
        script_append "send -- \\033$2"
        shift
        shift
    }
    ;;

    -esc) { # Send escape char
        script_append "send -- \\033"
        shift
    }
    ;;

    -sl) {
        script_append "sleep $2"
        shift
        shift
    }
    ;;

    -s.2) {
        script_append "sleep 0.2"
        shift
    }
    ;;

    -s1) {
        script_append "sleep 1"
        shift
    }
    ;;

    -sf|-send-file) { # Send contents of file
        input_fp="$2"
        # The bs have to be separated
        input_fp="$(printf -- "%s" "$input_fp" | bs "\\" | bs "[" | bs "]")"

        ## tcl
        ## set somevar [ exec cat "/home/shane/source/git/woodrush/py2hy/src/py2hy/py2hy.hy" ]

        script_append "set fp [ exec cat $(aqfd "$input_fp") ]"
        script_append "send -- \$fp"
        shift
        shift
    }
    ;;

    -se) { # Send a string and expect a change for each letter
        input="$2"
        printf -- "%s" "$input" | grep -o . | while IFS=$'\n' read -r char; do
            char="$(p "$char" | bs "\\" | bs "[" | bs "]")"
            script_append "send -- $(aqfd "$char")"
            script_append "expect \".\""
            script_append "sleep 0.2"
        done
        shift
        shift
    }
    ;;

    # -send can't really handle shell commands well.
    # For example, if you use z-repl and you send a $ it will not escape
    # it. If you send an escape then the escape will be escaped.
    # A workaround is to use -send-file.
    -s|-send) { # Send something
        # input="$(p "$2" | input_filter)"

        input="$2"

        # The bs have to be separated. But don't escape a lone '\'
        if test "$input" = "\\"; then
            script_append "send -- \"\\\\\""
        else
            input="$(printf -- "%s" "$input" | bs "\\" | bs "[" | bs "]")"
            script_append "send -- $(aqfd "$input")"
        fi

        shift
        shift
    }
    ;;

    -see) { # Send and expect to see what was sent (slightly more reliable)
        input="$2"
        # The bs have to be separated
        input="$(printf -- "%s" "$input" | bs "\\" | bs "[" | bs "]")"

        script_append "send -- $(aqfd "$input")"
        script_append "expect -exact $(aqfd "$input")"
        shift
        shift
    }
    ;;

    # Frustratingly, can't work out why this doesn't work
    -ss|-send-slow) { # Send something
        # input="$(p "$2" | input_filter)"

        input="$2"
        # The bs have to be separated
        input="$(printf -- "%s" "$input" | bs "\\" | bs "[" | bs "]")"

        # v +/"send_slow" "$NOTES/ws/playgrounds/tcl/remember.org"

        script_append "set send_slow {1 0.1}"
        script_append "send -s $(aqfd "$input")"
        script_append "set send_slow {1 0}"
        shift
        shift
    }
    ;;

    -i) {
        if test "$uses_tmux" = "y"; then
            # This sleep appears to help the script catch the final
            # expect statement
            script_append "sleep 0.2"
            script_append "exit"
        else
            script_append "interact"
        fi
        shift
    }
    ;;

    -o) {
        if test "$uses_tmux" = "y"; then
            attach_tmux=n
            print_output=y
            # This sleep appears to help the script catch the final
            # expect statement
            script_append "sleep 0.2"
            script_append "exit"
        else
            script_append "interact"
        fi
        shift
    }
    ;;

    -a) {
        if test "$uses_tmux" = "y"; then
            attach_tmux=y
            print_output=n
            # This sleep appears to help the script catch the final
            # expect statement
            script_append "sleep 0.2"
            script_append "exit"
        else
            script_append "interact"
        fi
        shift
    }
    ;;

    -fc) {
        # Set some expect options

        script_append "set force_conservative 0"
        shift
    }
    ;;

    -ts) {
        # tm n "$opt :: NOT IMPLEMENTED"
        # Tmux-Send something

        input="$(p "$2" | input_filter)"
        script_append "spawn \"tmux\" \"send\" \"-t\" \"${tmux_session_qne}\" \"$input\""

        # script_append "$2"
        shift
        shift
    }
    ;;

    -tsl) {
        # tm n "$opt :: NOT IMPLEMENTED"
        # Tmux-Send something

        input="$(p "$2" | input_filter)"
        script_append "spawn \"tmux\" \"send\" \"-t\" \"${tmux_session_qne}\" -l \"$input\""

        # script_append "$2"
        shift
        shift
    }
    ;;

    -tssl) {
        # tm n "$opt :: NOT IMPLEMENTED"
        # Tmux-Send something

        input="$(p "$2" | input_filter)"
        script_append "spawn \"tm\" \"type\" \"$input\""

        # script_append "$2"
        shift
        shift
    }
    ;;

    *) break;
esac; done

if test "$tmux_attached_init" = y; then
    read -r -d '' expect_script <<'HEREDOC'
exec tmux kill-session -t $win
sleep 0.2
close
HEREDOC
else
    read -r -d '' expect_script <<'HEREDOC'
if {[catch {
        expect eof
        close
    } issue]} {
    # puts "There is a failure and it is ignored"
    # puts "Reason for failure : $issue"
}
HEREDOC
fi

script_append "$expect_script"

printf -- "%s" "$script" >> "$tf_script"

export SHELL

# Needed for recterm
export WINDOWID

expect_cmd_run() {
    ret=0
    if test "$do_unbuffer" = "y"; then
        unbuffer expect "$@"
        ret="$?"
    else
        # If x is being piped into something, ensure we can use the TTY for
        # now.
        exec 3>&1
        exec 4>&2
        exec 1>"$TTY"
        exec 2>"$TTY"

        expect "$@"
        ret="$?"

        exec 1>&3
        exec 2>&4
    fi
    exit "$ret"
}

unansiify() {
    if test "$do_ansi2txt" = "y"; then
        "$@" | ansi2txt
    else
        "$@"
    fi
}

ret=0

if test "$DRY_RUN" = "y"; then
    cat "$tf_script"
else

    if test "$tmux_attached_init" = y; then
        (
        stty cols $x
        stty rows $y
        LINES=$y COLUMNS=$x unansiify expect_cmd_run -f "$tf_script"
        )
        # inbigtty expect -f "$tf_script"
        # expect_cmd_run -f "$tf_script"
    elif test "$print_output" = "y"; then
        unansiify expect_cmd_run -f "$tf_script" &>/dev/null
    else
        unansiify expect_cmd_run -f "$tf_script"
    fi
    ret="$?"
fi

if test -n "$tfstdout"; then
    cat "$tfstdout"
fi

# The session must be guaranteed to exist before attaching.
# This is risky

# sleep 1

if ! test "$DRY_RUN" = "y"; then
    if test "$tmux_attached_init" = y; then
        echo "$tmux_session" > /tmp/xx.txt
        test -n "$tmux_session" && tmux kill-session -t "$tmux_session"
    elif test "$attach_tmux" = "y"; then
        tmux attach -t "$tmux_session"
    elif test "$print_output" = "y"; then
        tm catp "$tmux_session"
        # cmd tm catp "$tmux_session"
        tmux kill-session -t "$tmux_session"
    elif test "$uses_tmux" = "y"; then
        tmux swap-pane -s "$tmux_session:1.0" -t "$PANE_ID" \; kill-session -t "$tmux_session"
    fi
fi

if ! test "$debug_mode" = "y"; then
    :
    # trap "rm \"$tf_script\" 2>/dev/null" 0
else
    echo
    echo "$tf_script" 1>&2
fi

exit "$ret"