rouge icon indicating copy to clipboard operation
rouge copied to clipboard

Support .tf and .tfvars extensions in HCL lexer

Open kumarmunish opened this issue 4 months ago • 3 comments

Name of the lexer HCL

Code sample

A .tf or .tfvars file (standard Terraform file extensions) is not highlighted when rendered via Rouge, because the lexer does not recognize these extensions.

Example .tf file content:

output = data.name

provider "aws" {
  region = "us-west-2"
}

resource "aws_s3_bucket" "example" {
  bucket = "my-example-bucket"
  acl    = "private"
}

You can reproduce this using the Dingus by uploading a .tf file — syntax highlighting is not applied unless the lexer is explicitly forced to HCL.

You'll see a red dot, which is caused by this.

Image

Additional context

The HCL lexer currently recognizes .hcl and .nomad extensions, but not .tf or .tfvars, which are widely used in modern infrastructure-as-code projects.

Image

Since the lexer itself works correctly when forced, this appears to be a filename recognition issue rather than a parsing one.

Rouge version is 4.5.2

I’d be happy to contribute a fix for this if that would be helpful!

kumarmunish avatar Aug 05 '25 17:08 kumarmunish

@kumarmunish Thank you for raising the issue. According to the spec, Terraform's configuration language is based on HCL. .tf and .tfvars are Terraform extensions so they must use the Terraform lexer. In other words, I don't think it is the filename recognition issue but the Terraform lexer itself that fails to parse the dot character.

Could you include the language spec for the .tfvars file that states the above syntax output = data.name is valid? I fail to find any references in https://developer.hashicorp.com/terraform/language/values.

tancnle avatar Aug 06 '25 03:08 tancnle

@tancnle, thanks for the clarification — you're absolutely right, the syntax I referenced (output = data.name) isn’t valid in .tfvars files, and I appreciate you pointing that out. I saw similar syntax was reported on an open issue on Gitlab(which uses Rouge), so I thought it was because if .tf files are not handled in the HCL lexer. I should have been more specific in my example — that was a mix-up on my part..

That said, I’m curious about the current behavior of the Rouge HCL lexer. It includes support for .hcl and .nomad extensions, but not .tf and .tfvars, even though Terraform is by far the most widespread use case of HCL in practice.

Is there a particular reason those extensions were excluded initially? Given their popularity and the fact that the underlying syntax is still HCL, it feels like a natural addition to support them alongside .nomad.

https://github.com/rouge-ruby/rouge/blob/master/lib/rouge/lexers/hcl.rb#L8

kumarmunish avatar Aug 06 '25 13:08 kumarmunish

@kumarmunish In Rouge, Terraform lexer inherits from HCL lexer. I would expect it supports majority of HCL syntax with some additional Terraform specific keywords and features.

Is there a particular reason those extensions were excluded initially?

HCL lexer is meant to support bare-bones HCL, rather than flavours of it.

tancnle avatar Aug 08 '25 12:08 tancnle