Skip to content

Commit 25b57d6

Browse files
authored
Merge pull request #199 from DorZuberi/add-bash-language
2 parents 8e4a11a + 8d83609 commit 25b57d6

13 files changed

Lines changed: 435 additions & 1 deletion

src/Highlighter.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use ReflectionClass;
88
use Tempest\Highlight\Languages\Base\Injections\GutterInjection;
9+
use Tempest\Highlight\Languages\Bash\BashLanguage;
910
use Tempest\Highlight\Languages\Blade\BladeLanguage;
1011
use Tempest\Highlight\Languages\Css\CssLanguage;
1112
use Tempest\Highlight\Languages\Diff\DiffLanguage;
@@ -51,7 +52,8 @@ final class Highlighter
5152

5253
public function __construct(private readonly Theme $theme = new CssTheme())
5354
{
54-
$this->addLanguage(new BladeLanguage())
55+
$this->addLanguage(new BashLanguage())
56+
->addLanguage(new BladeLanguage())
5557
->addLanguage(new CssLanguage())
5658
->addLanguage(new DiffLanguage())
5759
->addLanguage(new DocCommentLanguage())
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Bash;
6+
7+
use Override;
8+
use Tempest\Highlight\Languages\Base\BaseLanguage;
9+
use Tempest\Highlight\Languages\Bash\Patterns\BashBuiltinPattern;
10+
use Tempest\Highlight\Languages\Bash\Patterns\BashCommentPattern;
11+
use Tempest\Highlight\Languages\Bash\Patterns\BashFlagPattern;
12+
use Tempest\Highlight\Languages\Bash\Patterns\BashKeywordPattern;
13+
use Tempest\Highlight\Languages\Bash\Patterns\BashNumberPattern;
14+
use Tempest\Highlight\Languages\Bash\Patterns\BashOperatorPattern;
15+
use Tempest\Highlight\Languages\Bash\Patterns\BashShebangPattern;
16+
use Tempest\Highlight\Languages\Bash\Patterns\BashVariablePattern;
17+
use Tempest\Highlight\Languages\Php\Patterns\DoubleQuoteValuePattern;
18+
use Tempest\Highlight\Languages\Php\Patterns\SingleQuoteValuePattern;
19+
20+
class BashLanguage extends BaseLanguage
21+
{
22+
public function getName(): string
23+
{
24+
return 'bash';
25+
}
26+
27+
#[Override]
28+
public function getAliases(): array
29+
{
30+
return ['sh', 'shell'];
31+
}
32+
33+
#[Override]
34+
public function getInjections(): array
35+
{
36+
return [
37+
...parent::getInjections(),
38+
];
39+
}
40+
41+
#[Override]
42+
public function getPatterns(): array
43+
{
44+
return [
45+
...parent::getPatterns(),
46+
47+
// COMMENTS
48+
new BashShebangPattern(),
49+
new BashCommentPattern(),
50+
51+
// VALUES
52+
new SingleQuoteValuePattern(),
53+
new DoubleQuoteValuePattern(),
54+
55+
// KEYWORDS
56+
new BashKeywordPattern(),
57+
new BashBuiltinPattern(),
58+
59+
// VARIABLES
60+
new BashVariablePattern(),
61+
62+
// OPERATORS
63+
new BashOperatorPattern(),
64+
65+
// NUMBERS
66+
new BashNumberPattern(),
67+
68+
// FLAGS
69+
new BashFlagPattern(),
70+
];
71+
}
72+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Bash\Patterns;
6+
7+
use Tempest\Highlight\IsPattern;
8+
use Tempest\Highlight\Pattern;
9+
use Tempest\Highlight\Tokens\TokenTypeEnum;
10+
11+
final readonly class BashBuiltinPattern implements Pattern
12+
{
13+
use IsPattern;
14+
15+
public function __construct(private array $builtins = [
16+
'echo', 'printf', 'cd', 'pwd', 'test', 'eval', 'exec',
17+
'set', 'read', 'exit',
18+
])
19+
{
20+
}
21+
22+
public function getPattern(): string
23+
{
24+
$builtins = implode('|', $this->builtins);
25+
26+
return "\b(?<match>(?:{$builtins}))\b";
27+
}
28+
29+
public function getTokenType(): TokenTypeEnum
30+
{
31+
return TokenTypeEnum::TYPE;
32+
}
33+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Bash\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: '# this is a comment', output: '# this is a comment')]
13+
final readonly class BashCommentPattern implements Pattern
14+
{
15+
use IsPattern;
16+
17+
public function getPattern(): string
18+
{
19+
return '(^|[^\\\\])(?<match>#.*)';
20+
}
21+
22+
public function getTokenType(): TokenTypeEnum
23+
{
24+
return TokenTypeEnum::COMMENT;
25+
}
26+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Bash\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: 'ls -la', output: '-la')]
13+
#[PatternTest(input: 'grep --color=auto', output: '--color')]
14+
final readonly class BashFlagPattern implements Pattern
15+
{
16+
use IsPattern;
17+
18+
public function getPattern(): string
19+
{
20+
return '(?<match>--?[a-zA-Z][\w-]*)';
21+
}
22+
23+
public function getTokenType(): TokenTypeEnum
24+
{
25+
return TokenTypeEnum::GENERIC;
26+
}
27+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Bash\Patterns;
6+
7+
use Tempest\Highlight\IsPattern;
8+
use Tempest\Highlight\Pattern;
9+
use Tempest\Highlight\Tokens\TokenTypeEnum;
10+
11+
final readonly class BashKeywordPattern implements Pattern
12+
{
13+
use IsPattern;
14+
15+
public function __construct(private array $keywords = [
16+
'if', 'then', 'else', 'elif', 'fi', 'for', 'while', 'do', 'done',
17+
'case', 'esac', 'function', 'return', 'in', 'select', 'until',
18+
'break', 'continue', 'declare', 'local', 'export', 'readonly',
19+
'unset', 'shift', 'trap', 'source',
20+
])
21+
{
22+
}
23+
24+
public function getPattern(): string
25+
{
26+
$keywords = implode('|', $this->keywords);
27+
28+
return "\b(?<match>(?:{$keywords}))\b";
29+
}
30+
31+
public function getTokenType(): TokenTypeEnum
32+
{
33+
return TokenTypeEnum::KEYWORD;
34+
}
35+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Bash\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: 'exit 0', output: '0')]
13+
final readonly class BashNumberPattern implements Pattern
14+
{
15+
use IsPattern;
16+
17+
public function getPattern(): string
18+
{
19+
return '\b(?<match>\d+)\b';
20+
}
21+
22+
public function getTokenType(): TokenTypeEnum
23+
{
24+
return TokenTypeEnum::NUMBER;
25+
}
26+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Bash\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: 'cmd1 | cmd2', output: '|')]
13+
#[PatternTest(input: 'cmd1 && cmd2', output: '&&')]
14+
final readonly class BashOperatorPattern implements Pattern
15+
{
16+
use IsPattern;
17+
18+
public function getPattern(): string
19+
{
20+
return '(?<match>\|\||&&|>>|<<|;;|[|><;])';
21+
}
22+
23+
public function getTokenType(): TokenTypeEnum
24+
{
25+
return TokenTypeEnum::OPERATOR;
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Bash\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: '#!/bin/bash', output: '#!/bin/bash')]
13+
#[PatternTest(input: '#!/usr/bin/env bash', output: '#!/usr/bin/env bash')]
14+
final readonly class BashShebangPattern implements Pattern
15+
{
16+
use IsPattern;
17+
18+
public function getPattern(): string
19+
{
20+
return '/(?<match>\#!\/.*)/';
21+
}
22+
23+
public function getTokenType(): TokenTypeEnum
24+
{
25+
return TokenTypeEnum::COMMENT;
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Highlight\Languages\Bash\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: 'echo $HOME', output: '$HOME')]
13+
#[PatternTest(input: 'echo ${PATH}', output: '${PATH}')]
14+
final readonly class BashVariablePattern implements Pattern
15+
{
16+
use IsPattern;
17+
18+
public function getPattern(): string
19+
{
20+
return '(?<match>\$\{[^}]+\}|\$[a-zA-Z_]\w*|\$[\d@?#!\$\-\*])';
21+
}
22+
23+
public function getTokenType(): TokenTypeEnum
24+
{
25+
return TokenTypeEnum::VARIABLE;
26+
}
27+
}

0 commit comments

Comments
 (0)