2 namespace JakubOnderka\PhpConsoleColor;
9 const COLOR256_REGEXP = '~^(bg_)?color_([0-9]{1,3})$~';
11 const RESET_STYLE = 0;
17 private $forceStyle = false;
20 private $styles = array(
42 'light_green' => '92',
43 'light_yellow' => '93',
45 'light_magenta' => '95',
57 'bg_light_gray' => '47',
59 'bg_dark_gray' => '100',
60 'bg_light_red' => '101',
61 'bg_light_green' => '102',
62 'bg_light_yellow' => '103',
63 'bg_light_blue' => '104',
64 'bg_light_magenta' => '105',
65 'bg_light_cyan' => '106',
70 private $themes = array();
72 public function __construct()
74 $this->isSupported = $this->isSupported();
78 * @param string|array $style
81 * @throws InvalidStyleException
82 * @throws \InvalidArgumentException
84 public function apply($style, $text)
86 if (!$this->isStyleForced() && !$this->isSupported()) {
90 if (is_string($style)) {
91 $style = array($style);
93 if (!is_array($style)) {
94 throw new \InvalidArgumentException("Style must be string or array.");
99 foreach ($style as $s) {
100 if (isset($this->themes[$s])) {
101 $sequences = array_merge($sequences, $this->themeSequence($s));
102 } else if ($this->isValidStyle($s)) {
103 $sequences[] = $this->styleSequence($s);
105 throw new InvalidStyleException($s);
109 $sequences = array_filter($sequences, function ($val) {
110 return $val !== null;
113 if (empty($sequences)) {
117 return $this->escSequence(implode(';', $sequences)) . $text . $this->escSequence(self::RESET_STYLE);
121 * @param bool $forceStyle
123 public function setForceStyle($forceStyle)
125 $this->forceStyle = (bool) $forceStyle;
131 public function isStyleForced()
133 return $this->forceStyle;
137 * @param array $themes
138 * @throws InvalidStyleException
139 * @throws \InvalidArgumentException
141 public function setThemes(array $themes)
143 $this->themes = array();
144 foreach ($themes as $name => $styles) {
145 $this->addTheme($name, $styles);
150 * @param string $name
151 * @param array|string $styles
152 * @throws \InvalidArgumentException
153 * @throws InvalidStyleException
155 public function addTheme($name, $styles)
157 if (is_string($styles)) {
158 $styles = array($styles);
160 if (!is_array($styles)) {
161 throw new \InvalidArgumentException("Style must be string or array.");
164 foreach ($styles as $style) {
165 if (!$this->isValidStyle($style)) {
166 throw new InvalidStyleException($style);
170 $this->themes[$name] = $styles;
176 public function getThemes()
178 return $this->themes;
182 * @param string $name
185 public function hasTheme($name)
187 return isset($this->themes[$name]);
191 * @param string $name
193 public function removeTheme($name)
195 unset($this->themes[$name]);
201 public function isSupported()
203 if (DIRECTORY_SEPARATOR === '\\') {
204 if (function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support(STDOUT)) {
206 } elseif (getenv('ANSICON') !== false || getenv('ConEmuANSI') === 'ON') {
211 return function_exists('posix_isatty') && @posix_isatty(STDOUT);
218 public function are256ColorsSupported()
220 if (DIRECTORY_SEPARATOR === '\\') {
221 return function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support(STDOUT);
223 return strpos(getenv('TERM'), '256color') !== false;
230 public function getPossibleStyles()
232 return array_keys($this->styles);
236 * @param string $name
239 private function themeSequence($name)
241 $sequences = array();
242 foreach ($this->themes[$name] as $style) {
243 $sequences[] = $this->styleSequence($style);
249 * @param string $style
252 private function styleSequence($style)
254 if (array_key_exists($style, $this->styles)) {
255 return $this->styles[$style];
258 if (!$this->are256ColorsSupported()) {
262 preg_match(self::COLOR256_REGEXP, $style, $matches);
264 $type = $matches[1] === 'bg_' ? self::BACKGROUND : self::FOREGROUND;
265 $value = $matches[2];
267 return "$type;5;$value";
271 * @param string $style
274 private function isValidStyle($style)
276 return array_key_exists($style, $this->styles) || preg_match(self::COLOR256_REGEXP, $style);
280 * @param string|int $value
283 private function escSequence($value)
285 return "\033[{$value}m";