Skip to content

Commit 3242c2f

Browse files
authored
Merge pull request #201 from DorZuberi/add-terminal-support
2 parents 03276a5 + 1cee7fc commit 3242c2f

7 files changed

Lines changed: 213 additions & 0 deletions

File tree

src/Highlighter.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Tempest\Highlight\Languages\Python\PythonLanguage;
2525
use Tempest\Highlight\Languages\Scss\ScssLanguage;
2626
use Tempest\Highlight\Languages\Sql\SqlLanguage;
27+
use Tempest\Highlight\Languages\Terminal\TerminalLanguage;
2728
use Tempest\Highlight\Languages\Text\TextLanguage;
2829
use Tempest\Highlight\Languages\Twig\TwigLanguage;
2930
use Tempest\Highlight\Languages\Xml\XmlLanguage;
@@ -69,6 +70,7 @@ public function __construct(private readonly Theme $theme = new CssTheme())
6970
->addLanguage(new PythonLanguage())
7071
->addLanguage(new ScssLanguage())
7172
->addLanguage(new SqlLanguage())
73+
->addLanguage(new TerminalLanguage())
7274
->addLanguage(new XmlLanguage())
7375
->addLanguage(new YamlLanguage())
7476
->addLanguage(new DotEnvLanguage())
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Terminal\Patterns;
6+
7+
use Tempest\Highlight\IsPattern;
8+
use Tempest\Highlight\Pattern;
9+
use Tempest\Highlight\PatternTest;
10+
use Tempest\Highlight\Tokens\TokenTypeEnum;
11+
12+
#[PatternTest(input: '$ npm install express', output: 'npm')]
13+
#[PatternTest(input: '# docker ps -a', output: 'docker')]
14+
#[PatternTest(input: '$ ./configure', output: './configure')]
15+
final readonly class TerminalCommandNamePattern implements Pattern
16+
{
17+
use IsPattern;
18+
19+
public function getPattern(): string
20+
{
21+
return '/^[\$#%>]\s+(?<match>[\w.\/-][\w.\/-]*)(?=\s|$)/m';
22+
}
23+
24+
public function getTokenType(): TokenTypeEnum
25+
{
26+
return TokenTypeEnum::KEYWORD;
27+
}
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Terminal\Patterns;
6+
7+
use Tempest\Highlight\IsPattern;
8+
use Tempest\Highlight\Pattern;
9+
use Tempest\Highlight\PatternTest;
10+
use Tempest\Highlight\Tokens\TokenTypeEnum;
11+
12+
#[PatternTest(input: '$ npm install', output: '$')]
13+
#[PatternTest(input: '# apt update', output: '#')]
14+
#[PatternTest(input: '% brew install', output: '%')]
15+
#[PatternTest(input: '> command', output: '>')]
16+
final readonly class TerminalPromptPattern implements Pattern
17+
{
18+
use IsPattern;
19+
20+
public function getPattern(): string
21+
{
22+
return '/^(?<match>[\$#%>])(?=\s)/m';
23+
}
24+
25+
public function getTokenType(): TokenTypeEnum
26+
{
27+
return TokenTypeEnum::COMMENT;
28+
}
29+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Terminal;
6+
7+
use Override;
8+
use Tempest\Highlight\Languages\Base\BaseLanguage;
9+
use Tempest\Highlight\Languages\Bash\Patterns\BashFlagPattern;
10+
use Tempest\Highlight\Languages\Bash\Patterns\BashNumberPattern;
11+
use Tempest\Highlight\Languages\Bash\Patterns\BashOperatorPattern;
12+
use Tempest\Highlight\Languages\Bash\Patterns\BashVariablePattern;
13+
use Tempest\Highlight\Languages\Php\Patterns\DoubleQuoteValuePattern;
14+
use Tempest\Highlight\Languages\Php\Patterns\SingleQuoteValuePattern;
15+
use Tempest\Highlight\Languages\Terminal\Patterns\TerminalCommandNamePattern;
16+
use Tempest\Highlight\Languages\Terminal\Patterns\TerminalPromptPattern;
17+
18+
class TerminalLanguage extends BaseLanguage
19+
{
20+
public function getName(): string
21+
{
22+
return 'terminal';
23+
}
24+
25+
#[Override]
26+
public function getAliases(): array
27+
{
28+
return ['console', 'term'];
29+
}
30+
31+
#[Override]
32+
public function getPatterns(): array
33+
{
34+
return [
35+
...parent::getPatterns(),
36+
37+
// PROMPT
38+
new TerminalPromptPattern(),
39+
40+
// VALUES
41+
new SingleQuoteValuePattern(),
42+
new DoubleQuoteValuePattern(),
43+
44+
// COMMAND NAME
45+
new TerminalCommandNamePattern(),
46+
47+
// VARIABLES
48+
new BashVariablePattern(),
49+
50+
// OPERATORS
51+
new BashOperatorPattern(),
52+
53+
// NUMBERS
54+
new BashNumberPattern(),
55+
56+
// FLAGS
57+
new BashFlagPattern(),
58+
];
59+
}
60+
}

tests/Bench/Fixtures/terminal.txt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
$ npm install --save express
2+
added 57 packages in 3s
3+
4+
$ git status
5+
On branch main
6+
Your branch is up to date with 'origin/main'.
7+
8+
nothing to commit, working tree clean
9+
10+
$ docker ps -a
11+
CONTAINER ID IMAGE STATUS
12+
abc123 nginx:latest Up 2 hours
13+
def456 redis:7 Exited (0) 3 days ago
14+
15+
# apt update && apt install -y curl wget
16+
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
17+
Reading package lists... Done
18+
19+
$ echo "Hello $USER, today is $(date)"
20+
Hello john, today is Mon Apr 1 10:00:00 UTC 2026
21+
22+
$ cat /etc/hosts | grep -i 'localhost'
23+
127.0.0.1 localhost
24+
25+
% brew install --cask visual-studio-code
26+
==> Downloading https://update.code.visualstudio.com
27+
Already downloaded: /Users/john/Library/Caches/Homebrew
28+
29+
> node -v
30+
v20.11.0
31+
32+
$ ls -la /var/log/*.log
33+
-rw-r--r-- 1 root root 45231 Apr 1 09:00 /var/log/syslog.log
34+
35+
$ kubectl get pods -n production --output=wide
36+
NAME READY STATUS RESTARTS AGE
37+
api-7d4b8c6f9-x2k4m 1/1 Running 0 24h
38+
web-5f6a7b8c9-m3n5p 1/1 Running 0 24h

tests/Bench/HighlighterBench.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ final class HighlighterBench
3434
'python' => 'python.txt',
3535
'scss' => 'scss.txt',
3636
'sql' => 'sql.txt',
37+
'terminal' => 'terminal.txt',
3738
'twig' => 'twig.txt',
3839
'xml' => 'xml.txt',
3940
'yaml' => 'yaml.txt',
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Tests\Languages\Terminal;
6+
7+
use PHPUnit\Framework\Attributes\DataProvider;
8+
use PHPUnit\Framework\TestCase;
9+
use Tempest\Highlight\Highlighter;
10+
11+
class TerminalLanguageTest extends TestCase
12+
{
13+
#[DataProvider('provide_highlight_cases')]
14+
public function test_highlight(string $content, string $expected): void
15+
{
16+
$highlighter = new Highlighter();
17+
18+
$this->assertSame(
19+
$expected,
20+
$highlighter->parse($content, 'terminal'),
21+
);
22+
23+
$this->assertSame(
24+
$expected,
25+
$highlighter->parse($content, 'console'),
26+
);
27+
28+
$this->assertSame(
29+
$expected,
30+
$highlighter->parse($content, 'term'),
31+
);
32+
}
33+
34+
public static function provide_highlight_cases(): iterable
35+
{
36+
return [
37+
[<<<'TXT'
38+
$ npm install --save express
39+
added 57 packages
40+
$ echo "Hello $USER"
41+
Hello john
42+
# docker ps -a
43+
CONTAINER ID IMAGE STATUS
44+
TXT,
45+
<<<'TXT'
46+
<span class="hl-comment">$</span> <span class="hl-keyword">npm</span> install <span class="hl-generic">--save</span> express
47+
added <span class="hl-number">57</span> packages
48+
<span class="hl-comment">$</span> <span class="hl-keyword">echo</span> <span class="hl-value">&quot;Hello $USER&quot;</span>
49+
Hello john
50+
<span class="hl-comment">#</span> <span class="hl-keyword">docker</span> ps <span class="hl-generic">-a</span>
51+
CONTAINER ID IMAGE STATUS
52+
TXT],
53+
];
54+
}
55+
}

0 commit comments

Comments
 (0)