@@ -70,17 +70,40 @@ public function handleBuffer()
7070
7171 public function write ($ data )
7272 {
73- // clear readline prompt in order to overwrite with data
74- $ this ->readline ->clear ();
73+ if ((string )$ data === '' ) {
74+ return ;
75+ }
76+
77+ $ out = $ data ;
78+
79+ $ lastNewline = strrpos ($ data , "\n" );
80+
81+ $ restoreReadline = false ;
7582
76- // move one line up if the last write did not end with a newline
7783 if ($ this ->incompleteLine !== '' ) {
78- $ this ->output ->write ("\033[A " );
79- $ this ->output ->write ("\r\033[ " . $ this ->width ($ this ->incompleteLine ) . "C " );
80- }
84+ // the last write did not end with a newline => append to existing row
8185
82- // write actual data
83- $ this ->output ->write ($ data );
86+ // move one line up and move cursor to last position before writing data
87+ $ out = "\033[A " . "\r\033[ " . $ this ->width ($ this ->incompleteLine ) . "C " . $ out ;
88+
89+ // data contains a newline, so this will overwrite the readline prompt
90+ if ($ lastNewline !== false ) {
91+ // move cursor to beginning of readline prompt and clear line
92+ // clearing is important because $data may not overwrite the whole line
93+ $ out = "\r\033[K " . $ out ;
94+
95+ // make sure to restore readline after this output
96+ $ restoreReadline = true ;
97+ }
98+ } else {
99+ // here, we're writing to a new line => overwrite readline prompt
100+
101+ // move cursor to beginning of readline prompt and clear line
102+ $ out = "\r\033[K " . $ out ;
103+
104+ // we always overwrite the readline prompt, so restore it on next line
105+ $ restoreReadline = true ;
106+ }
84107
85108 // following write will have have to append to this line if it does not end with a newline
86109 $ endsWithNewline = substr ($ data , -1 ) === "\n" ;
@@ -90,9 +113,7 @@ public function write($data)
90113 $ this ->incompleteLine = '' ;
91114 } else {
92115 // always end data with newline in order to append readline on next line
93- $ this ->output ->write ("\n" );
94-
95- $ lastNewline = strrpos ($ data , "\n" );
116+ $ out .= "\n" ;
96117
97118 if ($ lastNewline === false ) {
98119 // contains no newline at all, everything is incomplete
@@ -103,8 +124,21 @@ public function write($data)
103124 }
104125 }
105126
106- // restore original readline prompt and line buffer
107- $ this ->readline ->redraw ();
127+ if ($ restoreReadline ) {
128+ // write output and restore original readline prompt and line buffer
129+ $ this ->output ->write ($ out );
130+ $ this ->readline ->redraw ();
131+ } else {
132+ // restore original cursor position in readline prompt
133+ $ pos = $ this ->width ($ this ->readline ->getPrompt ()) + $ this ->readline ->getCursorCell ();
134+ if ($ pos !== 0 ) {
135+ // we always start at beginning of line, move right by X
136+ $ out .= "\033[ " . $ pos . "C " ;
137+ }
138+
139+ // write to actual output stream
140+ $ this ->output ->write ($ out );
141+ }
108142 }
109143
110144 public function writeln ($ line )
0 commit comments