Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Highlighter.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use Tempest\Highlight\Languages\Terminal\TerminalLanguage;
use Tempest\Highlight\Languages\Terraform\TerraformLanguage;
use Tempest\Highlight\Languages\Text\TextLanguage;
use Tempest\Highlight\Languages\Toml\TomlLanguage;
use Tempest\Highlight\Languages\Tsx\TsxLanguage;
use Tempest\Highlight\Languages\Twig\TwigLanguage;
use Tempest\Highlight\Languages\TypeScript\TypeScriptLanguage;
Expand Down Expand Up @@ -94,6 +95,7 @@ public function __construct(
->addLanguage(new TerminalLanguage())
->addLanguage(new TextLanguage())
->addLanguage(new TerraformLanguage())
->addLanguage(new TomlLanguage())
->addLanguage(new TypeScriptLanguage())
->addLanguage(new XmlLanguage())
->addLanguage(new YamlLanguage())
Expand Down
28 changes: 28 additions & 0 deletions src/Languages/Toml/Patterns/TomlBooleanPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Toml\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'enabled = true', output: 'true')]
#[PatternTest(input: 'enabled = false', output: 'false')]
final class TomlBooleanPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '/(?<![A-Za-z0-9_-])(?<match>true|false)(?![A-Za-z0-9_-])/';
}

public function getTokenType(): TokenType
{
return TokenTypeEnum::LITERAL;
}
}
27 changes: 27 additions & 0 deletions src/Languages/Toml/Patterns/TomlCommentPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Toml\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: '# Server settings', output: '# Server settings')]
final class TomlCommentPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '/(?<match>#[^\r\n]*)/';
}

public function getTokenType(): TokenType
{
return TokenTypeEnum::COMMENT;
}
}
28 changes: 28 additions & 0 deletions src/Languages/Toml/Patterns/TomlDateTimePattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Toml\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'created = 1979-05-27T07:32:00Z', output: '1979-05-27T07:32:00Z')]
#[PatternTest(input: 'alarm = 07:32:00', output: '07:32:00')]
final class TomlDateTimePattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '/(?<![A-Za-z0-9_-])(?<match>(?:\d{4}-\d{2}-\d{2}(?:[Tt ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:[Zz]|[+-]\d{2}:\d{2})?)?|\d{2}:\d{2}:\d{2}(?:\.\d+)?))(?![A-Za-z0-9_-])/';
}

public function getTokenType(): TokenType
{
return TokenTypeEnum::VALUE;
}
}
30 changes: 30 additions & 0 deletions src/Languages/Toml/Patterns/TomlKeyPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Toml\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'title = "TOML"', output: 'title')]
#[PatternTest(input: 'fruit.physical.color = "orange"', output: 'fruit.physical.color')]
final class TomlKeyPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return <<<'REGEX'
/(?:^[\t ]*|(?<=[{,])[\t ]*)(?<match>(?:"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*'|[A-Za-z0-9_-]+)(?:[\t ]*\.[\t ]*(?:"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*'|[A-Za-z0-9_-]+))*)(?=[\t ]*=)/m
REGEX;
}

public function getTokenType(): TokenType
{
return TokenTypeEnum::PROPERTY;
}
}
31 changes: 31 additions & 0 deletions src/Languages/Toml/Patterns/TomlNumberPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Toml\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'answer = 42', output: '42')]
#[PatternTest(input: 'color = 0xDEAD_BEEF', output: '0xDEAD_BEEF')]
#[PatternTest(input: 'limit = +inf', output: '+inf')]
final class TomlNumberPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return <<<'REGEX'
/(?<![A-Za-z0-9_.-])(?<match>[+-]?(?:inf|nan)|0x[0-9A-Fa-f](?:_?[0-9A-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|[+-]?(?:\d(?:_?\d)*\.\d(?:_?\d)*(?:[eE][+-]?\d(?:_?\d)*)?|\d(?:_?\d)*[eE][+-]?\d(?:_?\d)*|\d(?:_?\d)*))(?![A-Za-z0-9_.-])/
REGEX;
}

public function getTokenType(): TokenType
{
return TokenTypeEnum::NUMBER;
}
}
28 changes: 28 additions & 0 deletions src/Languages/Toml/Patterns/TomlOperatorPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Toml\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'ports = [8000, 8001]', output: '=')]
#[PatternTest(input: '[[products]]', output: '[[')]
final class TomlOperatorPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '/(?<match>\[\[|\]\]|\[|\]|\{|\}|=|,)/';
}

