17
17
18
18
/**
19
19
* @author Pierre du Plessis <pdples@gmail.com>
20
+ * @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com>
20
21
*/
21
22
class ConsoleSectionOutput extends StreamOutput
22
23
{
23
- public $ content ;
24
+ public $ content = '' ;
24
25
public $ lines = 0 ;
25
26
26
- private $ sectionReference ;
27
+ private $ sections ;
27
28
private $ terminal ;
28
29
29
- public function __construct ($ stream , OutputSectionReference $ sectionReference , $ verbosity , $ decorated , OutputFormatterInterface $ formatter )
30
+ public function __construct ($ stream , array & $ sections , $ verbosity , $ decorated , OutputFormatterInterface $ formatter )
30
31
{
31
32
parent ::__construct ($ stream , $ verbosity , $ decorated , $ formatter );
32
- $ this -> sectionReference = $ sectionReference ;
33
- $ this ->sectionReference -> addRef ( $ this ) ;
33
+ array_unshift ( $ sections , $ this ) ;
34
+ $ this ->sections = & $ sections ;
34
35
$ this ->terminal = new Terminal ();
35
36
}
36
37
@@ -45,20 +46,14 @@ public function clear($lines = null)
45
46
return ;
46
47
}
47
48
48
- $ number = $ lines ?: $ this ->lines ;
49
-
50
- $ buffer = $ this ->sectionReference ->calculateBuffer ($ this );
51
- $ buffer += $ number ;
49
+ if (!$ lines ) {
50
+ $ lines = $ this ->lines ;
51
+ }
52
52
53
53
$ this ->content = '' ;
54
- $ this ->lines = $ this -> lines - $ number ;
54
+ $ this ->lines - = $ lines ;
55
55
56
- if ($ buffer > 0 ) {
57
- $ this ->moveUp ($ buffer );
58
- $ this ->clearOutput ();
59
- }
60
-
61
- $ this ->printOutput ();
56
+ parent ::doWrite ($ this ->popStreamContentUntilCurrentSection ($ lines ), false );
62
57
}
63
58
64
59
/**
@@ -81,57 +76,44 @@ protected function doWrite($message, $newline)
81
76
return parent ::doWrite ($ message , $ newline );
82
77
}
83
78
84
- $ newline = true ;
85
- $ buffer = $ this ->sectionReference ->calculateBuffer ($ this );
79
+ $ erasedContent = $ this ->popStreamContentUntilCurrentSection ();
86
80
87
- if ($ buffer > 0 ) {
88
- $ this ->moveUp ($ buffer );
89
- $ this ->clearOutput ();
81
+ foreach (explode (PHP_EOL , $ message ) as $ lineContent ) {
82
+ $ this ->lines += ceil (Helper::strlen ($ lineContent ) / $ this ->terminal ->getWidth ()) ?: 1 ;
90
83
}
91
84
92
- $ this ->calculateLines ($ message , $ newline );
93
-
94
- parent ::doWrite ($ message , $ newline );
85
+ $ this ->content .= $ message .PHP_EOL ;
95
86
96
- $ this ->printOutput ();
87
+ parent ::doWrite ($ message , true );
88
+ parent ::doWrite ($ erasedContent , false );
97
89
}
98
90
99
- private function calculateLines ($ messages , $ newLine )
91
+ /**
92
+ * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits
93
+ * current section. Then it erases content it crawled through. Optionally, it erases part of current section too.
94
+ *
95
+ * @param int $numberOfLinesToClearFromCurrentSection
96
+ * @return string
97
+ */
98
+ private function popStreamContentUntilCurrentSection ($ numberOfLinesToClearFromCurrentSection = 0 )
100
99
{
101
- $ total = 0 ;
100
+ $ numberOfLinesToClear = $ numberOfLinesToClearFromCurrentSection ;
101
+ $ erasedContent = [];
102
102
103
- $ prevLines = explode ("\n" , $ messages );
103
+ foreach ($ this ->sections as $ section ) {
104
+ if ($ section === $ this ) {
105
+ break ;
106
+ }
104
107
105
- for ( $ i = 0 ; $ i < count ( $ prevLines ); ++ $ i ) {
106
- $ total += ceil (Helper:: strlen ( $ prevLines [ $ i ]) / $ this -> terminal -> getWidth ()) ?: 1 ;
108
+ $ numberOfLinesToClear += $ section -> lines ;
109
+ $ erasedContent [] = $ section -> content ;
107
110
}
108
111
109
- $ this ->lines += $ total ;
110
- $ this ->content .= $ messages ;
111
-
112
- if ($ newLine ) {
113
- $ this ->content .= "\n" ;
112
+ if ($ numberOfLinesToClear > 0 ) {
113
+ // Move cursor up n lines and erase to end of screen
114
+ parent ::doWrite (sprintf ("\033[%dA \033[0J " , $ numberOfLinesToClear ), false );
114
115
}
115
116
116
- return $ total ;
117
- }
118
-
119
- private function moveUp ($ n )
120
- {
121
- parent ::doWrite (sprintf ("\033[%dA " , $ n ), false );
122
- }
123
-
124
- private function clearOutput ()
125
- {
126
- parent ::doWrite ("\033[0J " , false );
127
- }
128
-
129
- private function printOutput ()
130
- {
131
- $ output = $ this ->sectionReference ->getOutput ($ this );
132
-
133
- if (!empty ($ output )) {
134
- parent ::doWrite ($ output , false );
135
- }
117
+ return implode ('' , array_reverse ($ erasedContent ));
136
118
}
137
119
}
0 commit comments