├── .gitignore ├── .vscodeignore ├── image-after.png ├── terraform.png ├── image-before.png ├── .github └── workflows │ └── main.yml ├── .vscode └── launch.json ├── language-configuration.json ├── LICENSE ├── README.md ├── package.json └── syntaxes └── terraform.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.vsix 2 | node_modules 3 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | vsc-extension-quickstart.md 5 | -------------------------------------------------------------------------------- /image-after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pjmiravalle/vscode-terraform-advanced-syntax-highlighting/HEAD/image-after.png -------------------------------------------------------------------------------- /terraform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pjmiravalle/vscode-terraform-advanced-syntax-highlighting/HEAD/terraform.png -------------------------------------------------------------------------------- /image-before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pjmiravalle/vscode-terraform-advanced-syntax-highlighting/HEAD/image-before.png -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | tags: 4 | - "*" 5 | 6 | name: Deploy Extension 7 | jobs: 8 | deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-node@v1 13 | with: 14 | node-version: 16 15 | - name: Publish to Visual Studio Marketplace 16 | uses: HaaLeo/publish-vscode-extension@v1 17 | with: 18 | pat: ${{ secrets.VS_MARKETPLACE_TOKEN }} 19 | registryUrl: https://marketplace.visualstudio.com 20 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "#", 4 | "blockComment": ["/*", "*/"] 5 | }, 6 | // symbols used as brackets 7 | "brackets": [ 8 | ["{", "}"], 9 | ["[", "]"], 10 | ["(", ")"] 11 | ], 12 | "autoClosingPairs": [ 13 | { 14 | "open": "{", 15 | "close": "}" 16 | }, 17 | { 18 | "open": "[", 19 | "close": "]" 20 | }, 21 | { 22 | "open": "(", 23 | "close": ")" 24 | }, 25 | { 26 | "open": "\"", 27 | "close": "\"", 28 | "notIn": ["string"] 29 | }, 30 | { 31 | "open": "'", 32 | "close": "'", 33 | "notIn": ["string", "comment"] 34 | } 35 | ], 36 | "autoCloseBefore": ";:.,=}])> \n\t\"", 37 | "surroundingPairs": [ 38 | ["{", "}"], 39 | ["[", "]"], 40 | ["(", ")"], 41 | ["\"", "\""], 42 | ["'", "'"] 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Patrick Miravalle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform Advanced Syntax Highlighting 2 | 3 | **Terraform Advanced Syntax Highlighting** is a Visual Studio Code extension that dramatically improves syntax highlighting for `.tf`, `.tfvars`, and `.hcl` files in VS Code. 4 | 5 | This extension has been designed and tested to either work as a standalone solution for Terraform syntax highlighting, or alongside other extensions. Take a look at the [Compatibility](#compatibility) section for more information. 6 | 7 | ## Before (with Hashicorp Terraform Extension) 8 | 9 | ![Terraform Syntax Highlighting - Before](./image-before.png) 10 | 11 | ## After (with this extension) 12 | 13 | ![Terraform Syntax Highlighting - After](./image-after.png) 14 | 15 | ## Usage 16 | 17 | Most themes are supported by default. Just install this VS Code extension and you'll immediately see improved syntax highlighting for your Terraform files. 18 | 19 | For any theme specific issues, please take a look at the [following guide provided by VS Code](https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide). 20 | 21 | ## Compatibility 22 | 23 | The following extensions have been tested to work alongside **Terraform Advanced Syntax Highlighting**: 24 | 25 | - [Official Terraform VS Code Extension](https://marketplace.visualstudio.com/items?itemName=HashiCorp.terraform) 26 | 27 | ## Feedback 28 | 29 | Notice any bugs, or have an idea on how this extension can improve? Please submit a request [here](https://github.com/pjmiravalle/vscode-terraform-advanced-syntax-highlighting/issues). 30 | 31 | Happy Coding! 😄 32 | 33 | ~ Patrick 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "icon": "terraform.png", 3 | "name": "terraform-advanced-syntax-highlighting", 4 | "displayName": "Terraform Advanced Syntax Highlighting", 5 | "description": "Advanced Syntax Highlighting for all Terraform file types.", 6 | "version": "1.4.3", 7 | "publisher": "pjmiravalle", 8 | "engines": { 9 | "vscode": "^1.39.0" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/pjmiravalle/vscode-terraform-advanced-syntax-highlighting/issues", 13 | "email": "4603979+pjmiravalle@users.noreply.github.com" 14 | }, 15 | "categories": [ 16 | "Programming Languages", 17 | "Other", 18 | "Formatters", 19 | "Linters" 20 | ], 21 | "keywords": [ 22 | "devops", 23 | "terraform", 24 | "terraform syntax highlighting", 25 | "syntax highlighting", 26 | "hcl" 27 | ], 28 | "repository": { 29 | "type": "git", 30 | "url": "https://github.com/pjmiravalle/vscode-terraform-advanced-syntax-highlighting" 31 | }, 32 | "contributes": { 33 | "languages": [ 34 | { 35 | "id": "terraform", 36 | "aliases": [ 37 | "Terraform", 38 | "terraform" 39 | ], 40 | "extensions": [ 41 | ".tf", 42 | ".tfvars", 43 | ".hcl" 44 | ], 45 | "configuration": "./language-configuration.json" 46 | }, 47 | { 48 | "id": "json", 49 | "extensions": [ 50 | ".tfstate", 51 | ".tpl" 52 | ] 53 | } 54 | ], 55 | "grammars": [ 56 | { 57 | "language": "terraform", 58 | "scopeName": "scope.terraform", 59 | "path": "./syntaxes/terraform.json" 60 | } 61 | ] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /syntaxes/terraform.json: -------------------------------------------------------------------------------- 1 | { 2 | "scopeName": "scope.terraform", 3 | "fileTypes": [ 4 | "tf", 5 | "tfvars", 6 | "hcl" 7 | ], 8 | "name": "Terraform", 9 | "patterns": [ 10 | { 11 | "include": "#comments" 12 | }, 13 | { 14 | "include": "#attribute_definition" 15 | }, 16 | { 17 | "include": "#block" 18 | }, 19 | { 20 | "include": "#expressions" 21 | } 22 | ], 23 | "repository": { 24 | "char_escapes": { 25 | "match": "\\\\[nrt\"\\\\]|\\\\u(\\h{8}|\\h{4})", 26 | "comment": "Character Escapes", 27 | "name": "constant.character.escape.terraform" 28 | }, 29 | "comma": { 30 | "match": "\\,", 31 | "comment": "Commas - used in certain expressions", 32 | "name": "punctuation.separator.terraform keyword.operator" 33 | }, 34 | "language_constants": { 35 | "match": "\\b(true|false|null)\\b", 36 | "comment": "Language Constants", 37 | "name": "constant.language.terraform" 38 | }, 39 | "named_value_references": { 40 | "match": "\\b(var|local|module|data|path|terraform)\\b", 41 | "comment": "Constant values available only to Terraform.", 42 | "name": "variable.other.readwrite.terraform constant.language.terraform" 43 | }, 44 | "local_identifiers": { 45 | "match": "\\b(?!null|false|true|for|in)[[:alpha:]][[:alnum:]_-]*\\b", 46 | "comment": "Local Identifiers", 47 | "name": "variable.other.readwrite.terraform constant.language.terraform" 48 | }, 49 | "terraform_type_keywords": { 50 | "match": "\\b(any|string|number|bool)\\b", 51 | "comment": "Type keywords known to Terraform.", 52 | "name": "constant.language.terraform" 53 | }, 54 | "comments": { 55 | "patterns": [ 56 | { 57 | "include": "#inline_comments" 58 | }, 59 | { 60 | "include": "#block_comments" 61 | } 62 | ] 63 | }, 64 | "inline_comments": { 65 | "begin": "#|//", 66 | "comment": "Inline Comments", 67 | "name": "comment.line.terraform", 68 | "captures": { 69 | "0": { 70 | "name": "punctuation.definition.comment.terraform" 71 | } 72 | }, 73 | "end": "$\\n?" 74 | }, 75 | "block_comments": { 76 | "begin": "/\\*", 77 | "comment": "Block comments", 78 | "name": "comment.block.terraform", 79 | "captures": { 80 | "0": { 81 | "name": "punctuation.definition.comment.terraform" 82 | } 83 | }, 84 | "end": "\\*/" 85 | }, 86 | "attribute_definition": { 87 | "match": "(\\()?((?!null|false|true)[[:alpha:]][[:alnum:]_-]*)(\\))?\\s*(\\=(?!\\=|\\>))\\s*", 88 | "comment": "Identifier \"=\" with optional parens", 89 | "name": "variable.declaration.terraform", 90 | "captures": { 91 | "1": { 92 | "name": "punctuation.section.parens.begin.terraform meta.template.expression.terraform" 93 | }, 94 | "2": { 95 | "name": "variable.other.property.terraform" 96 | }, 97 | "3": { 98 | "name": "punctuation.section.parens.end.terraform meta.template.expression.terraform" 99 | }, 100 | "4": { 101 | "name": "keyword.operator.assignment.terraform" 102 | } 103 | } 104 | }, 105 | "block": { 106 | "name": "meta.block.terraform", 107 | "begin": "(\\w+)(?:([\\s\\\"\\-[:word:]]*)(\\{))", 108 | "beginCaptures": { 109 | "1": { 110 | "patterns": [ 111 | { 112 | "match": "\\b(?:resource|provider|variable|output|locals|module|data|terraform)\\b", 113 | "name": "entity.name.type.terraform" 114 | }, 115 | { 116 | "match": "\\b(?!null|false|true)[[:alpha:]][[:alnum:]_-]*\\b", 117 | "comment": "Identifer label", 118 | "name": "entity.name.type.terraform" 119 | } 120 | ] 121 | }, 122 | "2": { 123 | "patterns": [ 124 | { 125 | "include": "#string_literals" 126 | } 127 | ] 128 | }, 129 | "3": { 130 | "name": "punctuation.section.block.begin.terraform" 131 | } 132 | }, 133 | "end": "\\}", 134 | "endCaptures": { 135 | "0": { 136 | "name": "punctuation.section.block.end.terraform" 137 | } 138 | }, 139 | "patterns": [ 140 | { 141 | "include": "#comments" 142 | }, 143 | { 144 | "include": "#attribute_definition" 145 | }, 146 | { 147 | "include": "#block" 148 | }, 149 | { 150 | "include": "#expressions" 151 | }, 152 | { 153 | "include": "#local_identifiers" 154 | } 155 | ] 156 | }, 157 | "expressions": { 158 | "patterns": [ 159 | { 160 | "include": "#literal_values" 161 | }, 162 | { 163 | "include": "#operators" 164 | }, 165 | { 166 | "include": "#brackets" 167 | }, 168 | { 169 | "include": "#objects" 170 | }, 171 | { 172 | "include": "#attribute_access" 173 | }, 174 | { 175 | "include": "#structural_types" 176 | }, 177 | { 178 | "include": "#functions" 179 | }, 180 | { 181 | "include": "#parens" 182 | } 183 | ] 184 | }, 185 | "literal_values": { 186 | "patterns": [ 187 | { 188 | "include": "#numeric_literals" 189 | }, 190 | { 191 | "include": "#language_constants" 192 | }, 193 | { 194 | "include": "#string_literals" 195 | }, 196 | { 197 | "include": "#heredoc" 198 | }, 199 | { 200 | "include": "#terraform_type_keywords" 201 | }, 202 | { 203 | "include": "#named_value_references" 204 | } 205 | ] 206 | }, 207 | "numeric_literals": { 208 | "patterns": [ 209 | { 210 | "match": "\\b\\d+([Ee][+-]?)\\d+\\b", 211 | "comment": "Integer, no fraction, optional exponent", 212 | "name": "constant.numeric.float.terraform", 213 | "captures": { 214 | "1": { 215 | "name": "punctuation.separator.exponent.terraform" 216 | } 217 | } 218 | }, 219 | { 220 | "match": "\\b\\d+(\\.)\\d+(?:([Ee][+-]?)\\d+)?\\b", 221 | "comment": "Integer, fraction, optional exponent", 222 | "name": "constant.numeric.float.terraform", 223 | "captures": { 224 | "1": { 225 | "name": "punctuation.separator.decimal.terraform" 226 | }, 227 | "2": { 228 | "name": "punctuation.separator.exponent.terraform" 229 | } 230 | } 231 | }, 232 | { 233 | "match": "\\b\\d+\\b", 234 | "comment": "Integers", 235 | "name": "constant.numeric.integer.terraform" 236 | } 237 | ] 238 | }, 239 | "string_literals": { 240 | "begin": "\"", 241 | "comment": "Strings", 242 | "name": "string.quoted.double.terraform", 243 | "beginCaptures": { 244 | "0": { 245 | "name": "punctuation.definition.string.begin.terraform" 246 | } 247 | }, 248 | "end": "\"", 249 | "endCaptures": { 250 | "0": { 251 | "name": "punctuation.definition.string.end.terraform" 252 | } 253 | }, 254 | "patterns": [ 255 | { 256 | "include": "#string_interpolation" 257 | }, 258 | { 259 | "include": "#char_escapes" 260 | } 261 | ] 262 | }, 263 | "string_interpolation": { 264 | "begin": "[%$]{", 265 | "comment": "String interpolation", 266 | "name": "meta.interpolation.terraform", 267 | "beginCaptures": { 268 | "0": { 269 | "name": "keyword.other.interpolation.begin.terraform constant.language.terraform" 270 | } 271 | }, 272 | "end": "\\}", 273 | "endCaptures": { 274 | "0": { 275 | "name": "keyword.other.interpolation.end.terraform constant.language.terraform" 276 | } 277 | }, 278 | "patterns": [ 279 | { 280 | "match": "\\~\\s", 281 | "comment": "Trim left whitespace", 282 | "name": "keyword.operator.template.left.trim.terraform" 283 | }, 284 | { 285 | "match": "\\s\\~", 286 | "comment": "Trim right whitespace", 287 | "name": "keyword.operator.template.right.trim.terraform" 288 | }, 289 | { 290 | "match": "\\b(if|else|endif|for|in|endfor)\\b", 291 | "comment": "if/else/endif and for/in/endfor directives", 292 | "name": "keyword.control.terraform" 293 | }, 294 | { 295 | "include": "#expressions" 296 | }, 297 | { 298 | "include": "#local_identifiers" 299 | } 300 | ] 301 | }, 302 | "heredoc": { 303 | "begin": "(\\<\\<\\-?)\\s*(\\w+)\\s*$", 304 | "comment": "String Heredoc", 305 | "name": "string.unquoted.heredoc.terraform", 306 | "beginCaptures": { 307 | "1": { 308 | "name": "keyword.control.heredoc.terraform" 309 | }, 310 | "2": { 311 | "name": "keyword.control.heredoc.terraform" 312 | } 313 | }, 314 | "end": "^\\s*\\2\\s*$", 315 | "endCaptures": { 316 | "0": { 317 | "comment": "The heredoc token identifier (second capture above).", 318 | "name": "keyword.control.heredoc.terraform" 319 | } 320 | }, 321 | "patterns": [ 322 | { 323 | "include": "#string_interpolation" 324 | } 325 | ] 326 | }, 327 | "operators": { 328 | "patterns": [ 329 | { 330 | "match": "\\>\\=", 331 | "name": "keyword.control.terraform" 332 | }, 333 | { 334 | "match": "\\<\\=", 335 | "name": "keyword.control.terraform" 336 | }, 337 | { 338 | "match": "\\=\\>", 339 | "name": "storage.type.function.terraform" 340 | }, 341 | { 342 | "match": "\\=\\=", 343 | "name": "keyword.control.terraform" 344 | }, 345 | { 346 | "match": "\\!\\=", 347 | "name": "keyword.control.terraform" 348 | }, 349 | { 350 | "match": "\\+", 351 | "name": "keyword.control.arithmetic.terraform" 352 | }, 353 | { 354 | "comment": "minus sign, only matched if there is whitespace before and after the dash", 355 | "match": "\\s\\-\\s", 356 | "name": "keyword.control.arithmetic.terraform" 357 | }, 358 | { 359 | "comment": "negative integer", 360 | "match": "\\-\\d", 361 | "name": "constant.numeric.integer.terraform" 362 | }, 363 | { 364 | "match": "\\*", 365 | "name": "keyword.control.arithmetic.terraform" 366 | }, 367 | { 368 | "match": "\\/", 369 | "name": "keyword.control.arithmetic.terraform" 370 | }, 371 | { 372 | "match": "\\%", 373 | "name": "keyword.control.arithmetic.terraform" 374 | }, 375 | { 376 | "match": "\\&\\&", 377 | "name": "keyword.control.logical.terraform" 378 | }, 379 | { 380 | "match": "\\|\\|", 381 | "name": "keyword.control.logical.terraform" 382 | }, 383 | { 384 | "match": "\\!", 385 | "name": "keyword.control.logical.terraform" 386 | }, 387 | { 388 | "match": "\\>", 389 | "name": "keyword.control.terraform" 390 | }, 391 | { 392 | "match": "\\<", 393 | "name": "keyword.control.terraform" 394 | }, 395 | { 396 | "match": "\\?", 397 | "name": "keyword.control.terraform" 398 | }, 399 | { 400 | "match": "\\.\\.\\.", 401 | "name": "keyword.control.terraform" 402 | }, 403 | { 404 | "match": "\\:", 405 | "name": "keyword.control.terraform" 406 | } 407 | ] 408 | }, 409 | "brackets": { 410 | "begin": "\\[", 411 | "beginCaptures": { 412 | "0": { 413 | "name": "punctuation.section.brackets.begin.terraform meta.template.expression.terraform" 414 | } 415 | }, 416 | "end": "(\\*?)\\]", 417 | "endCaptures": { 418 | "0": { 419 | "name": "punctuation.section.brackets.end.terraform meta.template.expression.terraform" 420 | }, 421 | "1": { 422 | "name": "keyword.operator.splat.terraform constant.terraform" 423 | } 424 | }, 425 | "patterns": [ 426 | { 427 | "include": "#comma" 428 | }, 429 | { 430 | "include": "#comments" 431 | }, 432 | { 433 | "include": "#for_expressions" 434 | }, 435 | { 436 | "include": "#expressions" 437 | }, 438 | { 439 | "include": "#local_identifiers" 440 | } 441 | ] 442 | }, 443 | "objects": { 444 | "name": "meta.braces.terraform", 445 | "begin": "\\{", 446 | "beginCaptures": { 447 | "0": { 448 | "name": "punctuation.section.braces.begin.terraform" 449 | } 450 | }, 451 | "end": "\\}", 452 | "endCaptures": { 453 | "0": { 454 | "name": "punctuation.section.braces.end.terraform" 455 | } 456 | }, 457 | "patterns": [ 458 | { 459 | "include": "#comments" 460 | }, 461 | { 462 | "match": "\\b((?!null|false|true)[[:alpha:]][[:alnum:]_-]*)\\s*(\\s\\=\\s)\\s*", 463 | "comment": "Literal, named object key", 464 | "captures": { 465 | "1": { 466 | "name": "variable.other.property.terraform" 467 | }, 468 | "2": { 469 | "name": "variable" 470 | } 471 | } 472 | }, 473 | { 474 | "match": "\\b((\").*(\"))\\s*(\\=)\\s*", 475 | "comment": "String object key", 476 | "captures": { 477 | "0": { 478 | "patterns": [ 479 | { 480 | "include": "#named_value_references" 481 | } 482 | ] 483 | }, 484 | "1": { 485 | "name": "meta.mapping.key.terraform string.quoted.double.terraform" 486 | }, 487 | "2": { 488 | "name": "punctuation.definition.string.begin.terraform" 489 | }, 490 | "3": { 491 | "name": "punctuation.definition.string.end.terraform" 492 | }, 493 | "4": { 494 | "name": "keyword.operator.terraform" 495 | } 496 | } 497 | }, 498 | { 499 | "begin": "^\\s*\\(", 500 | "comment": "Computed object key (any expression between parens)", 501 | "name": "meta.mapping.key.terraform", 502 | "beginCaptures": { 503 | "0": { 504 | "name": "punctuation.section.parens.begin.terraform meta.template.expression.terraform" 505 | } 506 | }, 507 | "end": "(\\))\\s*(\\=)\\s*", 508 | "endCaptures": { 509 | "1": { 510 | "name": "punctuation.section.parens.end.terraform meta.template.expression.terraform" 511 | }, 512 | "2": { 513 | "name": "keyword.operator.terraform" 514 | } 515 | }, 516 | "patterns": [ 517 | { 518 | "include": "#named_value_references" 519 | }, 520 | { 521 | "include": "#attribute_access" 522 | } 523 | ] 524 | }, 525 | { 526 | "include": "#object_key_values" 527 | }, 528 | { 529 | "include": "#for_expressions" 530 | } 531 | ] 532 | }, 533 | "object_key_values": { 534 | "patterns": [ 535 | { 536 | "include": "#comments" 537 | }, 538 | { 539 | "include": "#literal_values" 540 | }, 541 | { 542 | "include": "#operators" 543 | }, 544 | { 545 | "include": "#heredoc" 546 | }, 547 | { 548 | "include": "#functions" 549 | }, 550 | { 551 | "include": "#local_identifiers" 552 | }, 553 | { 554 | "include": "#attribute_access" 555 | } 556 | ] 557 | }, 558 | "for_expressions": { 559 | "patterns": [ 560 | { 561 | "match": "\\bfor\\b", 562 | "comment": "for keyword", 563 | "name": "keyword.operator.word.terraform keyword.control.terraform" 564 | }, 565 | { 566 | "match": "\\bin\\b", 567 | "comment": "in keyword", 568 | "name": "keyword.operator.word.terraform keyword.control.terraform" 569 | }, 570 | { 571 | "match": "\\bif\\b", 572 | "comment": "if keyword", 573 | "name": "keyword.control.conditional.terraform" 574 | }, 575 | { 576 | "include": "#expressions" 577 | }, 578 | { 579 | "include": "#comments" 580 | }, 581 | { 582 | "include": "#comma" 583 | }, 584 | { 585 | "include": "#local_identifiers" 586 | } 587 | ] 588 | }, 589 | "attribute_access": { 590 | "begin": "\\.", 591 | "beginCaptures": { 592 | "0": { 593 | "name": "keyword.operator.accessor.terraform" 594 | } 595 | }, 596 | "end": "[\\w_-]+", 597 | "endCaptures": { 598 | "0": { 599 | "patterns": [ 600 | { 601 | "match": "\\b(?!null|false|true)[\\w_-]*\\b", 602 | "comment": "Attribute access", 603 | "name": "variable.other.member.terraform" 604 | } 605 | ] 606 | }, 607 | "1": { 608 | "patterns": [ 609 | { 610 | "match": "\\d+", 611 | "comment": "Subscript", 612 | "name": "constant.numeric.integer.terraform" 613 | }, 614 | { 615 | "match": "\\*", 616 | "comment": "Attribute-only splat", 617 | "name": "keyword.operator.splat.terraform" 618 | } 619 | ] 620 | } 621 | } 622 | }, 623 | "structural_types": { 624 | "patterns": [ 625 | { 626 | "begin": "(object)(\\()(\\{)\\s*", 627 | "comment": "Object structural type", 628 | "beginCaptures": { 629 | "1": { 630 | "name": "support.function.builtin.terraform" 631 | }, 632 | "2": { 633 | "name": "punctuation.section.parens.begin.terraform" 634 | }, 635 | "3": { 636 | "name": "punctuation.section.braces.begin.terraform" 637 | } 638 | }, 639 | "end": "(\\})(\\))", 640 | "endCaptures": { 641 | "1": { 642 | "name": "punctuation.section.braces.end.terraform" 643 | }, 644 | "2": { 645 | "name": "punctuation.section.parens.end.terraform" 646 | } 647 | }, 648 | "patterns": [ 649 | { 650 | "include": "#comments" 651 | }, 652 | { 653 | "include": "#functions" 654 | }, 655 | { 656 | "include": "#comma" 657 | }, 658 | { 659 | "match": "((?!null|false|true)[[:alpha:]][[:alnum:]_-]*)\\s*(\\=(?!\\=|\\>))\\s*", 660 | "comment": "Identifier \"=\"", 661 | "name": "variable.declaration.terraform", 662 | "captures": { 663 | "1": { 664 | "name": "variable.other.property.terraform" 665 | }, 666 | "2": { 667 | "name": "keyword.operator.assignment.terraform" 668 | } 669 | } 670 | }, 671 | { 672 | "include": "#terraform_type_keywords" 673 | } 674 | ] 675 | }, 676 | { 677 | "begin": "(tuple)(\\()(\\[)\\s*", 678 | "name": "meta.function-call.terraform", 679 | "comment": "Tuple structural type", 680 | "beginCaptures": { 681 | "1": { 682 | "name": "support.function.builtin.terraform" 683 | }, 684 | "2": { 685 | "name": "punctuation.section.parens.begin.terraform" 686 | }, 687 | "3": { 688 | "name": "punctuation.section.brackets.begin.terraform" 689 | } 690 | }, 691 | "end": "(\\])(\\))", 692 | "endCaptures": { 693 | "1": { 694 | "name": "punctuation.section.brackets.end.terraform" 695 | }, 696 | "2": { 697 | "name": "punctuation.section.parens.end.terraform" 698 | } 699 | }, 700 | "patterns": [ 701 | { 702 | "include": "#comma" 703 | }, 704 | { 705 | "include": "#terraform_type_keywords" 706 | } 707 | ] 708 | } 709 | ] 710 | }, 711 | "functions": { 712 | "begin": "(\\w+)(\\()", 713 | "name": "meta.function-call.terraform", 714 | "comment": "Built-in function calls", 715 | "beginCaptures": { 716 | "1": { 717 | "patterns": [ 718 | { 719 | "match": "abs|ceil|floor|log|max|min|pow|signum|chomp|format|formatlist|indent|join|lower|regex|regexall|replace|split|strrev|substr|title|trimspace|upper|chunklist|coalesce|coalescelist|compact|concat|contains|distinct|element|flatten|index|keys|length|list|lookup|map|matchkeys|merge|range|reverse|set|setintersection|setproduct|setunion|slice|sort|transpose|values|zipmap|base64decode|base64encode|base64gzip|csvdecode|jsondecode|jsonencode|urlencode|yamldecode|yamlencode|abspath|dirname|pathexpand|basename|file|fileexists|fileset|filebase64|templatefile|formatdate|timeadd|timestamp|base64sha256|base64sha512|bcrypt|filebase64sha256|filebase64sha512|filemd5|filemd1|filesha256|filesha512|md5|rsadecrypt|sha1|sha256|sha512|uuid|uuidv5|cidrhost|cidrnetmask|cidrsubnet|tobool|tolist|tomap|tonumber|toset|tostring", 720 | "name": "support.function.builtin.terraform entity.name.function" 721 | }, 722 | { 723 | "match": "\\b(?!null|false|true)[[:alpha:]][[:alnum:]_-]*\\b", 724 | "name": "variable.function.terraform" 725 | } 726 | ] 727 | }, 728 | "2": { 729 | "name": "punctuation.section.parens.begin.terraform meta.template.expression.terraform" 730 | } 731 | }, 732 | "end": "\\)", 733 | "endCaptures": { 734 | "0": { 735 | "name": "punctuation.section.parens.end.terraform meta.template.expression.terraform" 736 | } 737 | }, 738 | "patterns": [ 739 | { 740 | "include": "#comments" 741 | }, 742 | { 743 | "include": "#expressions" 744 | }, 745 | { 746 | "include": "#comma" 747 | }, 748 | { 749 | "include": "#local_identifiers" 750 | } 751 | ] 752 | }, 753 | "parens": { 754 | "begin": "\\(", 755 | "comment": "Parens - matched *after* function syntax", 756 | "beginCaptures": { 757 | "0": { 758 | "name": "punctuation.section.parens.begin.terraform meta.template.expression.terraform" 759 | } 760 | }, 761 | "end": "\\)", 762 | "endCaptures": { 763 | "0": { 764 | "name": "punctuation.section.parens.end.terraform meta.template.expression.terraform" 765 | } 766 | }, 767 | "patterns": [ 768 | { 769 | "include": "#expressions" 770 | }, 771 | { 772 | "include": "#local_identifiers" 773 | } 774 | ] 775 | } 776 | } 777 | } 778 | --------------------------------------------------------------------------------