Skip to content

Commit a7a0ca2

Browse files
committed
feat: add highlighter
1 parent c2c8808 commit a7a0ca2

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

src/Highlighter.php

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
namespace Ahc\CliSyntax;
4+
5+
class Highlighter
6+
{
7+
/** @var string The PHP code. */
8+
protected $code;
9+
10+
/** @var bool Indicates if it has been already configured. */
11+
protected static $configured;
12+
13+
public function __construct(string $code)
14+
{
15+
$this->code = $code;
16+
}
17+
18+
public function __toString(): string
19+
{
20+
return $this->highlight();
21+
}
22+
23+
public static function for(string $file): self
24+
{
25+
if (!\is_file($file)) {
26+
throw new \InvalidArgumentException('The given file doesnot exist or is unreadable.');
27+
}
28+
29+
return new static(\file_get_contents($file));
30+
}
31+
32+
public function highlight(): string
33+
{
34+
static::configure();
35+
36+
$html = \highlight_string($this->code, true);
37+
$html = \str_replace(['<br />', '<br/>', '<br>'], "\n", $html);
38+
39+
return $this->parse($html);
40+
}
41+
42+
public function configure()
43+
{
44+
if (static::$configured) {
45+
return;
46+
}
47+
48+
foreach (['comment', 'default', 'html', 'keyword', 'string'] as $type) {
49+
\ini_set("highlight.$type", \ini_get("highlight.$type") . \sprintf('" data-type="%s', $type));
50+
}
51+
52+
static::$configured = true;
53+
}
54+
55+
protected function parse(string $html): string
56+
{
57+
$str = '';
58+
$dom = new \DOMDocument;
59+
60+
$dom->loadHTML($html);
61+
foreach ($dom->getElementsByTagName('span') as $el) {
62+
$str .= $this->visit($el);
63+
}
64+
65+
return $str;
66+
}
67+
68+
protected function visit(\DOMElement $el): string
69+
{
70+
if ('html' === $type = $el->getAttribute('data-type')) {
71+
return '';
72+
}
73+
74+
$text = $el->textContent;
75+
76+
$text = \str_replace(['&nbsp;', '&lt;', '&gt;'], [' ', '<', '>'], $text);
77+
78+
return $this->format($text, $type);
79+
}
80+
81+
protected function format(string $text, string $type): string
82+
{
83+
static $formats = [
84+
'comment' => "\033[1;30;40m%s\033[0m",
85+
'default' => "\033[0;32;40m%s\033[0m",
86+
'keyword' => "\033[0;36;40m%s\033[0m",
87+
'string' => "\033[0;33;40m%s\033[0m",
88+
];
89+
90+
return \sprintf($formats[$type] ?? '%s', $text);
91+
}
92+
}

0 commit comments

Comments
 (0)