@@ -2,7 +2,6 @@ package termtest
22
33import (
44 "bufio"
5- "bytes"
65 "errors"
76 "fmt"
87 "io"
@@ -66,13 +65,15 @@ func (o *outputProducer) listen(r io.Reader, w io.Writer, appendBuffer func([]by
6665var PtyEOF = errors .New ("pty closed" )
6766
6867func (o * outputProducer ) processNextRead (r io.Reader , w io.Writer , appendBuffer func ([]byte , bool ) error , size int ) error {
68+ isEOF := false
6969 o .opts .Logger .Printf ("processNextRead started with size: %d\n " , size )
70- defer o .opts .Logger .Println ("processNextRead stopped" )
70+ defer func () {
71+ o .opts .Logger .Printf ("processNextRead stopped, isEOF: %v\n " , isEOF )
72+ }()
7173
7274 snapshot := make ([]byte , size )
7375 n , errRead := r .Read (snapshot )
7476
75- isEOF := false
7677 if errRead != nil {
7778 pathError := & fs.PathError {}
7879 if errors .Is (errRead , fs .ErrClosed ) || errors .Is (errRead , io .EOF ) || (runtime .GOOS == "linux" && errors .As (errRead , & pathError )) {
@@ -116,13 +117,13 @@ func (o *outputProducer) appendBuffer(value []byte, isFinal bool) error {
116117
117118 // Clean output
118119 var err error
119- o .output , o .cursorPos , o .cleanUptoPos , err = o .processDirtyOutput (output , o .cursorPos , o .cleanUptoPos , isFinal , func (output []byte , cursorPos int ) ([]byte , int , error ) {
120+ o .output , o .cursorPos , o .cleanUptoPos , err = o .processDirtyOutput (output , o .cursorPos , o .cleanUptoPos , isFinal , func (output []byte , cursorPos int ) ([]byte , int , int , error ) {
120121 var err error
121- output , cursorPos = cleanPtySnapshot (output , cursorPos , o .opts .Posix )
122+ output , cursorPos , cleanCursorPos : = cleanPtySnapshot (output , cursorPos , o .opts .Posix )
122123 if o .opts .OutputSanitizer != nil {
123- output , cursorPos , err = o .opts .OutputSanitizer (output , cursorPos )
124+ output , cursorPos , cleanCursorPos , err = o .opts .OutputSanitizer (output , cursorPos )
124125 }
125- return output , cursorPos , err
126+ return output , cursorPos , cleanCursorPos , err
126127 })
127128 if err != nil {
128129 return fmt .Errorf ("cleaning output failed: %w" , err )
@@ -138,48 +139,36 @@ func (o *outputProducer) appendBuffer(value []byte, isFinal bool) error {
138139 return nil
139140}
140141
141- type cleanerFunc func ([]byte , int ) ([]byte , int , error )
142+ type cleanerFunc func (snapshot []byte , cursorPos int ) (newSnapshot []byte , newCursorPos int , cleanUptoPos int , err error )
142143
143144// processDirtyOutput will sanitize the output received, but we have to be careful not to clean output that hasn't fully arrived
144145// For example we may be inside an escape sequence and the escape sequence hasn't finished
145146// So instead we only process new output up to the most recent line break
146147// In order for this to work properly the invoker must ensure the output and cleanUptoPos are consistent with each other.
147148func (o * outputProducer ) processDirtyOutput (output []byte , cursorPos int , cleanUptoPos int , isFinal bool , cleaner cleanerFunc ) (_output []byte , _cursorPos int , _cleanUptoPos int , _err error ) {
148149 defer func () {
149- o .opts .Logger .Printf ("Cleaned output from %d to %d\n " , cleanUptoPos , _cleanUptoPos )
150+ o .opts .Logger .Printf ("Cleaned output from %d to %d (isFinal: %v) \n " , cleanUptoPos , _cleanUptoPos , isFinal )
150151 }()
151152 alreadyCleanedOutput := copyBytes (output [:cleanUptoPos ])
152153 processedOutput := []byte {}
153154 unprocessedOutput := copyBytes (output [cleanUptoPos :])
154- processedCursorPos := cursorPos - len (alreadyCleanedOutput )
155-
156- if isFinal {
157- // If we've reached the end there's no point looking for the most recent line break as there's no guarantee the
158- // output will be terminated by a newline.
159- processedOutput = copyBytes (unprocessedOutput )
160- unprocessedOutput = []byte {}
161- } else {
162- // Find the most recent line break, and only clean until that point.
163- // Any output after the most recent line break is considered not ready for cleaning as cleaning depends on
164- // multiple consecutive characters.
165- lineSepN := bytes .LastIndex (unprocessedOutput , []byte ("\n " ))
166- if lineSepN != - 1 {
167- processedOutput = copyBytes (unprocessedOutput [0 : lineSepN + 1 ])
168- unprocessedOutput = unprocessedOutput [lineSepN + 1 :]
169- }
170- }
155+ relativeCursorPos := cursorPos - len (alreadyCleanedOutput )
171156
172157 // Invoke the cleaner now that we have output that can be cleaned
173- if len (processedOutput ) > 0 {
158+ newCleanUptoPos := cleanUptoPos
159+ if len (unprocessedOutput ) > 0 {
174160 var err error
175- processedOutput , processedCursorPos , err = cleaner (processedOutput , processedCursorPos )
161+ var processedCleanUptoPos int
162+ processedOutput , relativeCursorPos , processedCleanUptoPos , err = cleaner (unprocessedOutput , relativeCursorPos )
176163 if err != nil {
177- return processedOutput , processedCursorPos , cleanUptoPos , fmt .Errorf ("cleaner failed: %w" , err )
164+ return processedOutput , relativeCursorPos , processedCleanUptoPos , fmt .Errorf ("cleaner failed: %w" , err )
178165 }
166+ // Keep a record of what point we're up to
167+ newCleanUptoPos += processedCleanUptoPos
179168 }
180169
181170 // Convert cursor position back to absolute
182- processedCursorPos += len (alreadyCleanedOutput )
171+ processedCursorPos := relativeCursorPos + len (alreadyCleanedOutput )
183172
184173 if processedCursorPos < 0 {
185174 // Because the cleaner function needs to support a negative cursor position it is impossible for the cleaner
@@ -188,11 +177,8 @@ func (o *outputProducer) processDirtyOutput(output []byte, cursorPos int, cleanU
188177 processedCursorPos = 0
189178 }
190179
191- // Keep a record of what point we're up to
192- newCleanUptoPos := cleanUptoPos + len (processedOutput )
193-
194180 // Stitch everything back together
195- return append (append ( alreadyCleanedOutput , processedOutput ... ), unprocessedOutput ... ), processedCursorPos , newCleanUptoPos , nil
181+ return append (alreadyCleanedOutput , processedOutput ... ), processedCursorPos , newCleanUptoPos , nil
196182}
197183
198184func (o * outputProducer ) closeConsumers (reason error ) {
0 commit comments