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,46 @@ 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
+ $ lineLength = Helper::strlenWithoutDecoration ($ this ->getFormatter (), $ lineContent );
83
+ // calculates to how many lines does the line wrap to
84
+ $ this ->lines += $ lineLength ? ceil ($ lineLength / $ this ->terminal ->getWidth ()) : 1 ;
90
85
}
91
86
92
- $ this ->calculateLines ($ message , $ newline );
93
-
94
- parent ::doWrite ($ message , $ newline );
87
+ $ this ->content .= $ message .PHP_EOL ;
95
88
96
- $ this ->printOutput ();
89
+ parent ::doWrite ($ message , true );
90
+ parent ::doWrite ($ erasedContent , false );
97
91
}
98
92
99
- private function calculateLines ($ messages , $ newLine )
93
+ /**
94
+ * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits
95
+ * current section. Then it erases content it crawled through. Optionally, it erases part of current section too.
96
+ *
97
+ * @param int $numberOfLinesToClearFromCurrentSection
98
+ * @return string
99
+ */
100
+ private function popStreamContentUntilCurrentSection ($ numberOfLinesToClearFromCurrentSection = 0 )
100
101
{
101
- $ total = 0 ;
102
+ $ numberOfLinesToClear = $ numberOfLinesToClearFromCurrentSection ;
103
+ $ erasedContent = [];
102
104
103
- $ prevLines = explode ("\n" , $ messages );
105
+ foreach ($ this ->sections as $ section ) {
106
+ if ($ section === $ this ) {
107
+ break ;
108
+ }
104
109
105
- for ( $ i = 0 ; $ i < count ( $ prevLines ); ++ $ i ) {
106
- $ total += ceil (Helper:: strlen ( $ prevLines [ $ i ]) / $ this -> terminal -> getWidth ()) ?: 1 ;
110
+ $ numberOfLinesToClear += $ section -> lines ;
111
+ $ erasedContent [] = $ section -> content ;
107
112
}
108
113
109
- $ this ->lines += $ total ;
110
- $ this ->content .= $ messages ;
111
-
112
- if ($ newLine ) {
113
- $ this ->content .= "\n" ;
114
+ if ($ numberOfLinesToClear > 0 ) {
115
+ // Move cursor up n lines and erase to end of screen
116
+ parent ::doWrite (sprintf ("\033[%dA \033[0J " , $ numberOfLinesToClear ), false );
114
117
}
115
118
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
- }
119
+ return implode ('' , array_reverse ($ erasedContent ));
136
120
}
137
121
}
0 commit comments