Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita72f98a

Browse files
committed
[Console] Add sections with a maximum height
1 parentc1f53b5 commita72f98a

File tree

2 files changed

+103
-9
lines changed

2 files changed

+103
-9
lines changed

‎src/Symfony/Component/Console/Output/ConsoleSectionOutput.php‎

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class ConsoleSectionOutput extends StreamOutput
2525
privateint$lines =0;
2626
privatearray$sections;
2727
privateTerminal$terminal;
28+
privateint$maxHeight =0;
2829

2930
/**
3031
* @param resource $stream
@@ -38,6 +39,23 @@ public function __construct($stream, array &$sections, int $verbosity, bool $dec
3839
$this->terminal =newTerminal();
3940
}
4041

42+
/**
43+
* Defines a maximum number of lines for this section.
44+
*
45+
* When more lines are added, the section will automatically scroll to the
46+
* end (i.e. remove the first lines to comply with the max height).
47+
*/
48+
publicfunctionsetMaxHeight(int$maxHeight):void
49+
{
50+
// when changing max height, clear output of current section and redraw again with the new height
51+
$existingContent =$this->popStreamContentUntilCurrentSection($this->maxHeight ?min($this->maxHeight,$this->lines) :$this->lines);
52+
53+
$this->maxHeight =$maxHeight;
54+
55+
parent::doWrite($this->getVisibleContent(),false);
56+
parent::doWrite($existingContent,false);
57+
}
58+
4159
/**
4260
* Clears previous output for this section.
4361
*
@@ -58,7 +76,7 @@ public function clear(int $lines = null)
5876

5977
$this->lines -=$lines;
6078

61-
parent::doWrite($this->popStreamContentUntilCurrentSection($lines),false);
79+
parent::doWrite($this->popStreamContentUntilCurrentSection($this->maxHeight ?min($this->maxHeight,$lines) :$lines),false);
6280
}
6381

6482
/**
@@ -75,13 +93,23 @@ public function getContent(): string
7593
returnimplode('',$this->content);
7694
}
7795

96+
publicfunctiongetVisibleContent():string
97+
{
98+
if (0 ===$this->maxHeight) {
99+
return$this->getContent();
100+
}
101+
102+
returnimplode('',\array_slice($this->content, -$this->maxHeight));
103+
}
104+
78105
/**
79106
* @internal
80107
*/
81-
publicfunctionaddContent(string$input,bool$newline =true)
108+
publicfunctionaddContent(string$input,bool$newline =true):int
82109
{
83110
$width =$this->terminal->getWidth();
84111
$lines =explode(\PHP_EOL,$input);
112+
$linesAdded =0;
85113
$count =\count($lines) -1;
86114
foreach ($linesas$i =>$lineContent) {
87115
// re-add the line break (that has been removed in the above `explode()` for
@@ -113,8 +141,12 @@ public function addContent(string $input, bool $newline = true)
113141
$this->content[] =$lineContent;
114142
}
115143

116-
$this->lines += (int)ceil($this->getDisplayLength($lineContent) /$width) ?:1;
144+
$linesAdded += (int)ceil($this->getDisplayLength($lineContent) /$width) ?:1;
117145
}
146+
147+
$this->lines +=$linesAdded;
148+
149+
return$linesAdded;
118150
}
119151

120152
protectedfunctiondoWrite(string$message,bool$newline)
@@ -127,13 +159,25 @@ protected function doWrite(string $message, bool $newline)
127159

128160
// Check if the previous line (last entry of `$this->content`) needs to be continued
129161
// (i.e. does not end with a line break). In which case, it needs to be erased first.
130-
$deleteLastLine = ($lastLine =end($this->content) ?:'') && !str_ends_with($lastLine, \PHP_EOL) ?1 :0;
131-
$erasedContent =$this->popStreamContentUntilCurrentSection($deleteLastLine);
162+
$linesToClear =$deleteLastLine = ($lastLine =end($this->content) ?:'') && !str_ends_with($lastLine, \PHP_EOL) ?1 :0;
132163

