annotate vendor/sebastian/environment/src/Console.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 1fec387a4317
children
rev   line source
Chris@0 1 <?php
Chris@0 2 /*
Chris@14 3 * This file is part of sebastian/environment.
Chris@0 4 *
Chris@0 5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
Chris@0 6 *
Chris@0 7 * For the full copyright and license information, please view the LICENSE
Chris@0 8 * file that was distributed with this source code.
Chris@0 9 */
Chris@0 10
Chris@14 11 declare(strict_types=1);
Chris@14 12
Chris@0 13 namespace SebastianBergmann\Environment;
Chris@0 14
Chris@14 15 final class Console
Chris@0 16 {
Chris@14 17 /**
Chris@14 18 * @var int
Chris@14 19 */
Chris@0 20 const STDIN = 0;
Chris@14 21
Chris@14 22 /**
Chris@14 23 * @var int
Chris@14 24 */
Chris@0 25 const STDOUT = 1;
Chris@14 26
Chris@14 27 /**
Chris@14 28 * @var int
Chris@14 29 */
Chris@0 30 const STDERR = 2;
Chris@0 31
Chris@0 32 /**
Chris@0 33 * Returns true if STDOUT supports colorization.
Chris@0 34 *
Chris@0 35 * This code has been copied and adapted from
Chris@0 36 * Symfony\Component\Console\Output\OutputStream.
Chris@0 37 */
Chris@14 38 public function hasColorSupport(): bool
Chris@0 39 {
Chris@14 40 if ($this->isWindows()) {
Chris@14 41 // @codeCoverageIgnoreStart
Chris@14 42 return false !== \getenv('ANSICON') || 'ON' === \getenv('ConEmuANSI') || 'xterm' === \getenv('TERM');
Chris@14 43 // @codeCoverageIgnoreEnd
Chris@0 44 }
Chris@0 45
Chris@14 46 if (!\defined('STDOUT')) {
Chris@14 47 // @codeCoverageIgnoreStart
Chris@0 48 return false;
Chris@14 49 // @codeCoverageIgnoreEnd
Chris@0 50 }
Chris@0 51
Chris@0 52 return $this->isInteractive(STDOUT);
Chris@0 53 }
Chris@0 54
Chris@0 55 /**
Chris@0 56 * Returns the number of columns of the terminal.
Chris@0 57 *
Chris@14 58 * @codeCoverageIgnore
Chris@0 59 */
Chris@14 60 public function getNumberOfColumns(): int
Chris@0 61 {
Chris@14 62 if ($this->isWindows()) {
Chris@14 63 return $this->getNumberOfColumnsWindows();
Chris@0 64 }
Chris@0 65
Chris@0 66 if (!$this->isInteractive(self::STDIN)) {
Chris@0 67 return 80;
Chris@0 68 }
Chris@0 69
Chris@14 70 return $this->getNumberOfColumnsInteractive();
Chris@14 71 }
Chris@14 72
Chris@14 73 /**
Chris@14 74 * Returns if the file descriptor is an interactive terminal or not.
Chris@14 75 *
Chris@14 76 * @param int|resource $fileDescriptor
Chris@14 77 */
Chris@14 78 public function isInteractive($fileDescriptor = self::STDOUT): bool
Chris@14 79 {
Chris@14 80 return \function_exists('posix_isatty') && @\posix_isatty($fileDescriptor);
Chris@14 81 }
Chris@14 82
Chris@14 83 private function isWindows(): bool
Chris@14 84 {
Chris@14 85 return DIRECTORY_SEPARATOR === '\\';
Chris@14 86 }
Chris@14 87
Chris@14 88 /**
Chris@14 89 * @codeCoverageIgnore
Chris@14 90 */
Chris@14 91 private function getNumberOfColumnsInteractive(): int
Chris@14 92 {
Chris@14 93 if (\function_exists('shell_exec') && \preg_match('#\d+ (\d+)#', \shell_exec('stty size') ?? '', $match) === 1) {
Chris@0 94 if ((int) $match[1] > 0) {
Chris@0 95 return (int) $match[1];
Chris@0 96 }
Chris@0 97 }
Chris@0 98
Chris@14 99 if (\function_exists('shell_exec') && \preg_match('#columns = (\d+);#', \shell_exec('stty') ?? '', $match) === 1) {
Chris@0 100 if ((int) $match[1] > 0) {
Chris@0 101 return (int) $match[1];
Chris@0 102 }
Chris@0 103 }
Chris@0 104
Chris@0 105 return 80;
Chris@0 106 }
Chris@0 107
Chris@0 108 /**
Chris@14 109 * @codeCoverageIgnore
Chris@0 110 */
Chris@14 111 private function getNumberOfColumnsWindows(): int
Chris@0 112 {
Chris@14 113 $ansicon = \getenv('ANSICON');
Chris@14 114 $columns = 80;
Chris@14 115
Chris@14 116 if (\is_string($ansicon) && \preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', \trim($ansicon), $matches)) {
Chris@14 117 $columns = $matches[1];
Chris@14 118 } elseif (\function_exists('proc_open')) {
Chris@14 119 $process = \proc_open(
Chris@14 120 'mode CON',
Chris@14 121 [
Chris@14 122 1 => ['pipe', 'w'],
Chris@14 123 2 => ['pipe', 'w']
Chris@14 124 ],
Chris@14 125 $pipes,
Chris@14 126 null,
Chris@14 127 null,
Chris@14 128 ['suppress_errors' => true]
Chris@14 129 );
Chris@14 130
Chris@14 131 if (\is_resource($process)) {
Chris@14 132 $info = \stream_get_contents($pipes[1]);
Chris@14 133
Chris@14 134 \fclose($pipes[1]);
Chris@14 135 \fclose($pipes[2]);
Chris@14 136 \proc_close($process);
Chris@14 137
Chris@14 138 if (\preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
Chris@14 139 $columns = $matches[2];
Chris@14 140 }
Chris@14 141 }
Chris@14 142 }
Chris@14 143
Chris@14 144 return $columns - 1;
Chris@0 145 }
Chris@0 146 }