@@ -104,12 +104,38 @@ func (b *ShellExecutable) VTBellChannel() chan bool {
104
104
func (b * ShellExecutable ) ReadUntilConditionOrTimeout (condition func () bool , timeout time.Duration ) error {
105
105
err := b .ptyReader .ReadUntilConditionOrTimeout (condition , timeout )
106
106
if err != nil {
107
- return wrapReaderError (err )
108
- }
107
+ // First log any remaining output
108
+ state := b .vt .GetScreenState ()
109
+ for _ , row := range state {
110
+ output := virtual_terminal .BuildCleanedRow (row )
111
+ if len (output ) > 0 {
112
+ b .programLogger .Plainln (output )
113
+ }
114
+ }
109
115
116
+ // Then return error message
117
+ if errors .Is (err , io .EOF ) || errors .Is (err , syscall .EIO ) {
118
+ return ErrProgramExited
119
+ }
120
+ if errors .Is (err , condition_reader .ErrConditionNotMet ) {
121
+ return fmt .Errorf ("the 'exit' command should terminate your shell, but your shell is still running" )
122
+ }
123
+ return err
124
+ }
110
125
return nil
111
126
}
112
127
128
+ func (b * ShellExecutable ) LogRemainingOutput () {
129
+ // Get any remaining output from the virtual terminal
130
+ state := b .vt .GetScreenState ()
131
+ for _ , row := range state {
132
+ output := virtual_terminal .BuildCleanedRow (row )
133
+ if len (output ) > 0 {
134
+ b .LogOutput ([]byte (output ))
135
+ }
136
+ }
137
+ }
138
+
113
139
func (b * ShellExecutable ) SendCommand (command string ) error {
114
140
if err := b .SendCommandRaw (command + "\n " ); err != nil {
115
141
return err
0 commit comments