133-
$this->addContent($message,$newline);
164+
$linesAdded =$this->addContent($message,$newline);
165+
166+
if ($lineOverflow =$this->maxHeight >0 &&$this->lines >$this->maxHeight) {
167+
// on overflow, clear the whole section and redraw again (to remove the first lines)
168+
$linesToClear =$this->maxHeight;
169+
}
170+
171+
$erasedContent =$this->popStreamContentUntilCurrentSection($linesToClear);
172+
173+
if ($lineOverflow) {
174+
// redraw existing lines of the section
175+
$previousLinesOfSection =\array_slice($this->content,$this->lines -$this->maxHeight,$this->maxHeight -$linesAdded);
176+
parent::doWrite(implode('',$previousLinesOfSection),false);
177+
}
134178

135-
//If the last line was removed, re-print its content together with the new content.
136-
//Otherwise, just print the new content.
179+
//if the last line was removed, re-print its content together with the new content.
180+
//otherwise, just print the new content.
137181
parent::doWrite($deleteLastLine ?$lastLine.$message :$message,true);
138182
parent::doWrite($erasedContent,false);
139183
}
@@ -153,7 +197,7 @@ private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFr
153197
}
154198

155199
$numberOfLinesToClear +=$section->lines;
156-
if ('' !==$sectionContent =$section->getContent()) {
200+
if ('' !==$sectionContent =$section->getVisibleContent()) {
157201
if (!str_ends_with($sectionContent, \PHP_EOL)) {
158202
$sectionContent .= \PHP_EOL;
159203
}

‎src/Symfony/Component/Console/Tests/Output/ConsoleSectionOutputTest.php‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,56 @@ public function testOverwrite()
103103
$this->assertEquals('Foo'.\PHP_EOL."\x1b[1A\x1b[0JBar".\PHP_EOL,stream_get_contents($output->getStream()));
104104
}
105105

106+
publicfunctiontestMaxHeight()
107+
{
108+
$expected ='';
109+
$sections = [];
110+
$output =newConsoleSectionOutput($this->stream,$sections, OutputInterface::VERBOSITY_NORMAL,true,newOutputFormatter());
111+
$output->setMaxHeight(3);
112+
113+
// fill the section
114+
$output->writeln(['One','Two','Three']);
115+
$expected .='One'.\PHP_EOL.'Two'.\PHP_EOL.'Three'.\PHP_EOL;
116+
117+
// cause overflow (redraw whole section, without first line)
118+
$output->writeln('Four');
119+
$expected .="\x1b[3A\x1b[0J";
120+
$expected .='Two'.\PHP_EOL.'Three'.\PHP_EOL.'Four'.\PHP_EOL;
121+
122+
// cause overflow with multiple new lines at once
123+
$output->writeln('Five'.\PHP_EOL.'Six');
124+
$expected .="\x1b[3A\x1b[0J";
125+
$expected .='Four'.\PHP_EOL.'Five'.\PHP_EOL.'Six'.\PHP_EOL;
126+
127+
// reset line height (redraw whole section, displaying all lines)
128+
$output->setMaxHeight(0);
129+
$expected .="\x1b[3A\x1b[0J";
130+
$expected .='One'.\PHP_EOL.'Two'.\PHP_EOL.'Three'.\PHP_EOL.'Four'.\PHP_EOL.'Five'.\PHP_EOL.'Six'.\PHP_EOL;
131+
132+
rewind($output->getStream());
133+
$this->assertEquals($expected,stream_get_contents($output->getStream()));
134+
}
135+
136+
publicfunctiontestMaxHeightWithoutNewLine()
137+
{
138+
$expected ='';
139+
$sections = [];
140+
$output =newConsoleSectionOutput($this->stream,$sections, OutputInterface::VERBOSITY_NORMAL,true,newOutputFormatter());
141+
$output->setMaxHeight(3);
142+
143+
// fill the section
144+
$output->writeln(['One','Two']);
145+
$output->write('Three');
146+
$expected .='One'.\PHP_EOL.'Two'.\PHP_EOL.'Three'.\PHP_EOL;
147+
148+
// append text to the last line
149+
$output->write(' and Four');
150+
$expected .="\x1b[1A\x1b[0J".'Three and Four'.\PHP_EOL;
151+
152+
rewind($output->getStream());
153+
$this->assertEquals($expected,stream_get_contents($output->getStream()));
154+
}
155+
106156
publicfunctiontestOverwriteMultipleLines()
107157
{
108158
$sections = [];

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp