diff --git a/src/Highlighter.php b/src/Highlighter.php index 866fe91..7f97a2c 100644 --- a/src/Highlighter.php +++ b/src/Highlighter.php @@ -26,6 +26,7 @@ use Tempest\Highlight\Languages\Scss\ScssLanguage; use Tempest\Highlight\Languages\Sql\SqlLanguage; use Tempest\Highlight\Languages\Terminal\TerminalLanguage; +use Tempest\Highlight\Languages\Terraform\TerraformLanguage; use Tempest\Highlight\Languages\Text\TextLanguage; use Tempest\Highlight\Languages\Twig\TwigLanguage; use Tempest\Highlight\Languages\Xml\XmlLanguage; @@ -73,6 +74,7 @@ public function __construct(private readonly Theme $theme = new CssTheme()) ->addLanguage(new ScssLanguage()) ->addLanguage(new SqlLanguage()) ->addLanguage(new TerminalLanguage()) + ->addLanguage(new TerraformLanguage()) ->addLanguage(new XmlLanguage()) ->addLanguage(new YamlLanguage()) ->addLanguage(new DotEnvLanguage()) diff --git a/src/Languages/Terraform/Patterns/TerraformBlockTypePattern.php b/src/Languages/Terraform/Patterns/TerraformBlockTypePattern.php new file mode 100644 index 0000000..2467605 --- /dev/null +++ b/src/Languages/Terraform/Patterns/TerraformBlockTypePattern.php @@ -0,0 +1,32 @@ +{$blockTypes})\b/m"; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::KEYWORD; + } +} diff --git a/src/Languages/Terraform/Patterns/TerraformBooleanPattern.php b/src/Languages/Terraform/Patterns/TerraformBooleanPattern.php new file mode 100644 index 0000000..f40fdce --- /dev/null +++ b/src/Languages/Terraform/Patterns/TerraformBooleanPattern.php @@ -0,0 +1,27 @@ +true|false|null)\b'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::VALUE; + } +} diff --git a/src/Languages/Terraform/Patterns/TerraformHeredocPattern.php b/src/Languages/Terraform/Patterns/TerraformHeredocPattern.php new file mode 100644 index 0000000..0e4c8b4 --- /dev/null +++ b/src/Languages/Terraform/Patterns/TerraformHeredocPattern.php @@ -0,0 +1,41 @@ +<<-?\s*([A-Z_][A-Z0-9_]*)\n.*?\n\s*\2)/s'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::VALUE; + } +} diff --git a/src/Languages/Terraform/Patterns/TerraformInterpolationPattern.php b/src/Languages/Terraform/Patterns/TerraformInterpolationPattern.php new file mode 100644 index 0000000..b8a99c4 --- /dev/null +++ b/src/Languages/Terraform/Patterns/TerraformInterpolationPattern.php @@ -0,0 +1,26 @@ +\$\{[^}]+\})'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::GENERIC; + } +} diff --git a/src/Languages/Terraform/Patterns/TerraformKeywordPattern.php b/src/Languages/Terraform/Patterns/TerraformKeywordPattern.php new file mode 100644 index 0000000..61933d5 --- /dev/null +++ b/src/Languages/Terraform/Patterns/TerraformKeywordPattern.php @@ -0,0 +1,32 @@ +(?:{$keywords}))\b"; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::KEYWORD; + } +} diff --git a/src/Languages/Terraform/Patterns/TerraformOperatorPattern.php b/src/Languages/Terraform/Patterns/TerraformOperatorPattern.php new file mode 100644 index 0000000..12ffc51 --- /dev/null +++ b/src/Languages/Terraform/Patterns/TerraformOperatorPattern.php @@ -0,0 +1,28 @@ + value', output: '=>')] +final readonly class TerraformOperatorPattern implements Pattern +{ + use IsPattern; + + public function getPattern(): string + { + return '(?=>|==|!=|>=|<=|&&|\|\||[=>[a-zA-Z_][a-zA-Z0-9_]*)\s*=/m'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::PROPERTY; + } +} diff --git a/src/Languages/Terraform/Patterns/TerraformTypePattern.php b/src/Languages/Terraform/Patterns/TerraformTypePattern.php new file mode 100644 index 0000000..0e87bdc --- /dev/null +++ b/src/Languages/Terraform/Patterns/TerraformTypePattern.php @@ -0,0 +1,32 @@ +(?:{$types}))\b"; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::TYPE; + } +} diff --git a/src/Languages/Terraform/Patterns/TerraformVariablePattern.php b/src/Languages/Terraform/Patterns/TerraformVariablePattern.php new file mode 100644 index 0000000..7318cdd --- /dev/null +++ b/src/Languages/Terraform/Patterns/TerraformVariablePattern.php @@ -0,0 +1,30 @@ +(?:{$prefixes})(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)+)"; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::VARIABLE; + } +} diff --git a/src/Languages/Terraform/TerraformLanguage.php b/src/Languages/Terraform/TerraformLanguage.php new file mode 100644 index 0000000..f12ceba --- /dev/null +++ b/src/Languages/Terraform/TerraformLanguage.php @@ -0,0 +1,88 @@ + 'scss.txt', 'sql' => 'sql.txt', 'terminal' => 'terminal.txt', + 'terraform' => 'terraform.txt', 'twig' => 'twig.txt', 'xml' => 'xml.txt', 'yaml' => 'yaml.txt', diff --git a/tests/Languages/Terraform/TerraformLanguageTest.php b/tests/Languages/Terraform/TerraformLanguageTest.php new file mode 100644 index 0000000..c7ee521 --- /dev/null +++ b/tests/Languages/Terraform/TerraformLanguageTest.php @@ -0,0 +1,124 @@ +assertSame( + $expected, + $highlighter->parse($content, 'terraform'), + ); + + $this->assertSame( + $expected, + $highlighter->parse($content, 'tf'), + ); + + $this->assertSame( + $expected, + $highlighter->parse($content, 'hcl'), + ); + + $this->assertSame( + $expected, + $highlighter->parse($content, 'terragrunt'), + ); + } + + public static function provide_highlight_cases(): iterable + { + return [ + [<<<'TXT' +# Configure the AWS provider +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "web" { + ami = var.ami_id + instance_type = "t2.micro" + count = 3 + + tags = { + Name = "web-${var.environment}" + } +} +TXT, + <<<'TXT' +# Configure the AWS provider +provider "aws" { + region = "us-east-1" +} + +resource "aws_instance" "web" { + ami = var.ami_id + instance_type = "t2.micro" + count = 3 + + tags = { + Name = "web-${var.environment}" + } +} +TXT], + [<<<'TXT' +variable "instance_type" { + type = string + default = "t2.micro" +} + +output "instance_id" { + value = module.server.id +} + +// This is a single-line comment +/* This is a + multi-line comment */ +TXT, + <<<'TXT' +variable "instance_type" { + type = string + default = "t2.micro" +} + +output "instance_id" { + value = module.server.id +} + +// This is a single-line comment +/* This is a + multi-line comment */ +TXT], + [<<<'TXT' +resource "aws_iam_policy" "example" { + policy = <<-POLICY + { + "Version": "2012-10-17", + "Statement": [] + } + POLICY +} +TXT, + <<<'TXT' +resource "aws_iam_policy" "example" { + policy = <<-POLICY + { + "Version": "2012-10-17", + "Statement": [] + } + POLICY +} +TXT], + ]; + } +}