Console.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <?php
  2. /*
  3. * This file is part of the Environment package.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace SebastianBergmann\Environment;
  11. /**
  12. */
  13. class Console
  14. {
  15. const STDIN = 0;
  16. const STDOUT = 1;
  17. const STDERR = 2;
  18. /**
  19. * Returns true if STDOUT supports colorization.
  20. *
  21. * This code has been copied and adapted from
  22. * Symfony\Component\Console\Output\OutputStream.
  23. *
  24. * @return bool
  25. */
  26. public function hasColorSupport()
  27. {
  28. if (DIRECTORY_SEPARATOR == '\\') {
  29. return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM');
  30. }
  31. if (!defined('STDOUT')) {
  32. return false;
  33. }
  34. return $this->isInteractive(STDOUT);
  35. }
  36. /**
  37. * Returns the number of columns of the terminal.
  38. *
  39. * @return int
  40. */
  41. public function getNumberOfColumns()
  42. {
  43. if (DIRECTORY_SEPARATOR == '\\') {
  44. $columns = 80;
  45. if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
  46. $columns = $matches[1];
  47. } elseif (function_exists('proc_open')) {
  48. $process = proc_open(
  49. 'mode CON',
  50. [
  51. 1 => ['pipe', 'w'],
  52. 2 => ['pipe', 'w']
  53. ],
  54. $pipes,
  55. null,
  56. null,
  57. ['suppress_errors' => true]
  58. );
  59. if (is_resource($process)) {
  60. $info = stream_get_contents($pipes[1]);
  61. fclose($pipes[1]);
  62. fclose($pipes[2]);
  63. proc_close($process);
  64. if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
  65. $columns = $matches[2];
  66. }
  67. }
  68. }
  69. return $columns - 1;
  70. }
  71. if (!$this->isInteractive(self::STDIN)) {
  72. return 80;
  73. }
  74. if (function_exists('shell_exec') && preg_match('#\d+ (\d+)#', shell_exec('stty size'), $match) === 1) {
  75. if ((int) $match[1] > 0) {
  76. return (int) $match[1];
  77. }
  78. }
  79. if (function_exists('shell_exec') && preg_match('#columns = (\d+);#', shell_exec('stty'), $match) === 1) {
  80. if ((int) $match[1] > 0) {
  81. return (int) $match[1];
  82. }
  83. }
  84. return 80;
  85. }
  86. /**
  87. * Returns if the file descriptor is an interactive terminal or not.
  88. *
  89. * @param int|resource $fileDescriptor
  90. *
  91. * @return bool
  92. */
  93. public function isInteractive($fileDescriptor = self::STDOUT)
  94. {
  95. return function_exists('posix_isatty') && @posix_isatty($fileDescriptor);
  96. }
  97. }