public function getTokenType(): TokenType
{
return TokenTypeEnum::OPERATOR;
}
}
30 changes: 30 additions & 0 deletions src/Languages/Toml/Patterns/TomlStringPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Toml\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'name = "TOML"', output: '"TOML"')]
#[PatternTest(input: 'path = \'C:\\Users\'', output: '\'C:\\Users\'')]
final class TomlStringPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return <<<'REGEX'
/(?<match>"""(?:\\[\s\S]|"{1,2}(?!")|[^"\\])*"""|'''(?:'{1,2}(?!')|[^'])*'''|"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*')/
REGEX;
}

public function getTokenType(): TokenType
{
return TokenTypeEnum::VALUE;
}
}
30 changes: 30 additions & 0 deletions src/Languages/Toml/Patterns/TomlTablePattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Toml\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenType;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: '[database]', output: 'database')]
#[PatternTest(input: '[[products]]', output: 'products')]
final class TomlTablePattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return <<<'REGEX'
/^[\t ]*\[{1,2}[\t ]*(?<match>(?:"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*'|[A-Za-z0-9_-]+)(?:[\t ]*\.[\t ]*(?:"(?:\\(?:["\\bfnrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})|[^"\\\r\n])*"|'[^'\r\n]*'|[A-Za-z0-9_-]+))*)(?=[\t ]*\]{1,2})/m
REGEX;
}

public function getTokenType(): TokenType
{
return TokenTypeEnum::TYPE;
}
}
40 changes: 40 additions & 0 deletions src/Languages/Toml/TomlLanguage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Toml;

use Override;
use Tempest\Highlight\Languages\Base\BaseLanguage;
use Tempest\Highlight\Languages\Toml\Patterns\TomlBooleanPattern;
use Tempest\Highlight\Languages\Toml\Patterns\TomlCommentPattern;
use Tempest\Highlight\Languages\Toml\Patterns\TomlDateTimePattern;
use Tempest\Highlight\Languages\Toml\Patterns\TomlKeyPattern;
use Tempest\Highlight\Languages\Toml\Patterns\TomlNumberPattern;
use Tempest\Highlight\Languages\Toml\Patterns\TomlOperatorPattern;
use Tempest\Highlight\Languages\Toml\Patterns\TomlStringPattern;
use Tempest\Highlight\Languages\Toml\Patterns\TomlTablePattern;

final class TomlLanguage extends BaseLanguage
{
public function getName(): string
{
return 'toml';
}

#[Override]
public function getPatterns(): array
{
return [
...parent::getPatterns(),
new TomlKeyPattern(),
new TomlTablePattern(),
new TomlStringPattern(),
new TomlDateTimePattern(),
new TomlNumberPattern(),
new TomlBooleanPattern(),
new TomlCommentPattern(),
new TomlOperatorPattern(),
];
}
}
23 changes: 23 additions & 0 deletions tests/Bench/Fixtures/toml.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Application settings
title = "Nightly Service"
"site owner" = 'Operations'
enabled = true
ports = [8000, 8001, 8002]
ratio = 6.626e-34
mask = 0xFF_EC_DE_5E
released = 2026-10-19T03:45:00Z
alarm = 07:30:00
description = """A multiline
service description."""

[database.primary]
host = "db.internal"
credentials = { user = "service", retries = 3 }

[[servers]]
name = "api-01"
roles = ["web", "worker"]

[[servers]]
name = "api-02"
roles = ["web"]
1 change: 1 addition & 0 deletions tests/Bench/HighlighterBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ final class HighlighterBench
'swift' => 'swift.txt',
'terminal' => 'terminal.txt',
'terraform' => 'terraform.txt',
'toml' => 'toml.txt',
'typescript' => 'typescript.txt',
'txt' => 'text.txt',
'twig' => 'twig.txt',
Expand Down
Loading
Loading