Chris@12: message`,
Chris@12: * `message`)
Chris@12: * - Write output to a specified stream, optionally with colorization.
Chris@12: * - Write a line of output to a specified stream, optionally with
Chris@12: * colorization, using the system EOL sequence..
Chris@12: * - Write an error message to STDERR.
Chris@12: *
Chris@12: * Colorization will only occur when expected sequences are discovered, and
Chris@12: * then, only if the console terminal allows it.
Chris@12: *
Chris@12: * Essentially, provides the bare minimum to allow you to provide messages to
Chris@12: * the current console.
Chris@12: */
Chris@12: class ConsoleHelper
Chris@12: {
Chris@12: const COLOR_GREEN = "\033[32m";
Chris@12: const COLOR_RED = "\033[31m";
Chris@12: const COLOR_RESET = "\033[0m";
Chris@12:
Chris@12: const HIGHLIGHT_INFO = 'info';
Chris@12: const HIGHLIGHT_ERROR = 'error';
Chris@12:
Chris@12: private $highlightMap = [
Chris@12: self::HIGHLIGHT_INFO => self::COLOR_GREEN,
Chris@12: self::HIGHLIGHT_ERROR => self::COLOR_RED,
Chris@12: ];
Chris@12:
Chris@12: /**
Chris@12: * @var string Exists only for testing.
Chris@12: */
Chris@12: private $eol = PHP_EOL;
Chris@12:
Chris@12: /**
Chris@12: * @var resource Exists only for testing.
Chris@12: */
Chris@12: private $stderr = STDERR;
Chris@12:
Chris@12: /**
Chris@12: * @var bool
Chris@12: */
Chris@12: private $supportsColor;
Chris@12:
Chris@12: /**
Chris@12: * @param resource $resource
Chris@12: */
Chris@12: public function __construct($resource = STDOUT)
Chris@12: {
Chris@12: $this->supportsColor = $this->detectColorCapabilities($resource);
Chris@12: }
Chris@12:
Chris@12: /**
Chris@12: * Colorize a string for use with the terminal.
Chris@12: *
Chris@12: * Takes strings formatted as `string` and formats them per the
Chris@12: * $highlightMap; if color support is disabled, simply removes the formatting
Chris@12: * tags.
Chris@12: *
Chris@12: * @param string $string
Chris@12: * @return string
Chris@12: */
Chris@12: public function colorize($string)
Chris@12: {
Chris@12: $reset = $this->supportsColor ? self::COLOR_RESET : '';
Chris@12: foreach ($this->highlightMap as $key => $color) {
Chris@12: $pattern = sprintf('#<%s>(.*?)%s>#s', $key, $key);
Chris@12: $color = $this->supportsColor ? $color : '';
Chris@12: $string = preg_replace($pattern, $color . '$1' . $reset, $string);
Chris@12: }
Chris@12: return $string;
Chris@12: }
Chris@12:
Chris@12: /**
Chris@12: * @param string $string
Chris@12: * @param bool $colorize Whether or not to colorize the string
Chris@12: * @param resource $resource Defaults to STDOUT
Chris@12: * @return void
Chris@12: */
Chris@12: public function write($string, $colorize = true, $resource = STDOUT)
Chris@12: {
Chris@12: if ($colorize) {
Chris@12: $string = $this->colorize($string);
Chris@12: }
Chris@12:
Chris@12: $string = $this->formatNewlines($string);
Chris@12:
Chris@12: fwrite($resource, $string);
Chris@12: }
Chris@12:
Chris@12: /**
Chris@12: * @param string $string
Chris@12: * @param bool $colorize Whether or not to colorize the line
Chris@12: * @param resource $resource Defaults to STDOUT
Chris@12: * @return void
Chris@12: */
Chris@12: public function writeLine($string, $colorize = true, $resource = STDOUT)
Chris@12: {
Chris@12: $this->write($string . $this->eol, $colorize, $resource);
Chris@12: }
Chris@12:
Chris@12: /**
Chris@12: * Emit an error message.
Chris@12: *
Chris@12: * Wraps the message in ``, and passes it to `writeLine()`,
Chris@12: * using STDERR as the resource; emits an additional empty line when done,
Chris@12: * also to STDERR.
Chris@12: *
Chris@12: * @param string $message
Chris@12: * @return void
Chris@12: */
Chris@12: public function writeErrorMessage($message)
Chris@12: {
Chris@12: $this->writeLine(sprintf('%s', $message), true, $this->stderr);
Chris@12: $this->writeLine('', false, $this->stderr);
Chris@12: }
Chris@12:
Chris@12: /**
Chris@12: * @param resource $resource
Chris@12: * @return bool
Chris@12: */
Chris@12: private function detectColorCapabilities($resource = STDOUT)
Chris@12: {
Chris@12: if ('\\' === DIRECTORY_SEPARATOR) {
Chris@12: // Windows
Chris@12: return false !== getenv('ANSICON')
Chris@12: || 'ON' === getenv('ConEmuANSI')
Chris@12: || 'xterm' === getenv('TERM');
Chris@12: }
Chris@12:
Chris@12: return function_exists('posix_isatty') && posix_isatty($resource);
Chris@12: }
Chris@12:
Chris@12: /**
Chris@12: * Ensure newlines are appropriate for the current terminal.
Chris@12: *
Chris@12: * @param string
Chris@12: * @return string
Chris@12: */
Chris@12: private function formatNewlines($string)
Chris@12: {
Chris@12: $string = str_replace($this->eol, "\0PHP_EOL\0", $string);
Chris@12: $string = preg_replace("/(\r\n|\n|\r)/", $this->eol, $string);
Chris@12: return str_replace("\0PHP_EOL\0", $this->eol, $string);
Chris@12: }
Chris@12: }