├── .gitignore ├── .travis.yml ├── tests ├── bootstrap.php ├── AnsiTest.php ├── EscapeSequenceTest.php ├── EscapeSequenceWithParameterBytesTest.php ├── WritersTest.php ├── EscapeSequenceCUUTest.php ├── EscapeSequenceCUDTest.php ├── EscapeSequenceCUFTest.php ├── EscapeSequenceCUPTest.php ├── EscapeSequenceEDTest.php ├── EscapeSequenceSGRTest.php ├── EscapeSequenceELTest.php ├── EscapeSequenceCUBTest.php └── ControlFunctionsTest.php ├── src ├── ControlFunctions │ ├── Bell.php │ ├── Tab.php │ ├── Escape.php │ ├── LineFeed.php │ ├── Backspace.php │ ├── CarriageReturn.php │ ├── Base.php │ └── Enums │ │ └── C0.php ├── Writers │ ├── WriterInterface.php │ ├── FlushableInterface.php │ ├── BufferWriter.php │ ├── ProxyWriter.php │ └── StreamWriter.php ├── ControlSequences │ ├── EscapeSequences │ │ ├── Enums │ │ │ ├── EL.php │ │ │ ├── ED.php │ │ │ ├── FinalByte.php │ │ │ └── SGR.php │ │ ├── Base.php │ │ ├── EL.php │ │ ├── CUU.php │ │ ├── ED.php │ │ ├── CUB.php │ │ ├── CUD.php │ │ ├── CUF.php │ │ ├── CUP.php │ │ └── SGR.php │ ├── Traits │ │ ├── HasFinalByte.php │ │ ├── HasParameterBytes.php │ │ └── HasIntermediateBytes.php │ └── Base.php ├── Traits │ ├── EscapeSequences │ │ ├── CUU.php │ │ ├── CUB.php │ │ ├── CUD.php │ │ ├── CUF.php │ │ ├── CUP.php │ │ ├── ED.php │ │ ├── EL.php │ │ └── SGR.php │ └── ControlFunctions.php └── Ansi.php ├── phpunit.xml.dist ├── composer.json ├── LICENSE ├── readme.md └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | dist: trusty 4 | 5 | php: 6 | - 5.6 7 | - 7.0 8 | - 7.1 9 | - 7.2 10 | - 7.3 11 | 12 | before_script: composer install -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | tests/ 7 | 8 | 9 | 10 | 11 | src/ 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/Enums/EL.php: -------------------------------------------------------------------------------- 1 | =5.4.0" 14 | }, 15 | "require-dev": { 16 | "phpunit/phpunit": "~4.0" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "Bramus\\Ansi\\": "src/" 21 | } 22 | }, 23 | "scripts": { 24 | "test": "vendor/bin/phpunit" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ControlSequences/Traits/HasFinalByte.php: -------------------------------------------------------------------------------- 1 | finalByte = $finalByte; 22 | 23 | return $this; 24 | } 25 | 26 | /** 27 | * Get the Final Byte 28 | * @return string 29 | */ 30 | public function getFinalByte() 31 | { 32 | return $this->finalByte; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Traits/EscapeSequences/CUU.php: -------------------------------------------------------------------------------- 1 | writer->write( 19 | new \Bramus\Ansi\ControlSequences\EscapeSequences\CUU($data) 20 | ); 21 | 22 | // Afford chaining 23 | return $this; 24 | } 25 | 26 | /** 27 | * Move the cursor up n positions 28 | * @param integer $n the number of positions to move the cursor 29 | * @return Ansi self, for chaining 30 | */ 31 | public function cursorUp($n = 1) 32 | { 33 | return $this->cuu($n); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/Base.php: -------------------------------------------------------------------------------- 1 | setFinalByte($finalByte); 24 | 25 | // Call Parent Constructor 26 | parent::__construct( 27 | new \Bramus\Ansi\ControlFunctions\Escape() 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Traits/EscapeSequences/CUB.php: -------------------------------------------------------------------------------- 1 | writer->write( 19 | new \Bramus\Ansi\ControlSequences\EscapeSequences\CUB($data) 20 | ); 21 | 22 | // Afford chaining 23 | return $this; 24 | } 25 | 26 | /** 27 | * Move the cursor back n positions 28 | * @param integer $n the number of positions to move the cursor 29 | * @return Ansi self, for chaining 30 | */ 31 | public function cursorBack($n = 1) 32 | { 33 | return $this->cub($n); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Traits/EscapeSequences/CUD.php: -------------------------------------------------------------------------------- 1 | writer->write( 19 | new \Bramus\Ansi\ControlSequences\EscapeSequences\CUD($data) 20 | ); 21 | 22 | // Afford chaining 23 | return $this; 24 | } 25 | 26 | /** 27 | * Move the cursor n positions down 28 | * @param integer $n the number of positions to move the cursor 29 | * @return Ansi self, for chaining 30 | */ 31 | public function cursorDown($n = 1) 32 | { 33 | return $this->cud($n); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Traits/EscapeSequences/CUF.php: -------------------------------------------------------------------------------- 1 | writer->write( 19 | new \Bramus\Ansi\ControlSequences\EscapeSequences\CUF($data) 20 | ); 21 | 22 | // Afford chaining 23 | return $this; 24 | } 25 | 26 | /** 27 | * Move the cursor n positions forward 28 | * @param integer $n the number of positions to move the cursor 29 | * @return Ansi self, for chaining 30 | */ 31 | public function cursorForward($n = 1) 32 | { 33 | return $this->cuf($n); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Traits/EscapeSequences/CUP.php: -------------------------------------------------------------------------------- 1 | writer->write( 19 | new \Bramus\Ansi\ControlSequences\EscapeSequences\CUP($data) 20 | ); 21 | 22 | // Afford chaining 23 | return $this; 24 | } 25 | 26 | /** 27 | * Move the cursor to coordinates n, m 28 | * @param integer $n the row to move the cursor to 29 | * @param integer $n the column to move the cursor to 30 | * @return Ansi self, for chaining 31 | */ 32 | public function cursorPosition($n = 1, $m = 1) 33 | { 34 | return $this->cup("$n;$m"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/EL.php: -------------------------------------------------------------------------------- 1 | setParameterBytes($parameterBytes); 25 | 26 | // Call Parent Constructor (which will store finalByte) 27 | parent::__construct( 28 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\FinalByte::EL 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/CUU.php: -------------------------------------------------------------------------------- 1 | setParameterBytes($parameterBytes); 25 | 26 | // Call Parent Constructor (which will store finalByte) 27 | parent::__construct( 28 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\FinalByte::CUU 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/ED.php: -------------------------------------------------------------------------------- 1 | setParameterBytes($parameterBytes); 25 | 26 | // Call Parent Constructor (which will store finalByte) 27 | parent::__construct( 28 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\FinalByte::ED 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/CUB.php: -------------------------------------------------------------------------------- 1 | setParameterBytes($parameterBytes); 25 | 26 | // Call Parent Constructor (which will store finalByte) 27 | parent::__construct( 28 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\FinalByte::CUB 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/CUD.php: -------------------------------------------------------------------------------- 1 | setParameterBytes($parameterBytes); 25 | 26 | // Call Parent Constructor (which will store finalByte) 27 | parent::__construct( 28 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\FinalByte::CUD 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/CUF.php: -------------------------------------------------------------------------------- 1 | setParameterBytes($parameterBytes); 25 | 26 | // Call Parent Constructor (which will store finalByte) 27 | parent::__construct( 28 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\FinalByte::CUF 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Bram(us) Van Damme - https://www.bram.us/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/CUP.php: -------------------------------------------------------------------------------- 1 | setParameterBytes($parameterBytes); 26 | 27 | // Call Parent Constructor (which will store finalByte) 28 | parent::__construct( 29 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\FinalByte::CUP 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/AnsiTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\Ansi', $a); 20 | $this->assertInstanceOf('\Bramus\Ansi\Writers\StreamWriter', $a->getWriter()); 21 | 22 | // Create Ansi Instance (using custom writer) 23 | $a = new Ansi(new BufferWriter()); 24 | $this->assertInstanceOf('\Bramus\Ansi\Ansi', $a); 25 | $this->assertInstanceOf('\Bramus\Ansi\Writers\BufferWriter', $a->getWriter()); 26 | 27 | } 28 | 29 | public function testFunctions() 30 | { 31 | 32 | } 33 | 34 | public function testChaining() 35 | { 36 | $a = new Ansi(new BufferWriter()); 37 | $test = $a->text('foo')->text('bar')->get(); 38 | 39 | $this->assertEquals( 40 | $test, 41 | 'foobar' 42 | ); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/SGR.php: -------------------------------------------------------------------------------- 1 | setParameterBytes($parameterBytes); 31 | 32 | // Call Parent Constructor (which will store finalByte) 33 | parent::__construct( 34 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\FinalByte::SGR 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/EscapeSequenceTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\ControlSequences\EscapeSequences\Base', $es); 17 | 18 | // EscapeSequences MUST start with an Escape Control Function 19 | $this->assertInstanceOf('\Bramus\Ansi\ControlFunctions\Escape', $es->getControlSequenceIntroducer()); 20 | 21 | // The finalByte passed in was ED 22 | $this->assertEquals( 23 | $es->getFinalByte(), 24 | FinalByte::ED 25 | ); 26 | } 27 | 28 | public function testFinalByte() 29 | { 30 | $es = new EscapeSequence(FinalByte::ED); 31 | 32 | // Set new final byte 33 | $es->setFinalByte(FinalByte::EL); 34 | 35 | // Check for new Final Byte 36 | $this->assertEquals( 37 | $es->getFinalByte(), 38 | FinalByte::EL 39 | ); 40 | 41 | $this->assertEquals( 42 | $es->get(), 43 | C0::ESC . '[' . FinalByte::EL 44 | ); 45 | 46 | } 47 | 48 | } 49 | 50 | // EOF 51 | -------------------------------------------------------------------------------- /src/Traits/EscapeSequences/ED.php: -------------------------------------------------------------------------------- 1 | writer->write( 22 | new \Bramus\Ansi\ControlSequences\EscapeSequences\ED($data) 23 | ); 24 | 25 | // Afford chaining 26 | return $this; 27 | } 28 | 29 | /** 30 | * Erase the screen from the current line up to the top of the screen 31 | * @return Ansi self, for chaining 32 | */ 33 | public function eraseDisplayUp() 34 | { 35 | return $this->ed(EnumED::UP); 36 | } 37 | 38 | /** 39 | * Erase the screen from the current line down to the bottom of the screen 40 | * @return Ansi self, for chaining 41 | */ 42 | public function eraseDisplayDown() 43 | { 44 | return $this->ed(EnumED::DOWN); 45 | } 46 | 47 | /** 48 | * Erase the entire screen and moves the cursor to home 49 | * @return Ansi self, for chaining 50 | */ 51 | public function eraseDisplay() 52 | { 53 | return $this->ed(EnumED::ALL); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Writers/BufferWriter.php: -------------------------------------------------------------------------------- 1 | buffer .= $data; 25 | 26 | // Afford chaining 27 | return $this; 28 | } 29 | 30 | /** 31 | * Get/Flush the data 32 | * @param boolean $resetAfterwards Reset the data afterwards? 33 | * @return string The data 34 | */ 35 | public function flush($resetAfterwards = true) 36 | { 37 | // Get buffer contents 38 | $buffer = $this->buffer; 39 | 40 | // Clear buffer contents 41 | if ($resetAfterwards) { 42 | $this->clear(); 43 | } 44 | 45 | // Return data that was flushed 46 | return $buffer; 47 | } 48 | 49 | /** 50 | * Reset/Clear the buffer 51 | * @return BufferedStreamWriter self, for chaining 52 | */ 53 | public function clear() 54 | { 55 | // Clear the buffer 56 | $this->buffer = ''; 57 | 58 | // Afford chaining 59 | return $this; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/ControlSequences/Traits/HasParameterBytes.php: -------------------------------------------------------------------------------- 1 | parameterBytes[] = (string) $parameterByte; 21 | 22 | return $this; 23 | } 24 | 25 | /** 26 | * Set the Parameter Byte 27 | * @param array $parameterByte The byte to add 28 | * @return Base self, for chaining 29 | */ 30 | public function setParameterBytes($parameterBytes) 31 | { 32 | foreach ((array) $parameterBytes as $byte) { 33 | $this->addParameterByte($byte); 34 | } 35 | 36 | return $this; 37 | } 38 | 39 | /** 40 | * Get the Parameter Byte 41 | * @param bool $asString As a string, or as an array? 42 | * @return Base self, for chaining 43 | */ 44 | public function getParameterBytes($asString = true) 45 | { 46 | if ($asString === true) { 47 | return implode($this->parameterBytes); 48 | } else { 49 | return $this->parameterBytes; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/ControlSequences/Traits/HasIntermediateBytes.php: -------------------------------------------------------------------------------- 1 | intermediateBytes[] = (string) $intermediateByte; 21 | 22 | return $this; 23 | } 24 | 25 | /** 26 | * Set the Intermediate Byte 27 | * @param array $parameterByte The byte to add 28 | * @return Base self, for chaining 29 | */ 30 | public function setIntermediateBytes($intermediateBytes) 31 | { 32 | foreach ((array) $intermediateBytes as $byte) { 33 | $this->addIntermediateByte($byte); 34 | } 35 | 36 | return $this; 37 | } 38 | 39 | /** 40 | * Get the Intermediate Byte 41 | * @param bool $asString As a string, or as an array? 42 | * @return Base self, for chaining 43 | */ 44 | public function getIntermediateBytes($asString = true) 45 | { 46 | if ($asString === true) { 47 | return implode($this->intermediateBytes); 48 | } else { 49 | return $this->intermediateBytes; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Writers/ProxyWriter.php: -------------------------------------------------------------------------------- 1 | setWriter($writer); 24 | } 25 | 26 | /** 27 | * Set the writer to proxy for 28 | * @param WriterInterface $writer The writer to proxy for 29 | */ 30 | public function setWriter(WriterInterface $writer) 31 | { 32 | $this->writer = $writer; 33 | } 34 | 35 | /** 36 | * Get the writer we are proxying for 37 | * @return WriterInterface The writer we are proxying for 38 | */ 39 | public function getWriter() 40 | { 41 | return $this->writer; 42 | } 43 | 44 | /** 45 | * Get/Flush the data 46 | * @param boolean $resetAfterwards Reset the data afterwards? 47 | * @return string The data 48 | */ 49 | public function flush($resetAfterwards = true) 50 | { 51 | // Get the data from the buffer 52 | $data = parent::flush($resetAfterwards); 53 | 54 | // Write the data to the writer we are proxying for 55 | $this->writer->write($data); 56 | 57 | // Return the data 58 | return $data; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/EscapeSequenceWithParameterBytesTest.php: -------------------------------------------------------------------------------- 1 | assertEquals( 15 | $es->getParameterBytes(), 16 | 0 17 | ); 18 | 19 | $this->assertEquals( 20 | $es->get(), 21 | C0::ESC . '[' . 0 . FinalByte::SGR 22 | ); 23 | } 24 | 25 | public function testParameterBytesSingleAdd() 26 | { 27 | $es = new EscapeSequenceSGR(0); 28 | 29 | // Add a parameter byte 30 | $es->addParameterByte(1); 31 | 32 | $this->assertEquals( 33 | $es->getParameterBytes(), 34 | '01' 35 | ); 36 | 37 | $this->assertEquals( 38 | $es->get(), 39 | C0::ESC . '[' . '0;1' . FinalByte::SGR 40 | ); 41 | 42 | } 43 | 44 | public function testParameterBytesArray() 45 | { 46 | $es = new EscapeSequenceSGR(array(0, 1)); 47 | 48 | // Check for new Final Byte 49 | $this->assertEquals( 50 | $es->getParameterBytes(), 51 | '01' 52 | ); 53 | 54 | $this->assertEquals( 55 | $es->get(), 56 | C0::ESC . '[' . '0;1' . FinalByte::SGR 57 | ); 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/ControlFunctions/Base.php: -------------------------------------------------------------------------------- 1 | setControlCharacter($controlCharacter); 28 | } 29 | 30 | /** 31 | * Set the control character 32 | * @param string $controlCharacter The Control Character 33 | */ 34 | public function setControlCharacter($controlCharacter) 35 | { 36 | // @TODO: Check Validity 37 | $this->controlCharacter = $controlCharacter; 38 | 39 | return $this; 40 | } 41 | 42 | /** 43 | * Build and return the ANSI Code 44 | * @return string The ANSI Code 45 | */ 46 | public function get() 47 | { 48 | return $this->controlCharacter; 49 | } 50 | 51 | /** 52 | * Return the ANSI Code upon __toString 53 | * @return string The ANSI Code 54 | */ 55 | public function __toString() 56 | { 57 | return $this->get(); 58 | } 59 | 60 | /** 61 | * Echo the ANSI Code 62 | */ 63 | public function e() 64 | { 65 | echo $this->get(); 66 | 67 | return $this; 68 | } 69 | } 70 | 71 | // EOF 72 | -------------------------------------------------------------------------------- /src/Traits/EscapeSequences/EL.php: -------------------------------------------------------------------------------- 1 | writer->write( 22 | new \Bramus\Ansi\ControlSequences\EscapeSequences\EL($data) 23 | ); 24 | 25 | // Afford chaining 26 | return $this; 27 | } 28 | 29 | /** 30 | * Erase from the current cursor position to the end of the current line. 31 | * @param boolean $outputNow Echo the character right now, or add it to the buffer building? 32 | * @return Ansi self, for chaining 33 | */ 34 | public function eraseLineToEOL() 35 | { 36 | return $this->el(EnumEL::TO_EOL); 37 | } 38 | 39 | /** 40 | * Erases from the current cursor position to the start of the current line. 41 | * @param boolean $outputNow Echo the character right now, or add it to the buffer building? 42 | * @return Ansi self, for chaining 43 | */ 44 | public function eraseLineToSOL() 45 | { 46 | return $this->el(EnumEL::TO_SOL); 47 | } 48 | 49 | /** 50 | * Erase the entire current line. 51 | * @param boolean $outputNow Echo the character right now, or add it to the buffer building? 52 | * @return Ansi self, for chaining 53 | */ 54 | public function eraseLine() 55 | { 56 | return $this->el(EnumEL::ALL); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Writers/StreamWriter.php: -------------------------------------------------------------------------------- 1 | setStream($stream); 23 | } 24 | 25 | /** 26 | * Destructor 27 | */ 28 | public function __destruct() 29 | { 30 | @fclose($this->stream); 31 | } 32 | 33 | /** 34 | * Set the stream to write to 35 | * @param mixed $stream Stream to write to 36 | */ 37 | public function setStream($stream = null) 38 | { 39 | // String passed in? Try converting it to a stream 40 | if (is_string($stream)) { 41 | $stream = @fopen($stream, 'a'); 42 | } 43 | 44 | // Make sure the stream is a resource 45 | if (!is_resource($stream)) { 46 | throw new \InvalidArgumentException('Invalid Stream'); 47 | } 48 | 49 | // Store it 50 | $this->stream = $stream; 51 | 52 | // Afford chaining 53 | return $this; 54 | } 55 | 56 | /** 57 | * Get stream we are writing to 58 | * @return resource Stream we are writing to 59 | */ 60 | public function getStream() 61 | { 62 | return $this->stream; 63 | } 64 | 65 | /** 66 | * Write Data 67 | * @param string $data Data to write 68 | * @return WriterInterface Self, for chaining 69 | */ 70 | public function write($data) 71 | { 72 | // Write data on the stream 73 | fwrite($this->stream, $data); 74 | 75 | // Afford chaining 76 | return $this; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tests/WritersTest.php: -------------------------------------------------------------------------------- 1 | write('test'); 21 | 22 | // The written data should be echo'd (StreamWriter) 23 | $this->assertEquals('test', ob_get_contents()); 24 | 25 | // Cleanup 26 | ob_end_clean(); 27 | 28 | } 29 | 30 | public function testBufferWriter() 31 | { 32 | 33 | // Create a BufferWriter 34 | $w = new BufferWriter(); 35 | 36 | // Write something to the Proxy 37 | $w->write('test'); 38 | 39 | // Flush its contents 40 | $res = $w->flush(); 41 | 42 | // The written data should be returned 43 | $this->assertEquals('test', $res); 44 | 45 | } 46 | 47 | public function testProxyWriter() 48 | { 49 | 50 | // Start object buffering to catch any output 51 | ob_start(); 52 | 53 | // Create a ProxyWriter which proxies for a StreamWriter 54 | $w = new ProxyWriter(new StreamWriter('php://output')); 55 | 56 | // Write something to the Proxy 57 | $w->write('test'); 58 | 59 | // Flush its contents 60 | $res = $w->flush(); 61 | 62 | // The written data should be echo'd (StreamWriter) 63 | $this->assertEquals('test', ob_get_contents()); 64 | 65 | // The written data should be returned too (ProxyWriter) 66 | $this->assertEquals('test', $res); 67 | 68 | // Cleanup 69 | ob_end_clean(); 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /src/Traits/ControlFunctions.php: -------------------------------------------------------------------------------- 1 | writer->write(new \Bramus\Ansi\ControlFunctions\Bell()); 18 | 19 | // Afford chaining 20 | return $this; 21 | } 22 | 23 | /** 24 | * Add a Backspace Control Character to the buffer / echo it on screen 25 | * @return Ansi self, for chaining 26 | */ 27 | public function backspace() 28 | { 29 | // Write character onto writer 30 | $this->writer->write(new \Bramus\Ansi\ControlFunctions\Backspace()); 31 | 32 | // Afford chaining 33 | return $this; 34 | } 35 | 36 | /** 37 | * Add a Tab Control Character to the buffer / echo it on screen 38 | * @return Ansi self, for chaining 39 | */ 40 | public function tab() 41 | { 42 | // Write character onto writer 43 | $this->writer->write(new \Bramus\Ansi\ControlFunctions\Tab()); 44 | 45 | // Afford chaining 46 | return $this; 47 | } 48 | 49 | /** 50 | * Add a Line Feed Control Character to the buffer / echo it on screen 51 | * @return Ansi self, for chaining 52 | */ 53 | public function lf() 54 | { 55 | // Write character onto writer 56 | $this->writer->write(new \Bramus\Ansi\ControlFunctions\LineFeed()); 57 | 58 | // Afford chaining 59 | return $this; 60 | } 61 | 62 | /** 63 | * Add a Carriage Return Control Character to the buffer / echo it on screen 64 | * @return Ansi self, for chaining 65 | */ 66 | public function cr() 67 | { 68 | // Write character onto writer 69 | $this->writer->write(new \Bramus\Ansi\ControlFunctions\CarriageReturn()); 70 | 71 | // Afford chaining 72 | return $this; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/EscapeSequenceCUUTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\ControlSequences\EscapeSequences\CUU', $es); 17 | 18 | // Final byte must be CUU 19 | $this->assertEquals( 20 | $es->getFinalByte(), 21 | FinalByte::CUU 22 | ); 23 | 24 | // Parameter Byte must be the default 1 25 | $this->assertEquals( 26 | $es->getParameterBytes(), 27 | 1 28 | ); 29 | } 30 | 31 | public function testInstantiationWithNonDefaultParameterByte() 32 | { 33 | $es = new EscapeSequenceCUU(5); 34 | 35 | $this->assertEquals( 36 | $es->getParameterBytes(), 37 | 5 38 | ); 39 | } 40 | 41 | public function testCUURaw() 42 | { 43 | $this->assertEquals( 44 | new EscapeSequenceCUU(1), 45 | C0::ESC.'['.'1'.FinalByte::CUU 46 | ); 47 | } 48 | 49 | public function testAnsiCUUShorthandsSingle() 50 | { 51 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 52 | 53 | $this->assertEquals( 54 | $a->cursorUp()->get(), 55 | new EscapeSequenceCUU() 56 | ); 57 | } 58 | 59 | public function testAnsiCUUShorthandChained() 60 | { 61 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 62 | $es = new EscapeSequenceCUU(); 63 | 64 | $this->assertEquals( 65 | $a->cursorUp()->text('test')->get(), 66 | $es.'test' 67 | ); 68 | } 69 | 70 | public function testAnsiCUUShorthandsChained() 71 | { 72 | 73 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 74 | 75 | $this->assertEquals( 76 | $a->cursorUp()->text('test')->cursorUp()->get(), 77 | (new EscapeSequenceCUU()).'test'.(new EscapeSequenceCUU()) 78 | ); 79 | } 80 | } 81 | 82 | // EOF 83 | -------------------------------------------------------------------------------- /tests/EscapeSequenceCUDTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\ControlSequences\EscapeSequences\CUD', $es); 17 | 18 | // Final byte must be CUD 19 | $this->assertEquals( 20 | $es->getFinalByte(), 21 | FinalByte::CUD 22 | ); 23 | 24 | // Parameter Byte must be the default 1 25 | $this->assertEquals( 26 | $es->getParameterBytes(), 27 | 1 28 | ); 29 | } 30 | 31 | public function testInstantiationWithNonDefaultParameterByte() 32 | { 33 | $es = new EscapeSequenceCUD(5); 34 | 35 | $this->assertEquals( 36 | $es->getParameterBytes(), 37 | 5 38 | ); 39 | } 40 | 41 | public function testCUDRaw() 42 | { 43 | $this->assertEquals( 44 | new EscapeSequenceCUD(1), 45 | C0::ESC.'['.'1'.FinalByte::CUD 46 | ); 47 | } 48 | 49 | public function testAnsiCUDShorthandsSingle() 50 | { 51 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 52 | 53 | $this->assertEquals( 54 | $a->cursorDown()->get(), 55 | new EscapeSequenceCUD() 56 | ); 57 | } 58 | 59 | public function testAnsiCUDShorthandChained() 60 | { 61 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 62 | $es = new EscapeSequenceCUD(); 63 | 64 | $this->assertEquals( 65 | $a->cursorDown()->text('test')->get(), 66 | $es.'test' 67 | ); 68 | } 69 | 70 | public function testAnsiCUDShorthandsChained() 71 | { 72 | 73 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 74 | 75 | $this->assertEquals( 76 | $a->cursorDown()->text('test')->cursorDown()->get(), 77 | (new EscapeSequenceCUD()).'test'.(new EscapeSequenceCUD()) 78 | ); 79 | } 80 | } 81 | 82 | // EOF 83 | -------------------------------------------------------------------------------- /tests/EscapeSequenceCUFTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\ControlSequences\EscapeSequences\CUF', $es); 17 | 18 | // Final byte must be CUF 19 | $this->assertEquals( 20 | $es->getFinalByte(), 21 | FinalByte::CUF 22 | ); 23 | 24 | // Parameter Byte must be the default 1 25 | $this->assertEquals( 26 | $es->getParameterBytes(), 27 | 1 28 | ); 29 | } 30 | 31 | public function testInstantiationWithNonDefaultParameterByte() 32 | { 33 | $es = new EscapeSequenceCUF(5); 34 | 35 | $this->assertEquals( 36 | $es->getParameterBytes(), 37 | 5 38 | ); 39 | } 40 | 41 | public function testCUFRaw() 42 | { 43 | $this->assertEquals( 44 | new EscapeSequenceCUF(1), 45 | C0::ESC.'['.'1'.FinalByte::CUF 46 | ); 47 | } 48 | 49 | public function testAnsiCUFShorthandsSingle() 50 | { 51 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 52 | 53 | $this->assertEquals( 54 | $a->cursorForward()->get(), 55 | new EscapeSequenceCUF() 56 | ); 57 | } 58 | 59 | public function testAnsiCUFShorthandChained() 60 | { 61 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 62 | $es = new EscapeSequenceCUF(); 63 | 64 | $this->assertEquals( 65 | $a->cursorForward()->text('test')->get(), 66 | $es.'test' 67 | ); 68 | } 69 | 70 | public function testAnsiCUFShorthandsChained() 71 | { 72 | 73 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 74 | 75 | $this->assertEquals( 76 | $a->cursorForward()->text('test')->cursorForward()->get(), 77 | (new EscapeSequenceCUF()).'test'.(new EscapeSequenceCUF()) 78 | ); 79 | } 80 | } 81 | 82 | // EOF 83 | -------------------------------------------------------------------------------- /tests/EscapeSequenceCUPTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\ControlSequences\EscapeSequences\CUP', $es); 17 | 18 | // Final byte must be CUP 19 | $this->assertEquals( 20 | $es->getFinalByte(), 21 | FinalByte::CUP 22 | ); 23 | 24 | // Parameter Byte must be the default 1, 1 25 | $this->assertEquals( 26 | $es->getParameterBytes(), 27 | '1;1' 28 | ); 29 | } 30 | 31 | public function testInstantiationWithNonDefaultParameterByte() 32 | { 33 | $es = new EscapeSequenceCUP('5;6'); 34 | 35 | $this->assertEquals( 36 | $es->getParameterBytes(), 37 | '5;6' 38 | ); 39 | } 40 | 41 | public function testCUPRaw() 42 | { 43 | $this->assertEquals( 44 | new EscapeSequenceCUP('1;1'), 45 | C0::ESC.'['.'1;1'.FinalByte::CUP 46 | ); 47 | } 48 | 49 | public function testAnsiCUPShorthandsSingle() 50 | { 51 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 52 | 53 | $this->assertEquals( 54 | $a->cursorPosition()->get(), 55 | new EscapeSequenceCUP() 56 | ); 57 | } 58 | 59 | public function testAnsiCUPShorthandChained() 60 | { 61 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 62 | $es = new EscapeSequenceCUP(); 63 | 64 | $this->assertEquals( 65 | $a->cursorPosition()->text('test')->get(), 66 | $es.'test' 67 | ); 68 | } 69 | 70 | public function testAnsiCUPShorthandsChained() 71 | { 72 | 73 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 74 | 75 | $this->assertEquals( 76 | $a->cursorPosition()->text('test')->cursorPosition()->get(), 77 | (new EscapeSequenceCUP()).'test'.(new EscapeSequenceCUP()) 78 | ); 79 | } 80 | } 81 | 82 | // EOF 83 | -------------------------------------------------------------------------------- /tests/EscapeSequenceEDTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\ControlSequences\EscapeSequences\ED', $es); 18 | 19 | // Final byte must be ED 20 | $this->assertEquals( 21 | $es->getFinalByte(), 22 | FinalByte::ED 23 | ); 24 | 25 | // Parameter Byte must be ED::ALL 26 | $this->assertEquals( 27 | $es->getParameterBytes(), 28 | ED::ALL 29 | ); 30 | } 31 | 32 | public function testEDRaw() 33 | { 34 | // ED::ALL 35 | $this->assertEquals( 36 | new EscapeSequenceED(ED::ALL), 37 | C0::ESC.'['.ED::ALL.FinalByte::ED 38 | ); 39 | 40 | // ED::UP 41 | $this->assertEquals( 42 | new EscapeSequenceED(ED::UP), 43 | C0::ESC.'['.ED::UP.FinalByte::ED 44 | ); 45 | 46 | // ED::DOWN 47 | $this->assertEquals( 48 | new EscapeSequenceED(ED::DOWN), 49 | C0::ESC.'['.ED::DOWN.FinalByte::ED 50 | ); 51 | } 52 | 53 | public function testAnsiEDShorthandsSingle() 54 | { 55 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 56 | 57 | $this->assertEquals( 58 | $a->eraseDisplayUp()->get(), 59 | new EscapeSequenceED(ED::UP) 60 | ); 61 | 62 | $this->assertEquals( 63 | $a->eraseDisplayDown()->get(), 64 | new EscapeSequenceED(ED::DOWN) 65 | ); 66 | 67 | $this->assertEquals( 68 | $a->eraseDisplay()->get(), 69 | new EscapeSequenceED(ED::ALL) 70 | ); 71 | } 72 | 73 | public function testAnsiEDShorthandChained() 74 | { 75 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 76 | $es = new EscapeSequenceED(ED::ALL); 77 | 78 | $this->assertEquals( 79 | $a->ed(ED::ALL)->text('test')->get(), 80 | $es.'test' 81 | ); 82 | } 83 | 84 | public function testAnsiEDShorthandsChained() 85 | { 86 | 87 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 88 | 89 | $this->assertEquals( 90 | $a->eraseDisplayUp()->eraseDisplayDown()->eraseDisplay()->text('test')->get(), 91 | (new EscapeSequenceED(ED::UP)).(new EscapeSequenceED(ED::DOWN)).(new EscapeSequenceED(ED::ALL)).'test' 92 | ); 93 | } 94 | } 95 | 96 | // EOF 97 | -------------------------------------------------------------------------------- /tests/EscapeSequenceSGRTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\ControlSequences\EscapeSequences\SGR', $es); 18 | 19 | // Final byte must be SGR 20 | $this->assertEquals( 21 | $es->getFinalByte(), 22 | FinalByte::SGR 23 | ); 24 | 25 | // Parameter Byte must be SGR::STYLE_NONE 26 | $this->assertEquals( 27 | $es->getParameterBytes(), 28 | SGR::STYLE_NONE 29 | ); 30 | } 31 | 32 | public function testSgrRaw() 33 | { 34 | // One Parameter 35 | $this->assertEquals( 36 | new EscapeSequenceSGR(SGR::STYLE_NONE), 37 | C0::ESC.'['.SGR::STYLE_NONE.FinalByte::SGR 38 | ); 39 | 40 | // Multiple Parameters 41 | $this->assertEquals( 42 | new EscapeSequenceSGR(array(SGR::STYLE_NONE, SGR::STYLE_BOLD)), 43 | C0::ESC.'['.SGR::STYLE_NONE.';'.SGR::STYLE_BOLD.FinalByte::SGR 44 | ); 45 | } 46 | 47 | public function testAnsiSgrShorthandsSingle() 48 | { 49 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 50 | 51 | $this->assertEquals( 52 | $a->sgr(SGR::COLOR_FG_RED)->get(), 53 | new EscapeSequenceSGR(SGR::COLOR_FG_RED) 54 | ); 55 | 56 | $this->assertEquals( 57 | $a->sgr()->get(), 58 | new EscapeSequenceSGR(SGR::STYLE_NONE) 59 | ); 60 | } 61 | 62 | public function testAnsiSgrShorthandChained() 63 | { 64 | 65 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 66 | 67 | $this->assertEquals( 68 | $a->sgr(SGR::COLOR_FG_RED)->text('test')->get(), 69 | (new EscapeSequenceSGR(SGR::COLOR_FG_RED)).'test' 70 | ); 71 | } 72 | 73 | public function testAnsiSgrShorthandsChained() 74 | { 75 | 76 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 77 | 78 | $this->assertEquals( 79 | $a->bold()->underline()->color(SGR::COLOR_FG_RED)->underline()->blink()->text('test')->reset()->get(), 80 | (new EscapeSequenceSGR(SGR::STYLE_BOLD)).(new EscapeSequenceSGR(SGR::STYLE_UNDERLINE)).(new EscapeSequenceSGR(SGR::COLOR_FG_RED)).(new EscapeSequenceSGR(SGR::STYLE_UNDERLINE)).(new EscapeSequenceSGR(SGR::STYLE_BLINK)).'test'.(new EscapeSequenceSGR(SGR::STYLE_NONE)) 81 | ); 82 | } 83 | } 84 | 85 | // EOF 86 | -------------------------------------------------------------------------------- /tests/EscapeSequenceELTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\ControlSequences\EscapeSequences\EL', $es); 18 | 19 | // Final byte must be EL 20 | $this->assertEquals( 21 | $es->getFinalByte(), 22 | FinalByte::EL 23 | ); 24 | 25 | // Parameter Byte must be EL::ALL 26 | $this->assertEquals( 27 | $es->getParameterBytes(), 28 | EL::ALL 29 | ); 30 | } 31 | 32 | public function testELRaw() 33 | { 34 | // EL::ALL 35 | $this->assertEquals( 36 | new EscapeSequenceEL(EL::ALL), 37 | C0::ESC.'['.EL::ALL.FinalByte::EL 38 | ); 39 | 40 | // EL::TO_EOL 41 | $this->assertEquals( 42 | new EscapeSequenceEL(EL::TO_EOL), 43 | C0::ESC.'['.EL::TO_EOL.FinalByte::EL 44 | ); 45 | 46 | // EL::TO_SOL 47 | $this->assertEquals( 48 | new EscapeSequenceEL(EL::TO_SOL), 49 | C0::ESC.'['.EL::TO_SOL.FinalByte::EL 50 | ); 51 | } 52 | 53 | public function testAnsiELShorthandsSingle() 54 | { 55 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 56 | 57 | $this->assertEquals( 58 | $a->eraseLine()->get(), 59 | new EscapeSequenceEL(EL::ALL) 60 | ); 61 | 62 | $this->assertEquals( 63 | $a->eraseLineToEol()->get(), 64 | new EscapeSequenceEL(EL::TO_EOL) 65 | ); 66 | 67 | $this->assertEquals( 68 | $a->eraseLineToSol()->get(), 69 | new EscapeSequenceEL(EL::TO_SOL) 70 | ); 71 | } 72 | 73 | public function testAnsiELShorthandChained() 74 | { 75 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 76 | $es = new EscapeSequenceEL(EL::ALL); 77 | 78 | $this->assertEquals( 79 | $a->el(EL::ALL)->text('test')->get(), 80 | $es.'test' 81 | ); 82 | } 83 | 84 | public function testAnsiELShorthandsChained() 85 | { 86 | 87 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 88 | 89 | $this->assertEquals( 90 | $a->eraseLine()->eraseLineToEol()->eraseLineToSol()->text('test')->get(), 91 | (new EscapeSequenceEL(EL::ALL)).(new EscapeSequenceEL(EL::TO_EOL)).(new EscapeSequenceEL(EL::TO_SOL)).'test' 92 | ); 93 | } 94 | } 95 | 96 | // EOF 97 | -------------------------------------------------------------------------------- /tests/EscapeSequenceCUBTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('\Bramus\Ansi\ControlSequences\EscapeSequences\CUB', $es); 17 | 18 | // Final byte must be CUB 19 | $this->assertEquals( 20 | $es->getFinalByte(), 21 | FinalByte::CUB 22 | ); 23 | 24 | // Parameter Byte must be the default 1 25 | $this->assertEquals( 26 | $es->getParameterBytes(), 27 | 1 28 | ); 29 | } 30 | 31 | public function testInstantiationWithNonDefaultParameterByte() 32 | { 33 | $es = new EscapeSequenceCUB(5); 34 | 35 | $this->assertEquals( 36 | $es->getParameterBytes(), 37 | 5 38 | ); 39 | } 40 | 41 | public function testCUBRaw() 42 | { 43 | $this->assertEquals( 44 | new EscapeSequenceCUB(1), 45 | C0::ESC.'['.'1'.FinalByte::CUB 46 | ); 47 | } 48 | 49 | public function testAnsiCUBShorthandsSingle() 50 | { 51 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 52 | 53 | $this->assertEquals( 54 | $a->cursorBack()->get(), 55 | new EscapeSequenceCUB() 56 | ); 57 | } 58 | 59 | public function testAnsiCUBShorthandChained() 60 | { 61 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 62 | $es = new EscapeSequenceCUB(); 63 | 64 | $this->assertEquals( 65 | $a->cursorBack()->text('test')->get(), 66 | $es.'test' 67 | ); 68 | } 69 | 70 | public function testAnsiCUBShorthandsChained() 71 | { 72 | 73 | $a = new Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 74 | 75 | $this->assertEquals( 76 | $a->cursorBack()->text('test')->cursorBack()->get(), 77 | (new EscapeSequenceCUB()).'test'.(new EscapeSequenceCUB()) 78 | ); 79 | } 80 | 81 | public function testAnsiCUBPractical() 82 | { 83 | ob_start(); 84 | 85 | $numChars = 2; 86 | 87 | $a = new Ansi(new StreamWriter('php://output')); 88 | $a->text('test')->cursorBack($numChars)->text('overwritten'); 89 | 90 | $output = ob_get_contents(); 91 | 92 | // Split on the escape sequence, and manually trim the first part (because we move back) 93 | $output = explode(C0::ESC.'['.$numChars.FinalByte::CUB, $output); 94 | $output[0] = substr($output[0], 0, -$numChars); 95 | 96 | $this->assertEquals('teoverwritten', implode('', $output)); 97 | 98 | ob_end_clean(); 99 | } 100 | } 101 | 102 | // EOF 103 | -------------------------------------------------------------------------------- /tests/ControlFunctionsTest.php: -------------------------------------------------------------------------------- 1 | assertEquals((new \Bramus\Ansi\ControlFunctions\Base(C0::BS))->get(), C0::BS); 17 | 18 | // Helper Classes 19 | $this->assertEquals((new \Bramus\Ansi\ControlFunctions\Backspace())->get(), C0::BS); 20 | $this->assertEquals((new \Bramus\Ansi\ControlFunctions\Backspace())->get(), C0::BACKSPACE); 21 | $this->assertEquals((new \Bramus\Ansi\ControlFunctions\Bell())->get(), C0::BEL); 22 | $this->assertEquals((new \Bramus\Ansi\ControlFunctions\Bell())->get(), C0::BELL); 23 | $this->assertEquals((new \Bramus\Ansi\ControlFunctions\CarriageReturn())->get(), C0::CR); 24 | $this->assertEquals((new \Bramus\Ansi\ControlFunctions\Escape())->get(), C0::ESC); 25 | $this->assertEquals((new \Bramus\Ansi\ControlFunctions\LineFeed())->get(), C0::LF); 26 | $this->assertEquals((new \Bramus\Ansi\ControlFunctions\Tab())->get(), C0::TAB); 27 | } 28 | 29 | public function testUsingToString() 30 | { 31 | // Base 32 | $this->assertEquals(new \Bramus\Ansi\ControlFunctions\Base(C0::BS), C0::BS); 33 | 34 | // Helper Classes 35 | $this->assertEquals(new \Bramus\Ansi\ControlFunctions\Backspace(), C0::BS); 36 | $this->assertEquals(new \Bramus\Ansi\ControlFunctions\Backspace(), C0::BACKSPACE); 37 | $this->assertEquals(new \Bramus\Ansi\ControlFunctions\Bell(), C0::BEL); 38 | $this->assertEquals(new \Bramus\Ansi\ControlFunctions\Bell(), C0::BELL); 39 | $this->assertEquals(new \Bramus\Ansi\ControlFunctions\CarriageReturn(), C0::CR); 40 | $this->assertEquals(new \Bramus\Ansi\ControlFunctions\Escape(), C0::ESC); 41 | $this->assertEquals(new \Bramus\Ansi\ControlFunctions\LineFeed(), C0::LF); 42 | $this->assertEquals(new \Bramus\Ansi\ControlFunctions\Tab(), C0::TAB); 43 | } 44 | 45 | public function testAnsiShorthands() 46 | { 47 | $a = new Ansi(new BufferWriter()); 48 | 49 | $this->assertEquals($a->backspace()->flush(), C0::BS); 50 | $this->assertEquals($a->backspace()->flush(), C0::BACKSPACE); 51 | $this->assertEquals($a->bell()->flush(), C0::BEL); 52 | $this->assertEquals($a->bell()->flush(), C0::BELL); 53 | $this->assertEquals($a->cr()->flush(), C0::CR); 54 | $this->assertEquals($a->lf()->flush(), C0::LF); 55 | $this->assertEquals($a->tab()->flush(), C0::TAB); 56 | } 57 | 58 | public function testAnsiShorthandsChaining() 59 | { 60 | $a = new Ansi(new BufferWriter()); 61 | 62 | // @note: we are going a round trip (bell is tested twice) 63 | // to make sure the test before it is also working correctly 64 | $this->assertEquals( 65 | $a->bell()->backspace()->cr()->lf()->tab()->bell()->get(), 66 | C0::BELL.C0::BS.C0::CR.C0::LF.C0::TAB.C0::BEL 67 | ); 68 | } 69 | } 70 | 71 | // EOF 72 | -------------------------------------------------------------------------------- /src/Ansi.php: -------------------------------------------------------------------------------- 1 | setWriter($writer); 42 | } 43 | 44 | /** 45 | * Sets the writer 46 | * @param Writers\WriterInterface $writer The writer to use 47 | */ 48 | public function setWriter(Writers\WriterInterface $writer) 49 | { 50 | $this->writer = $writer; 51 | } 52 | 53 | /** 54 | * Gets the writer 55 | * @return Writers\WriterInterface $writer The writer used 56 | */ 57 | public function getWriter() 58 | { 59 | return $this->writer; 60 | } 61 | 62 | /** 63 | * Write a piece of text onto the writer 64 | * @param string $text The text to write 65 | * @return Ansi self, for chaining 66 | */ 67 | public function text($text) 68 | { 69 | // Write the text to the writer 70 | $this->writer->write($text); 71 | 72 | // Afford chaining 73 | return $this; 74 | } 75 | 76 | /** 77 | * Flush the contents of the writer 78 | * @param $resetAfterwards Reset the writer contents after flushing? 79 | * @return string The writer contents 80 | */ 81 | public function flush($resetAfterwards = true) 82 | { 83 | if ($this->writer instanceof Writers\FlushableInterface) { 84 | return $this->writer->flush($resetAfterwards); 85 | } else { 86 | throw new \Exception('Flushing a non FlushableInterface is not possible'); 87 | } 88 | } 89 | 90 | public function get($resetAfterwards = true) 91 | { 92 | try { 93 | return $this->flush($resetAfterwards); 94 | } catch (\Exception $e) { 95 | throw $e; 96 | } 97 | } 98 | 99 | /** 100 | * Echo the contents of the writer 101 | * @param $resetAfterwards Reset the writer contents after flushing? 102 | * @return Ansi self, for chaining 103 | */ 104 | public function e($resetAfterwards = true) 105 | { 106 | try { 107 | // Get the contents and echo them 108 | echo $this->flush($resetAfterwards); 109 | 110 | // Afford chaining 111 | return $this; 112 | } catch (\Exception $e) { 113 | throw $e; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/ControlSequences/Base.php: -------------------------------------------------------------------------------- 1 | setControlSequenceIntroducer($controlSequenceIntroducer); 29 | } 30 | 31 | /** 32 | * Set the control sequence introducer 33 | * @param \Bramus\Ansi\ControlFunction $controlSequenceIntroducer A ControlFunction that acts as the Control Sequence Introducer (CSI) 34 | * @return ControlSequence self, for chaining 35 | */ 36 | public function setControlSequenceIntroducer($controlSequenceIntroducer) 37 | { 38 | // Make sure it's a ControlFunction instance 39 | if (is_string($controlSequenceIntroducer)) { 40 | $controlSequenceIntroducer = new ControlFunction($controlSequenceIntroducer); 41 | } 42 | 43 | // @TODO: Check Validity 44 | $this->controlSequenceIntroducer = $controlSequenceIntroducer; 45 | 46 | return $this; 47 | } 48 | 49 | /** 50 | * Gets the CSI 51 | * @return string The CSI 52 | */ 53 | public function getControlSequenceIntroducer() 54 | { 55 | return $this->controlSequenceIntroducer; 56 | } 57 | 58 | /** 59 | * Build and return the ANSI Code 60 | * @return string The ANSI Code 61 | */ 62 | public function get() 63 | { 64 | $toReturn = ''; 65 | 66 | // Append CSI 67 | $toReturn = $this->controlSequenceIntroducer->get().'['; 68 | 69 | // Append Parameter Byte (if any) 70 | if (isset($this->parameterBytes) && sizeof((array) $this->parameterBytes) > 0) { 71 | $toReturn .= implode(';', $this->parameterBytes); 72 | } 73 | 74 | // Append Intermediate Bytes (if any) 75 | if (isset($this->intermediateBytes) && sizeof((array) $this->intermediateBytes) > 0) { 76 | $toReturn .= implode(';', $this->intermediateBytes); // @TODO: Verify that ';' is the glue for intermediate bytes 77 | } 78 | 79 | // Append Final Byte (if any) 80 | if (isset($this->finalByte)) { 81 | $toReturn .= $this->getFinalByte(); 82 | } 83 | 84 | return $toReturn; 85 | } 86 | 87 | /** 88 | * Return the ANSI Code upon __toString 89 | * @return string The ANSI Code 90 | */ 91 | public function __toString() 92 | { 93 | return $this->get(); 94 | } 95 | 96 | /** 97 | * Echo the ANSI Code 98 | */ 99 | public function e() 100 | { 101 | echo $this->get(); 102 | } 103 | } 104 | 105 | // EOF 106 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/Enums/FinalByte.php: -------------------------------------------------------------------------------- 1 | writer->write( 22 | new \Bramus\Ansi\ControlSequences\EscapeSequences\SGR($data) 23 | ); 24 | 25 | // Afford chaining 26 | return $this; 27 | } 28 | 29 | /** 30 | * Shorthand to remove all text styling (colors, bold, etc) 31 | * @return Ansi self, for chaining 32 | */ 33 | public function nostyle() 34 | { 35 | return $this->sgr(array(EnumSGR::STYLE_NONE)); 36 | } 37 | 38 | /** 39 | * Shorthand to remove all text styling (colors, bold, etc) 40 | * @return Ansi self, for chaining 41 | */ 42 | public function reset() 43 | { 44 | return $this->nostyle(); 45 | } 46 | 47 | /** 48 | * Shorthand to set the color. 49 | * @param array $color The color you want to set. Use an array filled with ControlSequences\EscapeSequences\Enums\SGR::COLOR_* constants 50 | * @return Ansi self, for chaining 51 | */ 52 | public function color($color = array()) 53 | { 54 | return $this->sgr($color); 55 | } 56 | 57 | /** 58 | * Shorthand to set make text styling to bold (on some systems bright intensity) 59 | * @return Ansi self, for chaining 60 | */ 61 | public function bold() 62 | { 63 | return $this->sgr(array(EnumSGR::STYLE_BOLD)); 64 | } 65 | 66 | /** 67 | * Shorthand to set the text intensity to bright (on some systems bold) 68 | * @return Ansi self, for chaining 69 | */ 70 | public function bright() 71 | { 72 | return $this->sgr(array(EnumSGR::STYLE_INTENSITY_BRIGHT)); 73 | } 74 | 75 | /** 76 | * Shorthand to set the text styling to normal (no bold/bright) 77 | * @return Ansi self, for chaining 78 | */ 79 | public function normal() 80 | { 81 | return $this->sgr(array(EnumSGR::STYLE_INTENSITY_NORMAL)); 82 | } 83 | 84 | /** 85 | * (Not widely supported) Shorthand to set the text intensity to faint 86 | * @return Ansi self, for chaining 87 | */ 88 | public function faint() 89 | { 90 | return $this->sgr(array(EnumSGR::STYLE_INTENSITY_FAINT)); 91 | } 92 | 93 | /** 94 | * (Not widely supported) Shorthand to set the text styling to italic 95 | * @return Ansi self, for chaining 96 | */ 97 | public function italic() 98 | { 99 | return $this->sgr(array(EnumSGR::STYLE_ITALIC)); 100 | } 101 | 102 | /** 103 | * Shorthand to set the text styling to underline 104 | * @return Ansi self, for chaining 105 | */ 106 | public function underline() 107 | { 108 | return $this->sgr(array(EnumSGR::STYLE_UNDERLINE)); 109 | } 110 | 111 | /** 112 | * Shorthand to set the text styling to blink 113 | * @return Ansi self, for chaining 114 | */ 115 | public function blink() 116 | { 117 | return $this->sgr(array(EnumSGR::STYLE_BLINK)); 118 | } 119 | 120 | /** 121 | * Shorthand to set the text styling to reserved (viz. swap background & foreground color) 122 | * @return Ansi self, for chaining 123 | */ 124 | public function negative() 125 | { 126 | return $this->sgr(array(EnumSGR::STYLE_NEGATIVE)); 127 | } 128 | 129 | /** 130 | * (Not widely supported) Shorthand to set the text styling to strikethrough 131 | * @return Ansi self, for chaining 132 | */ 133 | public function strikethrough() 134 | { 135 | return $this->sgr(array(EnumSGR::STYLE_STRIKETHROUGH)); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/ControlSequences/EscapeSequences/Enums/SGR.php: -------------------------------------------------------------------------------- 1 | color(array(SGR::COLOR_FG_RED, SGR::COLOR_BG_WHITE)) 76 | ->blink() 77 | ->text('I will be blinking red on a white background.') 78 | ->nostyle() 79 | ->text(' And I will be normally styled.') 80 | ->lf() 81 | ->text('Ooh, a bell is coming ...') 82 | ->bell(); 83 | ``` 84 | 85 | See more examples further down on how to use these. 86 | 87 | ## Concepts 88 | 89 | Since v3.0 `bramus/ansi-php` uses the concept of writers to write the data to. By default a `StreamWriter` writing to `php://stdout` is used. 90 | 91 | The following writers are provided 92 | 93 | - `StreamWriter`: Writes the data to a stream. Just pass in the path to a file and it will open a stream for you. Defaults to writing to `php://stdout`. 94 | - `BufferWriter`: Writes the data to a buffer. When calling `flush()` the contents of the buffer will be returned. 95 | - `ProxyWriter`: Acts as a proxy to another writer. Writes the data to an internal buffer. When calling `flush()` the writer will first write the data to the other writer before returning it. 96 | 97 | ## The `Ansi` helper class functions 98 | 99 | ### Core functions: 100 | 101 | - `text($text)`: Write a piece of data to the writer 102 | - `setWriter(\Bramus\Ansi\Writers\WriterInterface $writer)`: Sets the writer 103 | - `getWriter()`: Gets the writer 104 | 105 | ### ANSI Control Function shorthands: 106 | 107 | These shorthands write a Control Character to the writer. 108 | 109 | - `bell()`: Bell Control Character (`\a`) 110 | - `backspace()`: Backspace Control Character (`\b`) 111 | - `tab()`: Tab Control Character (`\t`) 112 | - `lf()`: Line Feed Control Character (`\n`) 113 | - `cr()`: Carriage Return Control Character (`\r`) 114 | - `esc()`: Escape Control Character 115 | 116 | ### SGR ANSI Escape Sequence shorthands: 117 | 118 | These shorthands write SGR ANSI Escape Sequences to the writer. 119 | 120 | - `nostyle()` or `reset()`: Remove all text styling (colors, bold, etc) 121 | - `color()`: Set the foreground and/or backgroundcolor of the text. _(see further)_ 122 | - `bold()` or `bright()`: Bold: On. On some systems "Intensity: Bright" 123 | - `normal()`: Bold: Off. On some systems "Intensity: Normal" 124 | - `faint()`: Intensity: Faint. _(Not widely supported)_ 125 | - `italic()`: Italic: On. _(Not widely supported)_ 126 | - `underline()`: Underline: On. 127 | - `blink()`: Blink: On. 128 | - `negative()`: Inverse or Reverse. Swap foreground and background. 129 | - `strikethrough()`: Strikethrough: On. _(Not widely supported)_ 130 | 131 | __IMPORTANT:__ Select Graphic Rendition works in such a way that text styling you have set will remain active until you call `nostyle()` or `reset()` to return to the default styling. 132 | 133 | ### ED ANSI Escape Sequence shorthands: 134 | 135 | These shorthands write ED ANSI Escape Sequences to the writer. 136 | 137 | - `eraseDisplay()`: Erase the entire screen and moves the cursor to home. 138 | - `eraseDisplayUp()`: Erase the screen from the current line up to the top of the screen. 139 | - `eraseDisplayDown()`: Erase the screen from the current line down to the bottom of the screen. 140 | 141 | ### EL ANSI Escape Sequence shorthands: 142 | 143 | These shorthands write EL ANSI Escape Sequences to the writer. 144 | 145 | - `eraseLine()`: Erase the entire current line. 146 | - `eraseLineToEOL()`: Erase from the current cursor position to the end of the current line. 147 | - `eraseLineToSOL()`: Erases from the current cursor position to the start of the current line. 148 | 149 | ### CUB/CUD/CUF/CUP/CUU ANSI Escape Sequence shorthands: 150 | 151 | - `cursorBack($n)`: Move cursor back `$n` positions _(default: 1)_ 152 | - `cursorForward($n)`: Move cursor forward `$n` positions _(default: 1)_ 153 | - `cursorDown($n)`: Move cursor down `$n` positions _(default: 1)_ 154 | - `cursorUp($n)`: Move cursor up `$n` positions _(default: 1)_ 155 | - `cursorPosition($n, $m)`: Move cursor to position `$n,$m` _(default: 1,1)_ 156 | 157 | ### Extra functions 158 | 159 | - `flush()` or `get()`: Retrieve contents of a `FlushableWriter` writer. 160 | - `e()`: Echo the contents of a `FlushableWriter` writer. 161 | 162 | ## Examples 163 | 164 | ### The Basics 165 | 166 | ```php 167 | // Create Ansi Instance 168 | $ansi = new \Bramus\Ansi\Ansi(); 169 | 170 | // This will output a Bell 171 | $ansi->bell(); 172 | 173 | // This will output some text 174 | $ansi->text('Hello World!'); 175 | ``` 176 | 177 | _NOTE:_ As no `$writer` is passed into the constructor of `\Bramus\Ansi\Ansi`, the default `StreamWriter` writing to `php://stdout` is used. 178 | 179 | ### Using a `FlushableWriter` 180 | 181 | Flushable Writers are writers that cache the data and only output it when flushed using its `flush()` function. The `BufferWriter` and `ProxyWriter` implement this interface. 182 | 183 | ```php 184 | // Create Ansi Instance 185 | $ansi = new \Bramus\Ansi\Ansi(new \Bramus\Ansi\Writers\BufferWriter()); 186 | 187 | // This will append a bell to the buffer. It will not output it. 188 | $ansi->bell(); 189 | 190 | // This will append a bell to the buffer. It will not output it. 191 | $ansi->text('Hello World!'); 192 | 193 | // Now we'll output it 194 | echo $ansi->get(); 195 | ``` 196 | 197 | ### Chaining 198 | 199 | `bramus/ansi-php`'s wrapper `Ansi` class supports chaining. 200 | 201 | ```php 202 | // Create Ansi Instance 203 | $ansi = new \Bramus\Ansi\Ansi(); 204 | 205 | // This will output a Line Feed, some text, a Bell, and a Line Feed 206 | $ansi->lf()->text('hello')->bell()->lf(); 207 | 208 | ``` 209 | 210 | ### Styling Text: The Basics 211 | 212 | ```php 213 | $ansi = new \Bramus\Ansi\Ansi(); 214 | $ansi->bold()->underline()->text('I will be bold and underlined')->lf(); 215 | ``` 216 | 217 | __IMPORTANT__ Select Graphic Rendition works in such a way that text styling you have set will remain active until you call `nostyle()` or `reset()` to return to the default styling. 218 | 219 | 220 | ```php 221 | $ansi = new \Bramus\Ansi\Ansi(); 222 | 223 | $ansi->bold()->underline()->text('I will be bold and underlined')->lf(); 224 | $ansi->text('I will also be bold because nostyle() has not been called yet')->lf(); 225 | $ansi->nostyle()->blink()->text('I will be blinking')->nostyle()->lf(); 226 | $ansi->text('I will be normal because nostyle() was called on the previous line'); 227 | 228 | ``` 229 | 230 | ### Styling Text: Colors 231 | 232 | Colors, and other text styling options, are defined as contants on `\Bramus\Ansi\ControlSequences\EscapeSequences\Enums\SGR`. 233 | 234 | #### Foreground (Text) Colors 235 | 236 | - `SGR::COLOR_FG_BLACK`: Black Foreground Color 237 | - `SGR::COLOR_FG_RED`: Red Foreground Color 238 | - `SGR::COLOR_FG_GREEN`: Green Foreground Color 239 | - `SGR::COLOR_FG_YELLOW`: Yellow Foreground Color 240 | - `SGR::COLOR_FG_BLUE`: Blue Foreground Color 241 | - `SGR::COLOR_FG_PURPLE`: Purple Foreground Color 242 | - `SGR::COLOR_FG_CYAN`: Cyan Foreground Color 243 | - `SGR::COLOR_FG_WHITE`: White Foreground Color 244 | - `SGR::COLOR_FG_BLACK_BRIGHT`: Black Foreground Color (Bright) 245 | - `SGR::COLOR_FG_RED_BRIGHT`: Red Foreground Color (Bright) 246 | - `SGR::COLOR_FG_GREEN_BRIGHT`: Green Foreground Color (Bright) 247 | - `SGR::COLOR_FG_YELLOW_BRIGHT`: Yellow Foreground Color (Bright) 248 | - `SGR::COLOR_FG_BLUE_BRIGHT`: Blue Foreground Color (Bright) 249 | - `SGR::COLOR_FG_PURPLE_BRIGHT`: Purple Foreground Color (Bright) 250 | - `SGR::COLOR_FG_CYAN_BRIGHT`: Cyan Foreground Color (Bright) 251 | - `SGR::COLOR_FG_WHITE_BRIGHT`: White Foreground Color (Bright) 252 | - `SGR::COLOR_FG_RESET`: Default Foreground Color 253 | 254 | #### Background Colors 255 | 256 | - `SGR::COLOR_BG_BLACK`: Black Background Color 257 | - `SGR::COLOR_BG_RED`: Red Background Color 258 | - `SGR::COLOR_BG_GREEN`: Green Background Color 259 | - `SGR::COLOR_BG_YELLOW`: Yellow Background Color 260 | - `SGR::COLOR_BG_BLUE`: Blue Background Color 261 | - `SGR::COLOR_BG_PURPLE`: Purple Background Color 262 | - `SGR::COLOR_BG_CYAN`: Cyan Background Color 263 | - `SGR::COLOR_BG_WHITE`: White Background Color 264 | - `SGR::COLOR_BG_BLACK_BRIGHT`: Black Background Color (Bright) 265 | - `SGR::COLOR_BG_RED_BRIGHT`: Red Background Color (Bright) 266 | - `SGR::COLOR_BG_GREEN_BRIGHT`: Green Background Color (Bright) 267 | - `SGR::COLOR_BG_YELLOW_BRIGHT`: Yellow Background Color (Bright) 268 | - `SGR::COLOR_BG_BLUE_BRIGHT`: Blue Background Color (Bright) 269 | - `SGR::COLOR_BG_PURPLE_BRIGHT`: Purple Background Color (Bright) 270 | - `SGR::COLOR_BG_CYAN_BRIGHT`: Cyan Background Color (Bright) 271 | - `SGR::COLOR_BG_WHITE_BRIGHT`: White Background Color (Bright) 272 | - `SGR::COLOR_BG_RESET`: Default Background Color 273 | 274 | Pass one of these into `$ansi->color()` and the color will be set. 275 | 276 | ```php 277 | use \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\SGR; 278 | 279 | $ansi = new \Bramus\Ansi\Ansi(); 280 | 281 | $ansi->color(SGR::COLOR_FG_RED) 282 | ->text('I will be red') 283 | ->nostyle(); 284 | ``` 285 | 286 | To set the foreground and background color in one call, pass them using an array to `$ansi->color()` 287 | 288 | ```php 289 | use \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\SGR; 290 | 291 | $ansi = new \Bramus\Ansi\Ansi(); 292 | 293 | $ansi->color(array(SGR::COLOR_FG_RED, SGR::COLOR_BG_WHITE)) 294 | ->blink() 295 | ->text('I will be blinking red on a wrhite background.') 296 | ->nostyle(); 297 | ``` 298 | 299 | ### Creating a loading Spinner 300 | 301 | By manipulating the cursor position one can create an in-place spinner 302 | 303 | ```php 304 | use \Bramus\Ansi\Ansi; 305 | use \Bramus\Ansi\Writers\StreamWriter; 306 | use \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\EL; 307 | use \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\SGR; 308 | 309 | // Create Ansi Instance 310 | $ansi = new Ansi(new StreamWriter('php://stdout')); 311 | 312 | // Parts of our spinner 313 | $spinnerParts = ['⣷','⣯','⣟','⡿','⢿','⣻','⣽','⣾']; 314 | 315 | $ansi->text('Loading Data')->lf(); 316 | for ($i = 0; $i < 100; $i++) { 317 | $ansi 318 | // Erase entire line 319 | ->el(EL::ALL) 320 | // Go back to very first position on current line 321 | ->cursorBack(9999) 322 | // Add a blue spinner 323 | ->color(SGR::COLOR_FG_BLUE)->text($spinnerParts[$i % sizeof($spinnerParts)]) 324 | // Write percentage 325 | ->nostyle()->text(' ' . str_pad($i, 3, 0, STR_PAD_LEFT) . '%'); 326 | 327 | usleep(50000); 328 | } 329 | $ansi 330 | ->el(EL::ALL) 331 | ->cursorBack(9999) 332 | ->color(SGR::COLOR_FG_GREEN)->text('✔') 333 | ->nostyle()->text(' 100%') 334 | ->lf(); 335 | ``` 336 | 337 | This snippet will output a little loading spinner icon + the current percentage (e.g. `⣯ 009%`) that constantly updates in-place. When 100% is reached, the line will read `✔ 100%`. 338 | 339 | ### Using the raw classes 340 | 341 | As all raw `ControlFunction` and `ControlSequence` classes are provided with a `__toString()` function it's perfectly possible to directly `echo` some `bramus/ansi-php` instance. 342 | 343 | ```php 344 | // Output a Bell Control Character 345 | echo new \Bramus\Ansi\ControlFunctions\Bell(); 346 | 347 | // Output an ED instruction, to erase the entire screen 348 | echo new \Bramus\Ansi\ControlSequences\EscapeSequences\ED( 349 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\ED::ALL 350 | ); 351 | ``` 352 | 353 | To fetch their contents, use the `get()` function: 354 | 355 | ```php 356 | // Get ANSI string for a Bell Control Character 357 | $bell = (new \Bramus\Ansi\ControlFunctions\Bell())->get(); 358 | 359 | // Get ANSI string for an ED instruction, to erase the entire screen 360 | $eraseDisplay = (new \Bramus\Ansi\ControlSequences\EscapeSequences\ED( 361 | \Bramus\Ansi\ControlSequences\EscapeSequences\Enums\ED::ALL 362 | ))->get(); 363 | 364 | echo $bell . $bell . $eraseDisplay . $bell; 365 | ``` 366 | 367 | ## Unit Testing 368 | 369 | `bramus/ansi-php` ships with unit tests using [PHPUnit](https://github.com/sebastianbergmann/phpunit/). 370 | 371 | - If PHPUnit is installed globally run `phpunit` to run the tests. 372 | 373 | - If PHPUnit is not installed globally, install it locally throuh composer by running `composer install --dev`. Run the tests themselves by calling `vendor/bin/phpunit` or `composer test` 374 | 375 | Unit tests are also automatically run [on Travis CI](http://travis-ci.org/bramus/ansi-php) 376 | 377 | ## License 378 | 379 | `bramus/ansi-php` is released under the MIT public license. See the enclosed `LICENSE` for details. 380 | 381 | ## ANSI References 382 | 383 | - [http://en.wikipedia.org/wiki/ANSI_escape_code](http://en.wikipedia.org/wiki/ANSI_escape_code) 384 | - [http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf) 385 | - [http://wiki.bash-hackers.org/scripting/terminalcodes](http://wiki.bash-hackers.org/scripting/terminalcodes) 386 | - [http://web.mit.edu/gnu/doc/html/screen_10.html](http://web.mit.edu/gnu/doc/html/screen_10.html) 387 | - [http://www.isthe.com/chongo/tech/comp/ansi_escapes.html](http://www.isthe.com/chongo/tech/comp/ansi_escapes.html) 388 | - [http://www.termsys.demon.co.uk/vtansi.htm](http://www.termsys.demon.co.uk/vtansi.htm) 389 | - [http://rrbrandt.dee.ufcg.edu.br/en/docs/ansi/](http://rrbrandt.dee.ufcg.edu.br/en/docs/ansi/) 390 | - [http://tldp.org/HOWTO/Bash-Prompt-HOWTO/c327.html](http://tldp.org/HOWTO/Bash-Prompt-HOWTO/c327.html) 391 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "2bd803cd6028d92b2de740f9bff2af1d", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "doctrine/instantiator", 12 | "version": "1.0.5", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/doctrine/instantiator.git", 16 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 21 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": ">=5.3,<8.0-DEV" 26 | }, 27 | "require-dev": { 28 | "athletic/athletic": "~0.1.8", 29 | "ext-pdo": "*", 30 | "ext-phar": "*", 31 | "phpunit/phpunit": "~4.0", 32 | "squizlabs/php_codesniffer": "~2.0" 33 | }, 34 | "type": "library", 35 | "extra": { 36 | "branch-alias": { 37 | "dev-master": "1.0.x-dev" 38 | } 39 | }, 40 | "autoload": { 41 | "psr-4": { 42 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 43 | } 44 | }, 45 | "notification-url": "https://packagist.org/downloads/", 46 | "license": [ 47 | "MIT" 48 | ], 49 | "authors": [ 50 | { 51 | "name": "Marco Pivetta", 52 | "email": "ocramius@gmail.com", 53 | "homepage": "http://ocramius.github.com/" 54 | } 55 | ], 56 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 57 | "homepage": "https://github.com/doctrine/instantiator", 58 | "keywords": [ 59 | "constructor", 60 | "instantiate" 61 | ], 62 | "time": "2015-06-14T21:17:01+00:00" 63 | }, 64 | { 65 | "name": "phpdocumentor/reflection-common", 66 | "version": "1.0.1", 67 | "source": { 68 | "type": "git", 69 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 70 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 71 | }, 72 | "dist": { 73 | "type": "zip", 74 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 75 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 76 | "shasum": "" 77 | }, 78 | "require": { 79 | "php": ">=5.5" 80 | }, 81 | "require-dev": { 82 | "phpunit/phpunit": "^4.6" 83 | }, 84 | "type": "library", 85 | "extra": { 86 | "branch-alias": { 87 | "dev-master": "1.0.x-dev" 88 | } 89 | }, 90 | "autoload": { 91 | "psr-4": { 92 | "phpDocumentor\\Reflection\\": [ 93 | "src" 94 | ] 95 | } 96 | }, 97 | "notification-url": "https://packagist.org/downloads/", 98 | "license": [ 99 | "MIT" 100 | ], 101 | "authors": [ 102 | { 103 | "name": "Jaap van Otterdijk", 104 | "email": "opensource@ijaap.nl" 105 | } 106 | ], 107 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 108 | "homepage": "http://www.phpdoc.org", 109 | "keywords": [ 110 | "FQSEN", 111 | "phpDocumentor", 112 | "phpdoc", 113 | "reflection", 114 | "static analysis" 115 | ], 116 | "time": "2017-09-11T18:02:19+00:00" 117 | }, 118 | { 119 | "name": "phpdocumentor/reflection-docblock", 120 | "version": "3.3.2", 121 | "source": { 122 | "type": "git", 123 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 124 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" 125 | }, 126 | "dist": { 127 | "type": "zip", 128 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", 129 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", 130 | "shasum": "" 131 | }, 132 | "require": { 133 | "php": "^5.6 || ^7.0", 134 | "phpdocumentor/reflection-common": "^1.0.0", 135 | "phpdocumentor/type-resolver": "^0.4.0", 136 | "webmozart/assert": "^1.0" 137 | }, 138 | "require-dev": { 139 | "mockery/mockery": "^0.9.4", 140 | "phpunit/phpunit": "^4.4" 141 | }, 142 | "type": "library", 143 | "autoload": { 144 | "psr-4": { 145 | "phpDocumentor\\Reflection\\": [ 146 | "src/" 147 | ] 148 | } 149 | }, 150 | "notification-url": "https://packagist.org/downloads/", 151 | "license": [ 152 | "MIT" 153 | ], 154 | "authors": [ 155 | { 156 | "name": "Mike van Riel", 157 | "email": "me@mikevanriel.com" 158 | } 159 | ], 160 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 161 | "time": "2017-11-10T14:09:06+00:00" 162 | }, 163 | { 164 | "name": "phpdocumentor/type-resolver", 165 | "version": "0.4.0", 166 | "source": { 167 | "type": "git", 168 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 169 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 170 | }, 171 | "dist": { 172 | "type": "zip", 173 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 174 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 175 | "shasum": "" 176 | }, 177 | "require": { 178 | "php": "^5.5 || ^7.0", 179 | "phpdocumentor/reflection-common": "^1.0" 180 | }, 181 | "require-dev": { 182 | "mockery/mockery": "^0.9.4", 183 | "phpunit/phpunit": "^5.2||^4.8.24" 184 | }, 185 | "type": "library", 186 | "extra": { 187 | "branch-alias": { 188 | "dev-master": "1.0.x-dev" 189 | } 190 | }, 191 | "autoload": { 192 | "psr-4": { 193 | "phpDocumentor\\Reflection\\": [ 194 | "src/" 195 | ] 196 | } 197 | }, 198 | "notification-url": "https://packagist.org/downloads/", 199 | "license": [ 200 | "MIT" 201 | ], 202 | "authors": [ 203 | { 204 | "name": "Mike van Riel", 205 | "email": "me@mikevanriel.com" 206 | } 207 | ], 208 | "time": "2017-07-14T14:27:02+00:00" 209 | }, 210 | { 211 | "name": "phpspec/prophecy", 212 | "version": "1.8.0", 213 | "source": { 214 | "type": "git", 215 | "url": "https://github.com/phpspec/prophecy.git", 216 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" 217 | }, 218 | "dist": { 219 | "type": "zip", 220 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", 221 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", 222 | "shasum": "" 223 | }, 224 | "require": { 225 | "doctrine/instantiator": "^1.0.2", 226 | "php": "^5.3|^7.0", 227 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", 228 | "sebastian/comparator": "^1.1|^2.0|^3.0", 229 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 230 | }, 231 | "require-dev": { 232 | "phpspec/phpspec": "^2.5|^3.2", 233 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 234 | }, 235 | "type": "library", 236 | "extra": { 237 | "branch-alias": { 238 | "dev-master": "1.8.x-dev" 239 | } 240 | }, 241 | "autoload": { 242 | "psr-0": { 243 | "Prophecy\\": "src/" 244 | } 245 | }, 246 | "notification-url": "https://packagist.org/downloads/", 247 | "license": [ 248 | "MIT" 249 | ], 250 | "authors": [ 251 | { 252 | "name": "Konstantin Kudryashov", 253 | "email": "ever.zet@gmail.com", 254 | "homepage": "http://everzet.com" 255 | }, 256 | { 257 | "name": "Marcello Duarte", 258 | "email": "marcello.duarte@gmail.com" 259 | } 260 | ], 261 | "description": "Highly opinionated mocking framework for PHP 5.3+", 262 | "homepage": "https://github.com/phpspec/prophecy", 263 | "keywords": [ 264 | "Double", 265 | "Dummy", 266 | "fake", 267 | "mock", 268 | "spy", 269 | "stub" 270 | ], 271 | "time": "2018-08-05T17:53:17+00:00" 272 | }, 273 | { 274 | "name": "phpunit/php-code-coverage", 275 | "version": "2.2.4", 276 | "source": { 277 | "type": "git", 278 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 279 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" 280 | }, 281 | "dist": { 282 | "type": "zip", 283 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", 284 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", 285 | "shasum": "" 286 | }, 287 | "require": { 288 | "php": ">=5.3.3", 289 | "phpunit/php-file-iterator": "~1.3", 290 | "phpunit/php-text-template": "~1.2", 291 | "phpunit/php-token-stream": "~1.3", 292 | "sebastian/environment": "^1.3.2", 293 | "sebastian/version": "~1.0" 294 | }, 295 | "require-dev": { 296 | "ext-xdebug": ">=2.1.4", 297 | "phpunit/phpunit": "~4" 298 | }, 299 | "suggest": { 300 | "ext-dom": "*", 301 | "ext-xdebug": ">=2.2.1", 302 | "ext-xmlwriter": "*" 303 | }, 304 | "type": "library", 305 | "extra": { 306 | "branch-alias": { 307 | "dev-master": "2.2.x-dev" 308 | } 309 | }, 310 | "autoload": { 311 | "classmap": [ 312 | "src/" 313 | ] 314 | }, 315 | "notification-url": "https://packagist.org/downloads/", 316 | "license": [ 317 | "BSD-3-Clause" 318 | ], 319 | "authors": [ 320 | { 321 | "name": "Sebastian Bergmann", 322 | "email": "sb@sebastian-bergmann.de", 323 | "role": "lead" 324 | } 325 | ], 326 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 327 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 328 | "keywords": [ 329 | "coverage", 330 | "testing", 331 | "xunit" 332 | ], 333 | "time": "2015-10-06T15:47:00+00:00" 334 | }, 335 | { 336 | "name": "phpunit/php-file-iterator", 337 | "version": "1.4.5", 338 | "source": { 339 | "type": "git", 340 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 341 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" 342 | }, 343 | "dist": { 344 | "type": "zip", 345 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", 346 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", 347 | "shasum": "" 348 | }, 349 | "require": { 350 | "php": ">=5.3.3" 351 | }, 352 | "type": "library", 353 | "extra": { 354 | "branch-alias": { 355 | "dev-master": "1.4.x-dev" 356 | } 357 | }, 358 | "autoload": { 359 | "classmap": [ 360 | "src/" 361 | ] 362 | }, 363 | "notification-url": "https://packagist.org/downloads/", 364 | "license": [ 365 | "BSD-3-Clause" 366 | ], 367 | "authors": [ 368 | { 369 | "name": "Sebastian Bergmann", 370 | "email": "sb@sebastian-bergmann.de", 371 | "role": "lead" 372 | } 373 | ], 374 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 375 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 376 | "keywords": [ 377 | "filesystem", 378 | "iterator" 379 | ], 380 | "time": "2017-11-27T13:52:08+00:00" 381 | }, 382 | { 383 | "name": "phpunit/php-text-template", 384 | "version": "1.2.1", 385 | "source": { 386 | "type": "git", 387 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 388 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 389 | }, 390 | "dist": { 391 | "type": "zip", 392 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 393 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 394 | "shasum": "" 395 | }, 396 | "require": { 397 | "php": ">=5.3.3" 398 | }, 399 | "type": "library", 400 | "autoload": { 401 | "classmap": [ 402 | "src/" 403 | ] 404 | }, 405 | "notification-url": "https://packagist.org/downloads/", 406 | "license": [ 407 | "BSD-3-Clause" 408 | ], 409 | "authors": [ 410 | { 411 | "name": "Sebastian Bergmann", 412 | "email": "sebastian@phpunit.de", 413 | "role": "lead" 414 | } 415 | ], 416 | "description": "Simple template engine.", 417 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 418 | "keywords": [ 419 | "template" 420 | ], 421 | "time": "2015-06-21T13:50:34+00:00" 422 | }, 423 | { 424 | "name": "phpunit/php-timer", 425 | "version": "1.0.9", 426 | "source": { 427 | "type": "git", 428 | "url": "https://github.com/sebastianbergmann/php-timer.git", 429 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 430 | }, 431 | "dist": { 432 | "type": "zip", 433 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 434 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 435 | "shasum": "" 436 | }, 437 | "require": { 438 | "php": "^5.3.3 || ^7.0" 439 | }, 440 | "require-dev": { 441 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 442 | }, 443 | "type": "library", 444 | "extra": { 445 | "branch-alias": { 446 | "dev-master": "1.0-dev" 447 | } 448 | }, 449 | "autoload": { 450 | "classmap": [ 451 | "src/" 452 | ] 453 | }, 454 | "notification-url": "https://packagist.org/downloads/", 455 | "license": [ 456 | "BSD-3-Clause" 457 | ], 458 | "authors": [ 459 | { 460 | "name": "Sebastian Bergmann", 461 | "email": "sb@sebastian-bergmann.de", 462 | "role": "lead" 463 | } 464 | ], 465 | "description": "Utility class for timing", 466 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 467 | "keywords": [ 468 | "timer" 469 | ], 470 | "time": "2017-02-26T11:10:40+00:00" 471 | }, 472 | { 473 | "name": "phpunit/php-token-stream", 474 | "version": "1.4.12", 475 | "source": { 476 | "type": "git", 477 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 478 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" 479 | }, 480 | "dist": { 481 | "type": "zip", 482 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", 483 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", 484 | "shasum": "" 485 | }, 486 | "require": { 487 | "ext-tokenizer": "*", 488 | "php": ">=5.3.3" 489 | }, 490 | "require-dev": { 491 | "phpunit/phpunit": "~4.2" 492 | }, 493 | "type": "library", 494 | "extra": { 495 | "branch-alias": { 496 | "dev-master": "1.4-dev" 497 | } 498 | }, 499 | "autoload": { 500 | "classmap": [ 501 | "src/" 502 | ] 503 | }, 504 | "notification-url": "https://packagist.org/downloads/", 505 | "license": [ 506 | "BSD-3-Clause" 507 | ], 508 | "authors": [ 509 | { 510 | "name": "Sebastian Bergmann", 511 | "email": "sebastian@phpunit.de" 512 | } 513 | ], 514 | "description": "Wrapper around PHP's tokenizer extension.", 515 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 516 | "keywords": [ 517 | "tokenizer" 518 | ], 519 | "time": "2017-12-04T08:55:13+00:00" 520 | }, 521 | { 522 | "name": "phpunit/phpunit", 523 | "version": "4.8.36", 524 | "source": { 525 | "type": "git", 526 | "url": "https://github.com/sebastianbergmann/phpunit.git", 527 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" 528 | }, 529 | "dist": { 530 | "type": "zip", 531 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", 532 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", 533 | "shasum": "" 534 | }, 535 | "require": { 536 | "ext-dom": "*", 537 | "ext-json": "*", 538 | "ext-pcre": "*", 539 | "ext-reflection": "*", 540 | "ext-spl": "*", 541 | "php": ">=5.3.3", 542 | "phpspec/prophecy": "^1.3.1", 543 | "phpunit/php-code-coverage": "~2.1", 544 | "phpunit/php-file-iterator": "~1.4", 545 | "phpunit/php-text-template": "~1.2", 546 | "phpunit/php-timer": "^1.0.6", 547 | "phpunit/phpunit-mock-objects": "~2.3", 548 | "sebastian/comparator": "~1.2.2", 549 | "sebastian/diff": "~1.2", 550 | "sebastian/environment": "~1.3", 551 | "sebastian/exporter": "~1.2", 552 | "sebastian/global-state": "~1.0", 553 | "sebastian/version": "~1.0", 554 | "symfony/yaml": "~2.1|~3.0" 555 | }, 556 | "suggest": { 557 | "phpunit/php-invoker": "~1.1" 558 | }, 559 | "bin": [ 560 | "phpunit" 561 | ], 562 | "type": "library", 563 | "extra": { 564 | "branch-alias": { 565 | "dev-master": "4.8.x-dev" 566 | } 567 | }, 568 | "autoload": { 569 | "classmap": [ 570 | "src/" 571 | ] 572 | }, 573 | "notification-url": "https://packagist.org/downloads/", 574 | "license": [ 575 | "BSD-3-Clause" 576 | ], 577 | "authors": [ 578 | { 579 | "name": "Sebastian Bergmann", 580 | "email": "sebastian@phpunit.de", 581 | "role": "lead" 582 | } 583 | ], 584 | "description": "The PHP Unit Testing framework.", 585 | "homepage": "https://phpunit.de/", 586 | "keywords": [ 587 | "phpunit", 588 | "testing", 589 | "xunit" 590 | ], 591 | "time": "2017-06-21T08:07:12+00:00" 592 | }, 593 | { 594 | "name": "phpunit/phpunit-mock-objects", 595 | "version": "2.3.8", 596 | "source": { 597 | "type": "git", 598 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 599 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" 600 | }, 601 | "dist": { 602 | "type": "zip", 603 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", 604 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", 605 | "shasum": "" 606 | }, 607 | "require": { 608 | "doctrine/instantiator": "^1.0.2", 609 | "php": ">=5.3.3", 610 | "phpunit/php-text-template": "~1.2", 611 | "sebastian/exporter": "~1.2" 612 | }, 613 | "require-dev": { 614 | "phpunit/phpunit": "~4.4" 615 | }, 616 | "suggest": { 617 | "ext-soap": "*" 618 | }, 619 | "type": "library", 620 | "extra": { 621 | "branch-alias": { 622 | "dev-master": "2.3.x-dev" 623 | } 624 | }, 625 | "autoload": { 626 | "classmap": [ 627 | "src/" 628 | ] 629 | }, 630 | "notification-url": "https://packagist.org/downloads/", 631 | "license": [ 632 | "BSD-3-Clause" 633 | ], 634 | "authors": [ 635 | { 636 | "name": "Sebastian Bergmann", 637 | "email": "sb@sebastian-bergmann.de", 638 | "role": "lead" 639 | } 640 | ], 641 | "description": "Mock Object library for PHPUnit", 642 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 643 | "keywords": [ 644 | "mock", 645 | "xunit" 646 | ], 647 | "time": "2015-10-02T06:51:40+00:00" 648 | }, 649 | { 650 | "name": "sebastian/comparator", 651 | "version": "1.2.4", 652 | "source": { 653 | "type": "git", 654 | "url": "https://github.com/sebastianbergmann/comparator.git", 655 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 656 | }, 657 | "dist": { 658 | "type": "zip", 659 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 660 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 661 | "shasum": "" 662 | }, 663 | "require": { 664 | "php": ">=5.3.3", 665 | "sebastian/diff": "~1.2", 666 | "sebastian/exporter": "~1.2 || ~2.0" 667 | }, 668 | "require-dev": { 669 | "phpunit/phpunit": "~4.4" 670 | }, 671 | "type": "library", 672 | "extra": { 673 | "branch-alias": { 674 | "dev-master": "1.2.x-dev" 675 | } 676 | }, 677 | "autoload": { 678 | "classmap": [ 679 | "src/" 680 | ] 681 | }, 682 | "notification-url": "https://packagist.org/downloads/", 683 | "license": [ 684 | "BSD-3-Clause" 685 | ], 686 | "authors": [ 687 | { 688 | "name": "Jeff Welch", 689 | "email": "whatthejeff@gmail.com" 690 | }, 691 | { 692 | "name": "Volker Dusch", 693 | "email": "github@wallbash.com" 694 | }, 695 | { 696 | "name": "Bernhard Schussek", 697 | "email": "bschussek@2bepublished.at" 698 | }, 699 | { 700 | "name": "Sebastian Bergmann", 701 | "email": "sebastian@phpunit.de" 702 | } 703 | ], 704 | "description": "Provides the functionality to compare PHP values for equality", 705 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 706 | "keywords": [ 707 | "comparator", 708 | "compare", 709 | "equality" 710 | ], 711 | "time": "2017-01-29T09:50:25+00:00" 712 | }, 713 | { 714 | "name": "sebastian/diff", 715 | "version": "1.4.3", 716 | "source": { 717 | "type": "git", 718 | "url": "https://github.com/sebastianbergmann/diff.git", 719 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 720 | }, 721 | "dist": { 722 | "type": "zip", 723 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", 724 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 725 | "shasum": "" 726 | }, 727 | "require": { 728 | "php": "^5.3.3 || ^7.0" 729 | }, 730 | "require-dev": { 731 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 732 | }, 733 | "type": "library", 734 | "extra": { 735 | "branch-alias": { 736 | "dev-master": "1.4-dev" 737 | } 738 | }, 739 | "autoload": { 740 | "classmap": [ 741 | "src/" 742 | ] 743 | }, 744 | "notification-url": "https://packagist.org/downloads/", 745 | "license": [ 746 | "BSD-3-Clause" 747 | ], 748 | "authors": [ 749 | { 750 | "name": "Kore Nordmann", 751 | "email": "mail@kore-nordmann.de" 752 | }, 753 | { 754 | "name": "Sebastian Bergmann", 755 | "email": "sebastian@phpunit.de" 756 | } 757 | ], 758 | "description": "Diff implementation", 759 | "homepage": "https://github.com/sebastianbergmann/diff", 760 | "keywords": [ 761 | "diff" 762 | ], 763 | "time": "2017-05-22T07:24:03+00:00" 764 | }, 765 | { 766 | "name": "sebastian/environment", 767 | "version": "1.3.8", 768 | "source": { 769 | "type": "git", 770 | "url": "https://github.com/sebastianbergmann/environment.git", 771 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" 772 | }, 773 | "dist": { 774 | "type": "zip", 775 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", 776 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", 777 | "shasum": "" 778 | }, 779 | "require": { 780 | "php": "^5.3.3 || ^7.0" 781 | }, 782 | "require-dev": { 783 | "phpunit/phpunit": "^4.8 || ^5.0" 784 | }, 785 | "type": "library", 786 | "extra": { 787 | "branch-alias": { 788 | "dev-master": "1.3.x-dev" 789 | } 790 | }, 791 | "autoload": { 792 | "classmap": [ 793 | "src/" 794 | ] 795 | }, 796 | "notification-url": "https://packagist.org/downloads/", 797 | "license": [ 798 | "BSD-3-Clause" 799 | ], 800 | "authors": [ 801 | { 802 | "name": "Sebastian Bergmann", 803 | "email": "sebastian@phpunit.de" 804 | } 805 | ], 806 | "description": "Provides functionality to handle HHVM/PHP environments", 807 | "homepage": "http://www.github.com/sebastianbergmann/environment", 808 | "keywords": [ 809 | "Xdebug", 810 | "environment", 811 | "hhvm" 812 | ], 813 | "time": "2016-08-18T05:49:44+00:00" 814 | }, 815 | { 816 | "name": "sebastian/exporter", 817 | "version": "1.2.2", 818 | "source": { 819 | "type": "git", 820 | "url": "https://github.com/sebastianbergmann/exporter.git", 821 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" 822 | }, 823 | "dist": { 824 | "type": "zip", 825 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", 826 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", 827 | "shasum": "" 828 | }, 829 | "require": { 830 | "php": ">=5.3.3", 831 | "sebastian/recursion-context": "~1.0" 832 | }, 833 | "require-dev": { 834 | "ext-mbstring": "*", 835 | "phpunit/phpunit": "~4.4" 836 | }, 837 | "type": "library", 838 | "extra": { 839 | "branch-alias": { 840 | "dev-master": "1.3.x-dev" 841 | } 842 | }, 843 | "autoload": { 844 | "classmap": [ 845 | "src/" 846 | ] 847 | }, 848 | "notification-url": "https://packagist.org/downloads/", 849 | "license": [ 850 | "BSD-3-Clause" 851 | ], 852 | "authors": [ 853 | { 854 | "name": "Jeff Welch", 855 | "email": "whatthejeff@gmail.com" 856 | }, 857 | { 858 | "name": "Volker Dusch", 859 | "email": "github@wallbash.com" 860 | }, 861 | { 862 | "name": "Bernhard Schussek", 863 | "email": "bschussek@2bepublished.at" 864 | }, 865 | { 866 | "name": "Sebastian Bergmann", 867 | "email": "sebastian@phpunit.de" 868 | }, 869 | { 870 | "name": "Adam Harvey", 871 | "email": "aharvey@php.net" 872 | } 873 | ], 874 | "description": "Provides the functionality to export PHP variables for visualization", 875 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 876 | "keywords": [ 877 | "export", 878 | "exporter" 879 | ], 880 | "time": "2016-06-17T09:04:28+00:00" 881 | }, 882 | { 883 | "name": "sebastian/global-state", 884 | "version": "1.1.1", 885 | "source": { 886 | "type": "git", 887 | "url": "https://github.com/sebastianbergmann/global-state.git", 888 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 889 | }, 890 | "dist": { 891 | "type": "zip", 892 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 893 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 894 | "shasum": "" 895 | }, 896 | "require": { 897 | "php": ">=5.3.3" 898 | }, 899 | "require-dev": { 900 | "phpunit/phpunit": "~4.2" 901 | }, 902 | "suggest": { 903 | "ext-uopz": "*" 904 | }, 905 | "type": "library", 906 | "extra": { 907 | "branch-alias": { 908 | "dev-master": "1.0-dev" 909 | } 910 | }, 911 | "autoload": { 912 | "classmap": [ 913 | "src/" 914 | ] 915 | }, 916 | "notification-url": "https://packagist.org/downloads/", 917 | "license": [ 918 | "BSD-3-Clause" 919 | ], 920 | "authors": [ 921 | { 922 | "name": "Sebastian Bergmann", 923 | "email": "sebastian@phpunit.de" 924 | } 925 | ], 926 | "description": "Snapshotting of global state", 927 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 928 | "keywords": [ 929 | "global state" 930 | ], 931 | "time": "2015-10-12T03:26:01+00:00" 932 | }, 933 | { 934 | "name": "sebastian/recursion-context", 935 | "version": "1.0.5", 936 | "source": { 937 | "type": "git", 938 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 939 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" 940 | }, 941 | "dist": { 942 | "type": "zip", 943 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 944 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 945 | "shasum": "" 946 | }, 947 | "require": { 948 | "php": ">=5.3.3" 949 | }, 950 | "require-dev": { 951 | "phpunit/phpunit": "~4.4" 952 | }, 953 | "type": "library", 954 | "extra": { 955 | "branch-alias": { 956 | "dev-master": "1.0.x-dev" 957 | } 958 | }, 959 | "autoload": { 960 | "classmap": [ 961 | "src/" 962 | ] 963 | }, 964 | "notification-url": "https://packagist.org/downloads/", 965 | "license": [ 966 | "BSD-3-Clause" 967 | ], 968 | "authors": [ 969 | { 970 | "name": "Jeff Welch", 971 | "email": "whatthejeff@gmail.com" 972 | }, 973 | { 974 | "name": "Sebastian Bergmann", 975 | "email": "sebastian@phpunit.de" 976 | }, 977 | { 978 | "name": "Adam Harvey", 979 | "email": "aharvey@php.net" 980 | } 981 | ], 982 | "description": "Provides functionality to recursively process PHP variables", 983 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 984 | "time": "2016-10-03T07:41:43+00:00" 985 | }, 986 | { 987 | "name": "sebastian/version", 988 | "version": "1.0.6", 989 | "source": { 990 | "type": "git", 991 | "url": "https://github.com/sebastianbergmann/version.git", 992 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" 993 | }, 994 | "dist": { 995 | "type": "zip", 996 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 997 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 998 | "shasum": "" 999 | }, 1000 | "type": "library", 1001 | "autoload": { 1002 | "classmap": [ 1003 | "src/" 1004 | ] 1005 | }, 1006 | "notification-url": "https://packagist.org/downloads/", 1007 | "license": [ 1008 | "BSD-3-Clause" 1009 | ], 1010 | "authors": [ 1011 | { 1012 | "name": "Sebastian Bergmann", 1013 | "email": "sebastian@phpunit.de", 1014 | "role": "lead" 1015 | } 1016 | ], 1017 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1018 | "homepage": "https://github.com/sebastianbergmann/version", 1019 | "time": "2015-06-21T13:59:46+00:00" 1020 | }, 1021 | { 1022 | "name": "symfony/polyfill-ctype", 1023 | "version": "v1.10.0", 1024 | "source": { 1025 | "type": "git", 1026 | "url": "https://github.com/symfony/polyfill-ctype.git", 1027 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" 1028 | }, 1029 | "dist": { 1030 | "type": "zip", 1031 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", 1032 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", 1033 | "shasum": "" 1034 | }, 1035 | "require": { 1036 | "php": ">=5.3.3" 1037 | }, 1038 | "suggest": { 1039 | "ext-ctype": "For best performance" 1040 | }, 1041 | "type": "library", 1042 | "extra": { 1043 | "branch-alias": { 1044 | "dev-master": "1.9-dev" 1045 | } 1046 | }, 1047 | "autoload": { 1048 | "psr-4": { 1049 | "Symfony\\Polyfill\\Ctype\\": "" 1050 | }, 1051 | "files": [ 1052 | "bootstrap.php" 1053 | ] 1054 | }, 1055 | "notification-url": "https://packagist.org/downloads/", 1056 | "license": [ 1057 | "MIT" 1058 | ], 1059 | "authors": [ 1060 | { 1061 | "name": "Symfony Community", 1062 | "homepage": "https://symfony.com/contributors" 1063 | }, 1064 | { 1065 | "name": "Gert de Pagter", 1066 | "email": "BackEndTea@gmail.com" 1067 | } 1068 | ], 1069 | "description": "Symfony polyfill for ctype functions", 1070 | "homepage": "https://symfony.com", 1071 | "keywords": [ 1072 | "compatibility", 1073 | "ctype", 1074 | "polyfill", 1075 | "portable" 1076 | ], 1077 | "time": "2018-08-06T14:22:27+00:00" 1078 | }, 1079 | { 1080 | "name": "symfony/yaml", 1081 | "version": "v3.4.22", 1082 | "source": { 1083 | "type": "git", 1084 | "url": "https://github.com/symfony/yaml.git", 1085 | "reference": "ba11776e9e6c15ad5759a07bffb15899bac75c2d" 1086 | }, 1087 | "dist": { 1088 | "type": "zip", 1089 | "url": "https://api.github.com/repos/symfony/yaml/zipball/ba11776e9e6c15ad5759a07bffb15899bac75c2d", 1090 | "reference": "ba11776e9e6c15ad5759a07bffb15899bac75c2d", 1091 | "shasum": "" 1092 | }, 1093 | "require": { 1094 | "php": "^5.5.9|>=7.0.8", 1095 | "symfony/polyfill-ctype": "~1.8" 1096 | }, 1097 | "conflict": { 1098 | "symfony/console": "<3.4" 1099 | }, 1100 | "require-dev": { 1101 | "symfony/console": "~3.4|~4.0" 1102 | }, 1103 | "suggest": { 1104 | "symfony/console": "For validating YAML files using the lint command" 1105 | }, 1106 | "type": "library", 1107 | "extra": { 1108 | "branch-alias": { 1109 | "dev-master": "3.4-dev" 1110 | } 1111 | }, 1112 | "autoload": { 1113 | "psr-4": { 1114 | "Symfony\\Component\\Yaml\\": "" 1115 | }, 1116 | "exclude-from-classmap": [ 1117 | "/Tests/" 1118 | ] 1119 | }, 1120 | "notification-url": "https://packagist.org/downloads/", 1121 | "license": [ 1122 | "MIT" 1123 | ], 1124 | "authors": [ 1125 | { 1126 | "name": "Fabien Potencier", 1127 | "email": "fabien@symfony.com" 1128 | }, 1129 | { 1130 | "name": "Symfony Community", 1131 | "homepage": "https://symfony.com/contributors" 1132 | } 1133 | ], 1134 | "description": "Symfony Yaml Component", 1135 | "homepage": "https://symfony.com", 1136 | "time": "2019-01-16T10:59:17+00:00" 1137 | }, 1138 | { 1139 | "name": "webmozart/assert", 1140 | "version": "1.4.0", 1141 | "source": { 1142 | "type": "git", 1143 | "url": "https://github.com/webmozart/assert.git", 1144 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" 1145 | }, 1146 | "dist": { 1147 | "type": "zip", 1148 | "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", 1149 | "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", 1150 | "shasum": "" 1151 | }, 1152 | "require": { 1153 | "php": "^5.3.3 || ^7.0", 1154 | "symfony/polyfill-ctype": "^1.8" 1155 | }, 1156 | "require-dev": { 1157 | "phpunit/phpunit": "^4.6", 1158 | "sebastian/version": "^1.0.1" 1159 | }, 1160 | "type": "library", 1161 | "extra": { 1162 | "branch-alias": { 1163 | "dev-master": "1.3-dev" 1164 | } 1165 | }, 1166 | "autoload": { 1167 | "psr-4": { 1168 | "Webmozart\\Assert\\": "src/" 1169 | } 1170 | }, 1171 | "notification-url": "https://packagist.org/downloads/", 1172 | "license": [ 1173 | "MIT" 1174 | ], 1175 | "authors": [ 1176 | { 1177 | "name": "Bernhard Schussek", 1178 | "email": "bschussek@gmail.com" 1179 | } 1180 | ], 1181 | "description": "Assertions to validate method input/output with nice error messages.", 1182 | "keywords": [ 1183 | "assert", 1184 | "check", 1185 | "validate" 1186 | ], 1187 | "time": "2018-12-25T11:19:39+00:00" 1188 | } 1189 | ], 1190 | "aliases": [], 1191 | "minimum-stability": "stable", 1192 | "stability-flags": [], 1193 | "prefer-stable": false, 1194 | "prefer-lowest": false, 1195 | "platform": { 1196 | "php": ">=5.4.0" 1197 | }, 1198 | "platform-dev": [] 1199 | } 1200 | --------------------------------------------------------------------------------