├── messages.json ├── HCL.sublime-settings ├── Terraform.sublime-settings ├── Terraform-vars.sublime-settings ├── snippets ├── data.sublime-snippet ├── provider.sublime-snippet ├── output.sublime-snippet ├── resource.sublime-snippet ├── module.sublime-snippet ├── provisioner.sublime-snippet ├── module_path.sublime-snippet ├── module_github.sublime-snippet ├── variable_empty.sublime-snippet ├── module_github_private.sublime-snippet ├── variable_string.sublime-snippet └── variable_map.sublime-snippet ├── Symbols - Indexed.tmPreferences ├── JSON (Terraform).sublime-syntax ├── Symbols - Local.tmPreferences ├── HCL.sublime-syntax ├── Terraform-vars.sublime-syntax ├── messages └── 2.0.0.md ├── Indentation Rules.tmPreferences ├── README.md ├── Comments.tmPreferences ├── LICENSE ├── Fold.tmPreferences ├── Terraform Plan.sublime-syntax ├── CHANGELOG.md └── Terraform.sublime-syntax /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "2.0.0": "messages/2.0.0.md" 3 | } 4 | -------------------------------------------------------------------------------- /HCL.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "tab_size": 2, 3 | "translate_tabs_to_spaces": true, 4 | // Move '-' to sub-word separators 5 | "word_separators": "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`~?", 6 | "sub_word_separators": "_-", 7 | } 8 | -------------------------------------------------------------------------------- /Terraform.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "tab_size": 2, 3 | "translate_tabs_to_spaces": true, 4 | // Move '-' to sub-word separators 5 | "word_separators": "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`~?", 6 | "sub_word_separators": "_-", 7 | } 8 | -------------------------------------------------------------------------------- /Terraform-vars.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "tab_size": 2, 3 | "translate_tabs_to_spaces": true, 4 | // Move '-' to sub-word separators 5 | "word_separators": "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`~?", 6 | "sub_word_separators": "_-", 7 | } 8 | -------------------------------------------------------------------------------- /snippets/data.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 7 | data 8 | source.terraform 9 | data block 10 | 11 | -------------------------------------------------------------------------------- /snippets/provider.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 7 | provider 8 | source.terraform 9 | provider block 10 | 11 | -------------------------------------------------------------------------------- /snippets/output.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 7 | output 8 | source.terraform 9 | output block 10 | 11 | -------------------------------------------------------------------------------- /snippets/resource.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 7 | resource 8 | source.terraform 9 | resource block 10 | 11 | -------------------------------------------------------------------------------- /snippets/module.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 8 | module 9 | source.terraform 10 | module block 11 | 12 | -------------------------------------------------------------------------------- /snippets/provisioner.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 7 | provisioner 8 | source.terraform 9 | provisioner block 10 | 11 | -------------------------------------------------------------------------------- /snippets/module_path.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 8 | moduleP 9 | source.terraform 10 | module (path) 11 | 12 | -------------------------------------------------------------------------------- /snippets/module_github.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 8 | moduleG 9 | source.terraform 10 | module (github public) 11 | 12 | -------------------------------------------------------------------------------- /snippets/variable_empty.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 8 | variableE 9 | source.terraform 10 | variable (empty) 11 | 12 | -------------------------------------------------------------------------------- /snippets/module_github_private.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 8 | moduleGS 9 | source.terraform 10 | module (github ssh) 11 | 12 | -------------------------------------------------------------------------------- /snippets/variable_string.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 9 | variableS 10 | source.terraform 11 | variable (string) 12 | 13 | -------------------------------------------------------------------------------- /snippets/variable_map.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 12 | variableM 13 | source.terraform 14 | variable (map) 15 | 16 | -------------------------------------------------------------------------------- /Symbols - Indexed.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Local Symbol List 7 | scope 8 | 9 | entity.name.label.terraform 10 | 11 | settings 12 | 13 | showInIndexedSymbolList 14 | 1 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /JSON (Terraform).sublime-syntax: -------------------------------------------------------------------------------- 1 | %YAML 1.2 2 | --- 3 | # http://www.sublimetext.com/docs/syntax.html 4 | name: JSON (Terraform) 5 | scope: source.json.terraform 6 | version: 2 7 | 8 | extends: Packages/JSON/JSON.sublime-syntax 9 | 10 | file_extensions: 11 | - tfstate 12 | 13 | contexts: 14 | double-quoted-string-body: 15 | - meta_prepend: true 16 | - include: Packages/Terraform/Terraform.sublime-syntax#string-interpolation 17 | - include: Packages/Terraform/Terraform.sublime-syntax#aws-acl 18 | 19 | line-comments: 20 | - meta_append: true 21 | - include: Packages/Terraform/Terraform.sublime-syntax#inline-comments 22 | -------------------------------------------------------------------------------- /Symbols - Local.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Local Symbol List 7 | scope 8 | 9 | meta.block.head.terraform 10 | 11 | settings 12 | 13 | showInSymbolList 14 | 1 15 | symbolTransformation 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /HCL.sublime-syntax: -------------------------------------------------------------------------------- 1 | %YAML 1.2 2 | # 3 | # This syntax definition is based on the Terraform guide: 4 | # https://www.terraform.io/docs/configuration/index.html 5 | # 6 | # As well as the HCL Native Syntax Spec: 7 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md 8 | # 9 | # For documentation on the .subline-syntax format: 10 | # https://www.sublimetext.com/docs/syntax.html 11 | # 12 | # Regex's in this file support the Oniguruma regex engine: 13 | # https://raw.githubusercontent.com/kkos/oniguruma/5.9.6/doc/RE 14 | # 15 | --- 16 | name: HCL 17 | scope: source.hcl 18 | version: 2 19 | 20 | extends: Terraform.sublime-syntax 21 | 22 | # File Extensions: 23 | # 24 | # - ".hcl": non-terraform tools often use this HCL syntax, i.e. Vault 25 | # https://www.vaultproject.io/docs/configuration/ 26 | file_extensions: 27 | - hcl 28 | -------------------------------------------------------------------------------- /Terraform-vars.sublime-syntax: -------------------------------------------------------------------------------- 1 | %YAML 1.2 2 | # 3 | # This syntax definition is based on the Terraform guide: 4 | # https://www.terraform.io/docs/configuration/index.html 5 | # 6 | # As well as the HCL Native Syntax Spec: 7 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md 8 | # 9 | # For documentation on the .subline-syntax format: 10 | # https://www.sublimetext.com/docs/syntax.html 11 | # 12 | # Regex's in this file support the Oniguruma regex engine: 13 | # https://raw.githubusercontent.com/kkos/oniguruma/5.9.6/doc/RE 14 | # 15 | --- 16 | name: Terraform (variables) 17 | scope: source.terraform-vars 18 | version: 2 19 | 20 | extends: Terraform.sublime-syntax 21 | 22 | # File Extensions: 23 | # 24 | # - ".tfvars": variables definitions file 25 | # https://www.terraform.io/docs/configuration/variables.html#variable-definitions-tfvars-files 26 | file_extensions: 27 | - tfvars 28 | -------------------------------------------------------------------------------- /messages/2.0.0.md: -------------------------------------------------------------------------------- 1 | v2.0.0 - 2025-05-11 2 | ------------------- 3 | 4 | The package has been adopted by the SublimeText GitHub org and now lives at 5 | for the community to maintain. 6 | This is accompanied by many changes 7 | to bring the syntax definition up to current standards, 8 | courtesy of @deathaxe, @FichteFoll, and @michaelblyons. 9 | 10 | In summary, the syntax has been aligned with current standards 11 | as they have developed over time for the default syntaxes 12 | and various other third-party syntaxes. 13 | For a detailed list of changes, 14 | please refer to the full changelog at 15 | . 16 | 17 | Note that this release is only compatible with ST builds 4180 and higher. 18 | The old version is still available for installation on older builds 19 | but is not maintained anymore. 20 | -------------------------------------------------------------------------------- /Indentation Rules.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | scope 5 | source.hcl, source.terraform, source.terraform-vars 6 | settings 7 | 8 | decreaseIndentPattern 9 | ^\s*[])}] 10 | increaseIndentPattern 11 | 19 | indentParens 20 | 21 | indentSquareBrackets 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform 2 | 3 | [Terraform][.tf] configuration file syntax definitions and snippets for [Sublime Text][]. 4 | 5 | ![preview](preview.png) 6 | 7 | 8 | ## Installation 9 | 10 | ### Using Package Control 11 | 12 | 1. Install [Package Control][], if needed. 13 | 2. Open the palette by pressing: 14 | - Windows, Linux: Ctrl+Shift+P 15 | - MacOS: Cmd+Shift+P 16 | 3. Select _Package Control: Install Package_. 17 | 4. Select _Terraform_. 18 | 19 | ### Manually 20 | 21 | 1. Open the Sublime Text Packages folder: 22 | - MacOS: `~/Library/Application Support/Sublime Text/Packages/` 23 | - Windows: `%APPDATA%/Sublime Text/Packages/` 24 | - Linux (Ubuntu/Debian): `~/.config/sublime-text/Packages/` 25 | 2. Clone this repo. 26 | 27 | [sublime text]: https://sublimetext.com/ 28 | [.tf]: https://developer.hashicorp.com/terraform/language/syntax/configuration 29 | [package control]: https://packagecontrol.io/installation 30 | -------------------------------------------------------------------------------- /Comments.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Comments 7 | scope 8 | source.terraform, source.terraform-vars, source.hcl 9 | settings 10 | 11 | shellVariables 12 | 13 | 14 | name 15 | TM_COMMENT_START 16 | value 17 | # 18 | 19 | 20 | name 21 | TM_COMMENT_START_2 22 | value 23 | /* 24 | 25 | 26 | name 27 | TM_COMMENT_END_2 28 | value 29 | */ 30 | 31 | 32 | name 33 | TM_COMMENT_START_3 34 | value 35 | // 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Alex Louden 4 | Copyright (c) 2024 FichteFoll 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /Fold.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | scope 5 | source.hcl, source.terraform, source.terraform-vars 6 | settings 7 | 8 | indentationFoldingEnabled 9 | 10 | foldScopes 11 | 12 | 13 | 14 | begin 15 | punctuation.section.baces.begin 16 | end 17 | punctuation.section.baces.end 18 | excludeTrailingNewlines 19 | 20 | 21 | 22 | begin 23 | punctuation.section.brackets.begin 24 | end 25 | punctuation.section.brackets.end 26 | excludeTrailingNewlines 27 | 28 | 29 | 30 | begin 31 | punctuation.section.parens.begin 32 | end 33 | punctuation.section.parens.end 34 | excludeTrailingNewlines 35 | 36 | 37 | 38 | 39 | 40 | begin 41 | punctuation.section.block.begin 42 | end 43 | punctuation.section.block.end 44 | excludeTrailingNewlines 45 | 46 | 47 | 48 | 49 | 50 | begin 51 | punctuation.section.mapping.begin 52 | end 53 | punctuation.section.mapping.end 54 | excludeTrailingNewlines 55 | 56 | 57 | 58 | begin 59 | punctuation.section.sequence.begin 60 | end 61 | punctuation.section.sequence.end 62 | excludeTrailingNewlines 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Terraform Plan.sublime-syntax: -------------------------------------------------------------------------------- 1 | %YAML 1.2 2 | --- 3 | # http://www.sublimetext.com/docs/syntax.html 4 | # https://github.com/hashicorp/terraform/blob/337bf8e11b75dff87509455cabee60b023dd586e/internal/command/jsonformat/plan.go#L201 5 | name: Terraform Plan 6 | scope: source.diff.terraform 7 | version: 2 8 | 9 | file_extensions: 10 | - tfplan 11 | - tf.plan 12 | 13 | contexts: 14 | 15 | main: 16 | - include: comments 17 | - include: diffs 18 | - include: summary 19 | 20 | comments: 21 | - match: '#' 22 | scope: punctuation.definition.comment.terraform 23 | push: 24 | - meta_scope: comment.line.number-sign.terraform 25 | - include: pop-eol 26 | 27 | diffs: 28 | - match: ^\+/- 29 | scope: punctuation.definition.changed.diff 30 | push: line-created-then-destroyed 31 | - match: ^-/\+ 32 | scope: punctuation.definition.changed.diff 33 | push: line-destroyed-then-created 34 | - match: ^! 35 | scope: punctuation.definition.changed.diff 36 | push: line-changed 37 | - match: ^\+ 38 | scope: punctuation.definition.inserted.diff 39 | push: line-inserted 40 | - match: ^- 41 | scope: punctuation.definition.deleted.diff 42 | push: line-deleted 43 | 44 | annotations: 45 | - match: -> 46 | scope: keyword.operator.assignment.terraform 47 | - match: \(known after apply\)$ 48 | scope: comment.block.terraform 49 | - match: \bnull$ 50 | scope: constant.language.null.terraform 51 | 52 | line-deleted: 53 | - meta_scope: markup.deleted.diff 54 | - include: pop-eol 55 | - include: annotations 56 | 57 | line-inserted: 58 | - meta_scope: markup.inserted.diff 59 | - include: pop-eol 60 | - include: annotations 61 | 62 | line-changed: 63 | - meta_scope: markup.changed.updated-in-place.diff 64 | - include: pop-eol 65 | - include: annotations 66 | 67 | line-created-then-destroyed: 68 | - meta_scope: markup.changed.created-then-destroyed.diff 69 | - include: pop-eol 70 | - include: annotations 71 | 72 | line-destroyed-then-created: 73 | - meta_scope: markup.changed.destroyed-then-created.diff 74 | - include: pop-eol 75 | - include: annotations 76 | 77 | line-ignored: 78 | - meta_scope: comment.line.diff 79 | - include: pop-eol 80 | - include: annotations 81 | 82 | summary: 83 | - match: ^(?=Plan:[ ]\d) 84 | push: 85 | - meta_scope: meta.block.summary.terraform 86 | - include: pop-eol 87 | - match: ',' 88 | scope: punctuation.separator.sequence.terraform 89 | - match: \. 90 | scope: punctuation.terminator.terraform 91 | - match: (\d+) to add 92 | scope: markup.inserted.terraform 93 | captures: 94 | 1: meta.number.integer.decimal.terraform constant.numeric.value.terraform 95 | - match: (\d+) to change 96 | scope: markup.changed.terraform 97 | captures: 98 | 1: meta.number.integer.decimal.terraform constant.numeric.value.terraform 99 | - match: (\d+) to destroy 100 | scope: markup.deleted.terraform 101 | captures: 102 | 1: meta.number.integer.decimal.terraform constant.numeric.value.terraform 103 | 104 | pop-eol: 105 | - match: \n|$ 106 | pop: 1 107 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## v2.0.1 - 2025-12-07 8 | 9 | - Fix indexed symbol scope selector leaking into other languages. (@FichteFoll, #99) 10 | - Add support for template literal escape sequence. (@yagizmunger, #97, #98) 11 | 12 | --- 13 | 14 | ## v2.0.0 - 2025-05-11 15 | 16 | The package has been adopted by the SublimeText GitHub org and now lives at 17 | for the community to maintain. 18 | This is accompanied by many changes 19 | to bring the syntax definition up to current standards. 20 | 21 | ### Added 22 | 23 | - Declare hyphens as sub-word separators. (@FichteFoll, #60) 24 | - Special highlighting for `for_each` and `count` meta arguments (`keyword.control`). (@FichteFoll, #59) 25 | - Highlighting of more special language variables: `each`, `count` and `self`. (@FichteFoll, #58) 26 | - Highlighting for `ephemeral` blocks. (@TerminalFi, #70) 27 | - A separate syntax definition for `terraform plan` output (@michaelblyons, #51, #68) 28 | - Special highlighting for AWS ACL resource references in strings. (@michaelblyons, @deathaxe, #69, #76) 29 | - Support JSON-style objects (requires ST 4180). (@michaelblyons, #54, #71) 30 | - Scope-based folding rules. (@deathaxe, #81) 31 | - Consistent indentation rules. (@deathaxe, #82) 32 | - Highlight unclosed strings and stray closing brackets as illegal. (@FichteFoll, #91) 33 | 34 | ### Changed 35 | 36 | - Switched to syntax version 2. 37 | This breaks compatibility with ST builds before 4000, 38 | but the previous version can still be installed on older builds. 39 | (@FichteFoll, #62) 40 | - Adapted and improved many scope names to standards that have been established 41 | over the past years for the default packages: 42 | * String interpolation meta scopes and punctuation (@FichteFoll, #58) 43 | * Keywords (@FichteFoll, @deathaxe, #58, #78, #86) 44 | * Attribute access punctuation (@FichteFoll, #58) 45 | * Punctuation scopes in `for` expressions (@FichteFoll, #58) 46 | * Blocks, including indexing for "name" labels 47 | (@michaelblyons, @FichteFoll, #69, #87) 48 | * Operators (@michaelblyons, #66) 49 | * Numbers (@deathaxe, #77) 50 | * Brackets (@deathaxe, #80) 51 | * Function calls (@deathaxe, #83) 52 | - Updated the built-in function list for highlighting. (@FichteFoll, #59) 53 | - Renamed many contexts and resolved various anonymous contexts 54 | for better extensibility. (@deathaxe, #75, #79) 55 | 56 | ### Removed 57 | 58 | - Removed various files targeting older ST versions, 59 | notably the old `.tmLanguage` syntax definition. 60 | This breaks compatibility with ST 2, 61 | but the previous version can still be installed on older builds. 62 | (@FichteFoll, #63) 63 | 64 | ### Fixed 65 | 66 | - Improved matching of identifiers by adding a scope and properly recognizing hyphens. (@FichteFoll, #60) 67 | - Support identifiers starting with an underscore character (@FichteFoll, #43, #64). 68 | 69 | --- 70 | 71 | ## v1.3.1 - 2024-02-03 72 | 73 | ### Added 74 | 75 | - `.nomad` files are also recognized by the Terraform syntax. (@Quenty, #55) 76 | 77 | ## v1.3.0 - 2024-01-18 78 | 79 | ### Changed 80 | 81 | - Separate HCL syntax into its own file and report it as `source.hcl` (rather than `source.terraform`). (@rchl, #56) 82 | - Update links to official docs on terraform.io. (@totoroot, #53) 83 | 84 | ## v1.2.0 - 2021-06-21 85 | 86 | ### Changed 87 | 88 | - Split the tfvars handling into a separate syntax file. (@rchl, #49)
89 | This improves interoperability with terraform-ls, e.g. via LSP. 90 | 91 | ## v1.1.0 - 2021-05-17 92 | 93 | ### Fixed 94 | 95 | - Removed quotes around variable types in snippets. (@notnmeyer, #42) 96 | 97 | ## v1.0.0 - 2020-01-20 98 | 99 | A huge thanks to @patrickrgaffney for this amazing contribution. (#39) 100 | 101 | ### Added 102 | 103 | - [Syntax tests][tests] have been added. 104 | - `null` constant. 105 | - [Exponents][exponents] in numeric literals. 106 | - [Character escapes][strings] for newline, carriage return, backslash, quote, and unicode points inside string literals. 107 | - [Trim-left and trim-right operators][string-templates] inside string templates. 108 | - [Directives][string-templates] inside string templates. 109 | - Match all valid expressions inside string templates. 110 | - Comparison operators `==`, `!=`, `<`, `>`, `<=`, `>=`. 111 | - Arithmetic operators `+`, `-`, `*`, `/`, `%`. 112 | - Logic operators `&&`, `||`, `!`. 113 | - Conditional operator `p ? e1 : e2` 114 | - Parenthesis matching. 115 | - Tuple list syntax. 116 | - Square-bracket [index notation][indices]. 117 | - [Full-splat][splat] operator. 118 | - Comma matching inside function calls, tuples, maps, and for-expressions. 119 | - Attribute-access is matched on named members and the `.` dot operator. 120 | - [Attribute-only splat][splat] operator. 121 | - Allow `-` after first alpha character in identifiers. 122 | - Computed attribute named using parenthesis. 123 | - Allow function-calls outside of string interpolation. 124 | - Match all valid expressions inside function-call parameter lists. 125 | - Match functions unknown to Terraform (for other HCL uses). 126 | - Match [for-expressions][for-exp] inside tuples and maps. 127 | - Map collection syntax. 128 | - Match unknown block names. 129 | - Support for variable number of block labels. 130 | - Nested blocks. 131 | - Inline blocks. 132 | - Terraform [named values][named-values]. 133 | - Update list of built-in Terraform functions. 134 | - Built-in block types `locals` and `terraform`. 135 | - Meta-scope `meta.block.terraform` added to all block bodies. 136 | - [Primitive type constants][types]. 137 | - Heredocs with the leading-spaces operator `<<-`. 138 | - String interpolation inside heredocs. 139 | - [Import][import] statements. 140 | - JSON highlighting for `*.tfstate` files. 141 | 142 | ### Changed 143 | 144 | - Rename scope `comment.line.number-sign.terraform` to `comment.line.terraform` to better reflect [scope naming standards][scopes]. 145 | - Rename scope `constant.numeric.terraform` to `constant.numeric.[integer|float].terraform` to better reflect [scope naming standards][scopes]. 146 | - Rename scope `entity.tag.embedded.[begin|end]` to `punctuation.section.interpolation.[begin|end]` to better reflect [scope naming standards][scopes]. 147 | - Rename scope `variable.other.assignment.terraform` to `variable.other.readwrite.terraform` to better reflect [scope naming standards][scopes]. 148 | - A `meta_scope` of `variable.declaration.terraform` covers the entire attribute definition now. 149 | - Rename scope for `=` in assignments from `keyword.operator` to `keyword.operator.assignment` to better reflect [scope naming standards][scopes]. 150 | - Rename scope `keyword.other.function.inline` to `support.function.builtin` to better reflect [scope naming standards][scopes]. 151 | - Rename scope for known block types from `storage.type.function.terraform` to `storage.type.terraform` to better reflect [scope naming standards][scopes]. 152 | - Rename scope for block labels from `string.value.terraform` to `string.quoted.double.terraform` to better reflect [scope naming standards][scopes]. 153 | - Rename meta-scope for block definitions from `meta.block.terraform` to `meta.type.terraform` to better reflect [scope naming standards][scopes]. 154 | 155 | ### Removed 156 | 157 | - Invalid constants `yes`, `no`, `on`, and `off`. 158 | - [Unit of measurement suffixes][uom-suffixes]. 159 | - [Hexadecimal literals][hex-literals]. 160 | - An extra `string.terraform` scope was previously added to all string literals. 161 | - [`atlas` blocks][atlas]. 162 | 163 | ### Fixed 164 | 165 | - Remove the `string.*` scope inside string templates. 166 | 167 | ## v0.19.0 - 2019-08-20 168 | 169 | ### Added 170 | 171 | - Symbol indexing for top-level blocks. (@patrickrgaffney - #38) 172 | 173 | ## v0.18.0 - 2019-07-01 174 | 175 | ### Added 176 | 177 | - Update list of built-in functions. (@Tenzer - #37) 178 | 179 | ### Fixed 180 | 181 | - Allow hyphens in names of attributes inside string interpolation. (@Tenzer - #37) 182 | 183 | ## v0.17.0 - 2019-01-25 184 | 185 | ### Added 186 | 187 | - [Sublime syntax][subl-format] format. (@thiagoalmeidasa - #35) 188 | 189 | ### Fixed 190 | 191 | - Better support for parenthesis inside string interpolation. (@NightsPaladin - #33) 192 | 193 | ## v0.16.0 - 2018-08-08 194 | 195 | ### Added 196 | 197 | - Snippet for `data` blocks. (@mschurenko - #32) 198 | 199 | ## v0.15.0 - 2018-02-22 200 | 201 | ### Added 202 | 203 | - Terraform constant `local`. (@digitalfiz - #30) 204 | 205 | ## v0.14.0 - 2017-08-31 206 | 207 | ### Added 208 | 209 | - Update list of built-in functions. (@gburiola - #27) 210 | 211 | ### Removed 212 | 213 | - Built-in function `from`. 214 | 215 | ## v0.13.1 - 2017-08-10 216 | 217 | ### Fixed 218 | 219 | - Allow nested function calls. 220 | 221 | ## v0.13.0 - 2017-06-07 222 | 223 | ### Changed 224 | 225 | - Set default tab size to 2. (@kushmansingh - #25) 226 | - Set default indentation to spaces. (@kushmansingh - #25) 227 | 228 | ## v0.12.2 - 2017-05-08 229 | 230 | ### Fixed 231 | 232 | - Allow whitespace before `<<` when closing heredocs. (@GreatFruitOmsk - #24) 233 | 234 | ## v0.12.1 - 2017-03-31 235 | 236 | ### Fixed 237 | 238 | - Escape hyphens in block labels 239 | 240 | ## v0.12.0 - 2017-03-30 241 | 242 | ### Added 243 | 244 | - Code folding markers. 245 | - Built-in Terraform functions. 246 | 247 | ### Fixed 248 | 249 | - Function calls and attribute access inside string templates. 250 | 251 | ## v0.11.0 - 2017-03-08 252 | 253 | ### Added 254 | 255 | - Heredocs. 256 | 257 | ## v0.10.0 - 2017-02-14 258 | 259 | ### Added 260 | 261 | - `.hcl` file extensions (@akarnani - #19) 262 | 263 | ## v0.9.0 - 2017-02-12 264 | 265 | ### Fixed 266 | 267 | - Handle nested string interpolation. 268 | 269 | ## v0.8.0 - 2017-02-08 270 | 271 | ### Added 272 | 273 | - String interpolation. 274 | - Unquoted block labels. 275 | 276 | ### Fixed 277 | 278 | - De-emphasize variable assignment. 279 | 280 | ## v0.7.0 - 2017-01-10 281 | 282 | ### Added 283 | 284 | - C-style single line comments `//`. (@kerma - #16) 285 | 286 | ## v0.6.0 - 2016-09-08 287 | 288 | ### Added 289 | 290 | - Support for `data` blocks. (@Jonnymcc - #14) 291 | 292 | ## v0.5.0 - 2016-07-05 293 | 294 | ### Added 295 | 296 | - Snippet for `provisioner` blocks. (@ApsOps - #13) 297 | 298 | ## v0.4.0 - 2016-06-08 299 | 300 | ### Added 301 | 302 | - Match opening/closing brackets. (@alexlouden - #12) 303 | 304 | ## v0.3.0 - 2016-06-08 305 | 306 | ### Added 307 | 308 | - Snippets for `module` blocks. (@maplebed - #10) 309 | 310 | ## v0.2.0 - 2016-03-01 311 | 312 | ### Added 313 | 314 | - Blocks comments `/* ... */`. (@bigkraig - #8) 315 | 316 | ## v0.1.0 - 2015-08-04 317 | 318 | Initial release. 319 | 320 | [atlas]: https://www.terraform.io/docs/configuration/terraform-enterprise.html 321 | [exponents]: https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#numeric-literals 322 | [hex-literals]: https://github.com/hashicorp/terraform/issues/20933#issuecomment-480050478 323 | [for-exp]: https://www.terraform.io/docs/configuration/expressions.html#for-expressions 324 | [import]: https://www.terraform.io/docs/import/usage.html 325 | [indices]: https://www.terraform.io/docs/configuration/expressions.html#indices-and-attributes 326 | [named-values]: https://www.terraform.io/docs/configuration/expressions.html#references-to-named-values 327 | [old-splat]: https://www.terraform.io/docs/configuration/expressions.html#legacy-attribute-only-splat-expressions 328 | [scopes]: https://www.sublimetext.com/docs/scope_naming.html 329 | [splat]: https://www.terraform.io/docs/configuration/expressions.html#splat-expressions 330 | [string-templates]: https://www.terraform.io/docs/configuration/expressions.html#string-literals 331 | [strings]: https://www.terraform.io/docs/configuration/expressions.html#string-literals 332 | [subl-format]: https://www.sublimetext.com/docs/syntax.html 333 | [tests]: https://www.sublimetext.com/docs/syntax.html#testing 334 | [types]: https://www.terraform.io/docs/configuration/types.html 335 | [uom-suffixes]: https://github.com/hashicorp/terraform/issues/3287#issuecomment-241560576 336 | -------------------------------------------------------------------------------- /Terraform.sublime-syntax: -------------------------------------------------------------------------------- 1 | %YAML 1.2 2 | # 3 | # This syntax definition is based on the Terraform guide: 4 | # https://www.terraform.io/docs/language/index.html 5 | # 6 | # As well as the HCL Native Syntax Spec: 7 | # https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md 8 | # (previously https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md) 9 | # 10 | # For documentation on the .subline-syntax format: 11 | # https://www.sublimetext.com/docs/syntax.html 12 | # 13 | # Regex's in this file support the Oniguruma regex engine: 14 | # https://raw.githubusercontent.com/kkos/oniguruma/5.9.6/doc/RE 15 | # 16 | --- 17 | name: Terraform 18 | scope: source.terraform 19 | version: 2 20 | 21 | # File Extensions: 22 | # 23 | # - ".tf": the standard file extension 24 | # https://www.terraform.io/docs/language/index.html 25 | file_extensions: 26 | - tf 27 | - nomad 28 | 29 | variables: 30 | # Identifiers: ID_Start (ID_Continue | '-')*; 31 | # 32 | # There is an undocumented exception 33 | # that an underscore character is also accepted 34 | # as an id start character. 35 | # 36 | # https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#identifiers 37 | # http://unicode.org/reports/tr31/#Table_Lexical_Classes_for_Identifiers 38 | ID_Start: '[\p{ID_Start}_]' 39 | ID_Continue: '[\p{ID_Continue}-]' 40 | identifier: (?:{{ID_Start}}{{ID_Continue}}*) 41 | 42 | # Exponent: "e" or "E" followed by an optional sign 43 | # 44 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#numeric-literals 45 | exponent: ([Ee][+-]?) 46 | 47 | # Character Escapes: 48 | # 49 | # - \n: newline 50 | # - \r: carriage return 51 | # - \t: tab 52 | # - \": quote 53 | # - \\: backslash 54 | # - \uNNNN: unicode char (NNNN is 4 hex digits) 55 | # - \uNNNNNNNN: unicode char (NNNNNNNN us 8 digits) 56 | # 57 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#template-expressions 58 | char_escapes: \\[nrt"\\]|\\u(\h{8}|\h{4}) 59 | 60 | # String literals (basically static and single-line strings) 61 | # for usage in look-aheads. 62 | # 63 | # https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#template-expressions 64 | string_literal: '"(?:[^"]|{{char_escapes}})*"' 65 | 66 | # Template literals 67 | # 68 | # https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#template-literals 69 | template_literal: '(?:\$\$|%%)\{' 70 | 71 | # A block label 72 | # 73 | # https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#structural-elements 74 | label: (?:{{identifier}}|{{string_literal}}) 75 | 76 | # Terraform Named Values 77 | # 78 | # https://www.terraform.io/docs/language/expressions/references.html 79 | named_values: (?:var|local|module|data|path|terraform|each|count|self) 80 | 81 | # Block types that are known to Terraform. 82 | # 83 | # data: https://developer.hashicorp.com/terraform/language/data-sources 84 | # ephemeral: https://developer.hashicorp.com/terraform/language/resources/ephemeral 85 | # resource: https://developer.hashicorp.com/terraform/language/resources/syntax 86 | terraform_typed_and_named_blocks: (?:data|ephemeral|resource) 87 | # module: https://developer.hashicorp.com/terraform/language/modules/syntax 88 | # output: https://developer.hashicorp.com/terraform/language/values/outputs 89 | # provider: https://developer.hashicorp.com/terraform/language/providers/configuration 90 | # variable: https://developer.hashicorp.com/terraform/language/values/variables 91 | terraform_named_blocks: (?:module|output|provider|variable) 92 | # locals: https://developer.hashicorp.com/terraform/language/values/locals 93 | # terraform: https://developer.hashicorp.com/terraform/language/terraform#terraform-block-syntax 94 | # (Currently unused because they do not have special behavior implemented.) 95 | terraform_other_blocks: (?:locals|terraform) 96 | 97 | # Terraform built-in type keywords 98 | # 99 | # https://www.terraform.io/docs/language/expressions/type-constraints.html#primitive-types 100 | # https://www.terraform.io/docs/language/expressions/type-constraints.html#dynamic-types-the-quot-any-quot-constraint 101 | terraform_type_keywords: (?:any|string|number|bool) 102 | 103 | # Built-In Functions 104 | # 105 | # https://developer.hashicorp.com/terraform/language/functions 106 | builtin_functions: |- 107 | (?x: 108 | # numbers 109 | abs | ceil | floor | log | max | min | parseint | pow | signum 110 | # string 111 | | chomp | endswith | format | formatlist | indent | join | lower | regex 112 | | regexall | replace | split | startswith | strcontains | strrev | substr 113 | | templatestring | title | trim | trimprefix | trimsuffix | trimspace | upper 114 | # collection 115 | | alltrue | anytrue | chunklist | coalesce | coalescelist | compact | concat 116 | | contains | distinct | element | flatten | index | keys | length | list 117 | | lookup | map | matchkeys | merge | one | range | reverse | setintersection 118 | | setproduct | setsubtract | setunion | slice | sort | sum | transpose 119 | | values | zipmap 120 | # encoding 121 | | base64decode | base64encode | base64gzip | csvdecode | jsondecode 122 | | jsonencode | textdecodebase64 | textencodebase64 | urlencode | yamldecode 123 | | yamlencode 124 | # filesystem 125 | | abspath | dirname | pathexpand | basename | file | fileexists | fileset 126 | | filebase64 | templatefile 127 | # date and time 128 | | formatdate | plantimestamp | timeadd | timecmp | timestamp 129 | # hash and crypto 130 | | base64sha256 | base64sha512 | bcrypt | filebase64sha256 131 | | filebase64sha512 | filemd5 | filesha1 | filesha256 | filesha512 | md5 132 | | rsadecrypt | sha1 | sha256 | sha512 | uuid | uuidv5 133 | # ip network 134 | | cidrhost | cidrnetmask | cidrsubnet | cidrsubnets 135 | # type conversion 136 | | can | issensitive | nonsensitive | sensitive | tobool | tolist | tomap 137 | | tonumber | toset | tostring | try | type 138 | # terraform-specific 139 | | provider::terraform::(?:encode_tfvars | decode_tfvars | encode_expr) 140 | # deprecated/old 141 | | filemd1 142 | ) 143 | 144 | contexts: 145 | main: 146 | - include: comments 147 | - include: attribute-definition 148 | - include: imports 149 | - include: blocks 150 | - include: expressions 151 | 152 | comments: 153 | - include: inline-comments 154 | - include: block-comments 155 | 156 | # Expressions: 157 | # 158 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#expression-terms 159 | expressions: 160 | - include: literals 161 | - include: operators 162 | - include: brackets 163 | - include: objects 164 | - include: attribute-access 165 | - include: functions 166 | - include: parens 167 | - include: identifiers 168 | - include: illegal-strays 169 | 170 | comma: 171 | - match: \, 172 | comment: Commas - used in certain expressions 173 | scope: punctuation.separator.terraform 174 | 175 | parens: 176 | - match: \( 177 | scope: punctuation.section.parens.begin.terraform 178 | comment: Parens - matched *after* function syntax 179 | push: paren-body 180 | 181 | paren-body: 182 | - meta_scope: meta.parens.terraform 183 | - match: \) 184 | scope: punctuation.section.parens.end.terraform 185 | pop: 1 186 | - include: expressions 187 | 188 | # Literal Values: Numbers, Language Constants, and Strings 189 | # 190 | # Strings are _technically_ part of the "expression sub-language", 191 | # but make the most sense to be part of this stack. 192 | # 193 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#literal-values 194 | literals: 195 | - include: numeric-literals 196 | - include: language-constants 197 | - include: string-literals 198 | - include: heredoc 199 | - include: type-keywords 200 | - include: named-value-references 201 | 202 | named-value-references: 203 | - match: \b{{named_values}}\b 204 | comment: Special variables available only to Terraform. 205 | scope: variable.language.terraform 206 | 207 | type-keywords: 208 | - match: \b{{terraform_type_keywords}}\b 209 | comment: Type keywords known to Terraform. 210 | scope: storage.type.terraform 211 | 212 | # Inline Comments: begin at the operator, end at the end of the line. 213 | # 214 | # https://www.terraform.io/docs/language/syntax/configuration.html#comments 215 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#comments-and-whitespace 216 | inline-comments: 217 | - match: '#|//' 218 | comment: Inline Comments 219 | scope: punctuation.definition.comment.terraform 220 | push: inline-comment-body 221 | 222 | inline-comment-body: 223 | - meta_scope: comment.line.terraform 224 | - match: $\n? 225 | scope: punctuation.definition.comment.terraform 226 | pop: 1 227 | 228 | # Block comments: start and end delimiters for multi-line comments. 229 | # 230 | # https://www.terraform.io/docs/language/syntax/configuration.html#comments 231 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#comments-and-whitespace 232 | block-comments: 233 | - match: /\* 234 | comment: Block comments 235 | scope: punctuation.definition.comment.terraform 236 | push: block-comments-body 237 | 238 | block-comments-body: 239 | - meta_scope: comment.block.terraform 240 | - match: \*/ 241 | scope: punctuation.definition.comment.terraform 242 | pop: 1 243 | 244 | # Language Constants: booleans and `null`. 245 | # 246 | # https://www.terraform.io/docs/language/expressions/types.html#literal-expressions 247 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#literal-values 248 | language-constants: 249 | - match: \btrue\b 250 | scope: constant.language.boolean.true.terraform 251 | - match: \bfalse\b 252 | scope: constant.language.boolean.false.terraform 253 | - match: \bnull\b 254 | scope: constant.language.null.terraform 255 | 256 | # Numbers: Integers, fractions and exponents 257 | # 258 | # https://www.terraform.io/docs/language/expressions/types.html 259 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#numeric-literals 260 | numeric-literals: 261 | - match: \b\d+{{exponent}}\d+\b 262 | comment: Integer, no fraction, optional exponent 263 | scope: meta.number.float.decimal.terraform constant.numeric.value.terraform 264 | - match: \b\d+(\.)\d+(?:{{exponent}}\d+)?\b 265 | comment: Integer, fraction, optional exponent 266 | scope: meta.number.float.decimal.terraform constant.numeric.value.terraform 267 | captures: 268 | 1: punctuation.separator.decimal.terraform 269 | - match: \b\d+\b 270 | comment: Integers 271 | scope: meta.number.integer.decimal.terraform constant.numeric.value.terraform 272 | 273 | # Strings: 274 | # 275 | # https://www.terraform.io/docs/language/expressions/types.html 276 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#template-expressions 277 | string-literals: 278 | - match: \" 279 | comment: Strings 280 | scope: punctuation.definition.string.begin.terraform 281 | push: string-body 282 | 283 | string-body: 284 | - meta_scope: meta.string.terraform string.quoted.double.terraform 285 | - match: \" 286 | scope: punctuation.definition.string.end.terraform 287 | pop: 1 288 | - match: \n 289 | scope: invalid.illegal.unclosed-string.terraform 290 | pop: 1 291 | - include: character-escapes 292 | - include: string-interpolation 293 | - include: aws-acl 294 | 295 | character-escapes: 296 | - match: '{{char_escapes}}' 297 | comment: Character Escapes 298 | scope: constant.character.escape.terraform 299 | 300 | template-literals: 301 | - match: '{{template_literal}}' 302 | comment: Template Literal 303 | scope: constant.character.escape.terraform 304 | 305 | aws-acl: 306 | - match: (?=\barn:aws:) 307 | push: aws-acl-body 308 | 309 | aws-acl-body: 310 | - clear_scopes: 1 # Clear the string.* scope. 311 | - meta_scope: variable.language.acl.terraform 312 | - match: ([$%]\{)(~)? 313 | captures: 314 | 1: punctuation.section.interpolation.begin.terraform 315 | 2: keyword.operator.template.trim.left.terraform 316 | push: acl-interpolation-body 317 | - match: :|/ 318 | scope: punctuation.separator.sequence.terraform 319 | - match: \* 320 | scope: constant.other.wildcard.asterisk.terraform 321 | - match: (?![\w-]) 322 | pop: 1 323 | 324 | acl-interpolation-body: 325 | - meta_scope: meta.interpolation.terraform 326 | - meta_content_scope: source.terraform 327 | - include: string-interpolation-body 328 | 329 | # String Interpolation: ("${" | "${~") Expression ("}" | "~}" 330 | # 331 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#templates 332 | string-interpolation: 333 | - include: template-literals 334 | - match: ([$%]\{)(~)? 335 | captures: 336 | 1: punctuation.section.interpolation.begin.terraform 337 | 2: keyword.operator.template.trim.left.terraform 338 | push: string-interpolation-body 339 | 340 | string-interpolation-body: 341 | - clear_scopes: 1 # Clear the string.* scope. 342 | - meta_scope: meta.interpolation.terraform 343 | - meta_content_scope: source.terraform 344 | - match: (~)?(\}) 345 | captures: 346 | 1: keyword.operator.template.trim.right.terraform 347 | 2: punctuation.section.interpolation.end.terraform 348 | pop: 1 349 | - match: \bif\b 350 | scope: keyword.control.conditional.if.terraform 351 | - match: \belse\b 352 | scope: keyword.control.conditional.else.terraform 353 | - match: \bendif\b 354 | scope: keyword.control.conditional.end.terraform 355 | - match: \bfor\b 356 | scope: keyword.control.loop.for.terraform 357 | - match: \bendfor\b 358 | scope: keyword.control.loop.end.terraform 359 | - match: \bin\b 360 | scope: keyword.control.loop.in.terraform 361 | - include: expressions 362 | 363 | # String Heredocs 364 | # 365 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#template-expressions 366 | heredoc: 367 | - match: (\<\<\-?)\s*({{identifier}})\s*$ 368 | comment: String Heredoc's 369 | captures: 370 | 1: keyword.operator.heredoc.terraform 371 | 2: keyword.control.heredoc.terraform 372 | push: heredoc-body 373 | 374 | heredoc-body: 375 | - meta_content_scope: meta.string.terraform string.unquoted.heredoc.terraform 376 | - match: ^\s*\2\s*$ 377 | comment: The heredoc token identifier (second capture above). 378 | scope: keyword.control.heredoc.terraform 379 | pop: 1 380 | - include: string-interpolation 381 | 382 | # Operators: 383 | # 384 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#operators-and-delimiters 385 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#operations 386 | operators: 387 | - match: \>\= # >= 388 | scope: keyword.operator.comparison.terraform 389 | - match: \<\= # <= 390 | scope: keyword.operator.comparison.terraform 391 | - match: \=\= # == 392 | scope: keyword.operator.comparison.terraform 393 | - match: \!\= # != 394 | scope: keyword.operator.comparison.terraform 395 | - match: \+ # + 396 | scope: keyword.operator.arithmetic.terraform 397 | - match: \- # - 398 | scope: keyword.operator.arithmetic.terraform 399 | - match: \* # * 400 | scope: keyword.operator.arithmetic.terraform 401 | - match: \/ # / 402 | scope: keyword.operator.arithmetic.terraform 403 | - match: \% # % 404 | scope: keyword.operator.arithmetic.terraform 405 | - match: \&\& # && 406 | scope: keyword.operator.logical.terraform 407 | - match: \|\| # || 408 | scope: keyword.operator.logical.terraform 409 | - match: \! # ! 410 | scope: keyword.operator.logical.terraform 411 | - match: \> # > 412 | scope: keyword.operator.comparison.terraform 413 | - match: \< # < 414 | scope: keyword.operator.comparison.terraform 415 | - match: \? # ? 416 | scope: keyword.operator.ternary.terraform 417 | - match: \.\.\. # ... 418 | scope: keyword.operator.terraform 419 | - match: ':' # : 420 | scope: keyword.operator.ternary.terraform 421 | 422 | # Terraform "import" statements 423 | # 424 | # https://www.terraform.io/docs/cli/import/usage.html 425 | imports: 426 | - match: \b(terraform)\s+(import)\b 427 | comment: Importing resources 428 | captures: 429 | 1: support.constant.terraform 430 | 2: keyword.control.import.terraform 431 | push: import-body 432 | 433 | import-body: 434 | - match: \" 435 | comment: String literal label 436 | scope: punctuation.definition.string.begin.terraform 437 | push: literal-label-body 438 | - match: '{{identifier}}' 439 | comment: Identifier label 440 | scope: entity.name.label.terraform 441 | - include: numeric-literals 442 | - include: attribute-access 443 | - match: $\n? 444 | comment: Pop at newline 445 | pop: 1 446 | 447 | literal-label-body: 448 | - meta_scope: meta.string.terraform string.quoted.double.terraform 449 | - match: \" 450 | scope: punctuation.definition.string.end.terraform 451 | pop: 1 452 | 453 | # Brackets: matches tuples and subscript notation 454 | # 455 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#index-operator 456 | brackets: 457 | - match: \[ 458 | scope: punctuation.section.brackets.begin.terraform 459 | push: bracket-body 460 | 461 | bracket-body: 462 | - meta_scope: meta.brackets.terraform 463 | - match: (\*)?\] 464 | comment: Full-splat operator 465 | scope: punctuation.section.brackets.end.terraform 466 | captures: 467 | 1: keyword.operator.splat.terraform 468 | pop: 1 469 | - include: comma 470 | - include: comments 471 | - include: tuple-for-expression 472 | - include: expressions 473 | 474 | # Objects: collection values 475 | # 476 | # Allows keys as identifiers, strings, and computed values wrapped in parens. 477 | # 478 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#collection-values 479 | objects: 480 | - match: \{ 481 | scope: punctuation.section.braces.begin.terraform 482 | push: object-body 483 | 484 | object-body: 485 | - meta_scope: meta.braces.terraform 486 | - match: \} 487 | scope: punctuation.section.braces.end.terraform 488 | pop: 1 489 | - include: object-for-expression 490 | - include: comments 491 | - match: (?=({{identifier}}|\".*?\")\s*=) 492 | push: 493 | - object-value 494 | - assignment-operator 495 | - object-literal-key 496 | - match: \( 497 | comment: Computed object key (any expression between parens) 498 | scope: punctuation.section.parens.begin.terraform 499 | push: 500 | - object-value 501 | - assignment-operator 502 | - object-computed-key 503 | - include: Packages/Terraform/JSON (Terraform).sublime-syntax#object-body 504 | 505 | object-computed-key: 506 | - meta_scope: meta.mapping.key.terraform meta.parens.terraform 507 | - include: paren-body 508 | 509 | object-literal-key: 510 | - match: '{{identifier}}' 511 | scope: meta.mapping.key.terraform meta.string.terraform string.unquoted.terraform 512 | pop: 1 513 | - match: (\").*?(\") 514 | scope: meta.mapping.key.terraform meta.string.terraform string.quoted.double.terraform 515 | captures: 516 | 1: punctuation.definition.string.begin.terraform 517 | 2: punctuation.definition.string.end.terraform 518 | pop: 1 519 | - include: else-pop 520 | 521 | assignment-operator: 522 | - match: = 523 | scope: keyword.operator.assignment.terraform 524 | pop: 1 525 | - include: else-pop 526 | 527 | # Object key values: pop at comma, newline, and closing-bracket 528 | # 529 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#collection-values 530 | object-value: 531 | - include: comments 532 | - match: \, 533 | comment: Pop scope on comma. 534 | scope: punctuation.separator.terraform 535 | pop: 1 536 | - match: $\n? 537 | comment: Pop scope on EOL. 538 | pop: 1 539 | - match: (?=\}) 540 | comment: Lookahead (don't consume) and pop scope on a bracket. 541 | scope: punctuation.section.braces.end.terraform 542 | pop: 1 543 | - include: expressions 544 | 545 | # Attribute Access: "." Identifier 546 | # 547 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#attribute-access-operator 548 | attribute-access: 549 | - match: \. 550 | scope: punctuation.accessor.dot.terraform 551 | push: member 552 | 553 | member: 554 | - include: comments 555 | - match: '{{identifier}}' 556 | comment: Attribute access 557 | scope: variable.other.member.terraform 558 | pop: 1 559 | - match: \d+ 560 | comment: Subscript 561 | scope: meta.number.integer.decimal.terraform constant.numeric.value.terraform 562 | pop: 1 563 | - match: \* 564 | comment: Attribute-only splat 565 | scope: keyword.operator.splat.terraform 566 | pop: 1 567 | - include: else-pop 568 | 569 | # Attribute Definition: Identifier "=" Expression Newline 570 | # 571 | # The "=" operator cannot be immediately followed by "=" 572 | # ">", as those are other operators, not attr definitions. 573 | # 574 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#attribute-definitions 575 | attribute-definition: 576 | - match: (?=(\()?({{identifier}})(\))?\s*(\=(?![\=\>]))) 577 | push: 578 | - assignment-operator 579 | - attribute-key 580 | 581 | attribute-key: 582 | - match: \((?={{identifier}}\)) 583 | scope: punctuation.section.parens.begin.terraform 584 | set: 585 | - attribute-key-end 586 | - attribute-key 587 | # https://developer.hashicorp.com/terraform/language/meta-arguments/for_each 588 | - match: for_each\b 589 | scope: variable.declaration.terraform keyword.control.loop.for.terraform 590 | pop: 1 591 | # https://developer.hashicorp.com/terraform/language/meta-arguments/count 592 | - match: count\b 593 | scope: variable.declaration.terraform keyword.control.conditional.terraform 594 | pop: 1 595 | - match: '{{identifier}}' 596 | scope: variable.declaration.terraform variable.other.readwrite.terraform 597 | pop: 1 598 | 599 | attribute-key-end: 600 | - meta_scope: meta.parens.terraform 601 | - match: \) 602 | scope: punctuation.section.parens.end.terraform 603 | pop: 1 604 | 605 | # Functions: Terraform builtins and unknown 606 | # 607 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#functions-and-function-calls 608 | # https://www.terraform.io/docs/language/expressions/function-calls.html 609 | functions: 610 | - match: (?={{builtin_functions}}\() 611 | push: builtin-function-name 612 | - match: (?=(?:{{identifier}}::)*{{identifier}}\() 613 | push: other-function-name 614 | 615 | builtin-function-name: 616 | - meta_content_scope: meta.function-call.identifier.terraform 617 | - include: function-argument-list 618 | - include: namespaces 619 | - match: '{{identifier}}' 620 | scope: support.function.builtin.terraform 621 | 622 | other-function-name: 623 | - meta_content_scope: meta.function-call.identifier.terraform 624 | - include: function-argument-list 625 | - include: namespaces 626 | - match: '{{identifier}}' 627 | scope: variable.function.terraform 628 | 629 | function-argument-list: 630 | - match: \( 631 | scope: punctuation.section.parens.begin.terraform 632 | set: function-argument-list-body 633 | 634 | function-argument-list-body: 635 | - meta_scope: meta.function-call.arguments.terraform meta.parens.terraform 636 | - match: \) 637 | scope: punctuation.section.parens.end.terraform 638 | pop: 1 639 | - include: comments 640 | - include: expressions 641 | - include: comma 642 | 643 | # Tuple for-Expression: 644 | # 645 | # "[" "for" Identifier ("," Identifier)? "in" Expression ":" Expression ("if" Expression)? "]"; 646 | # 647 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#for-expressions 648 | # https://www.terraform.io/docs/language/expressions/for.html 649 | tuple-for-expression: 650 | - match: \bfor\b 651 | comment: for expression (arrays) 652 | scope: keyword.control.loop.for.terraform 653 | set: tuple-for-expression-body 654 | 655 | tuple-for-expression-body: 656 | - meta_content_scope: meta.brackets.terraform 657 | - match: \] 658 | scope: meta.brackets.terraform punctuation.section.brackets.end.terraform 659 | pop: 1 660 | - include: for-expression-body 661 | 662 | # Object for-Expression: 663 | # 664 | # "{" "for" Identifier ("," Identifier)? "in" Expression ":" Expression "=>" Expression "..."? ("if" Expression)? "}"; 665 | # 666 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#for-expressions 667 | # https://www.terraform.io/docs/language/expressions/for.html 668 | object-for-expression: 669 | - match: \bfor\b 670 | comment: for expression (arrays) 671 | scope: keyword.control.loop.for.terraform 672 | set: object-for-expression-body 673 | 674 | object-for-expression-body: 675 | - meta_content_scope: meta.braces.terraform 676 | - match: \} 677 | scope: meta.braces.terraform punctuation.section.braces.end.terraform 678 | pop: 1 679 | - match: \=\> 680 | scope: punctuation.separator.key-value.terraform 681 | - include: for-expression-body 682 | 683 | # Shared body syntax for tuple and object for-expressions. 684 | # They require different `set` blocks because they are 685 | # pop'd with different characters and objects allow `=>`. 686 | for-expression-body: 687 | - match: \bin\b 688 | scope: keyword.operator.iteration.in.terraform 689 | - match: \bif\b 690 | scope: keyword.control.conditional.terraform 691 | - match: '\:' 692 | scope: punctuation.section.block.loop.for.terraform 693 | - include: expressions 694 | - include: comments 695 | - include: comma 696 | 697 | namespaces: 698 | - match: ({{identifier}})(::) 699 | captures: 700 | 1: variable.namespace.terraform 701 | 2: punctuation.accessor.double-colon.terraform 702 | 703 | identifiers: 704 | - match: '{{identifier}}' 705 | scope: variable.other.readwrite.terraform 706 | 707 | illegal-strays: 708 | - match: '[\])}]' 709 | scope: invalid.illegal.stray.terraform 710 | 711 | # Blocks: Identifier (StringLit|Identifier)* "{" Newline Body "}" Newline; 712 | # 713 | # https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md#structural-elements 714 | blocks: 715 | - include: typed-and-named-blocks 716 | - include: named-blocks 717 | - include: generic-blocks 718 | 719 | typed-and-named-blocks: 720 | # Special case for two-label resources, 721 | # where the first denotes the type and the second the name. 722 | - match: (?=\b{{terraform_typed_and_named_blocks}}(\s+{{label}}){2}\s*\{) 723 | push: 724 | - body 725 | - block-name-label 726 | - block-type-label 727 | - block-declaration 728 | 729 | named-blocks: 730 | # Special case for two-label resources, 731 | # where the first denotes the type and the second the name. 732 | - match: (?=\b{{terraform_named_blocks}}\s+{{label}}\s*\{) 733 | push: 734 | - body 735 | - block-name-label 736 | - block-declaration 737 | 738 | generic-blocks: 739 | - match: (?=\b({{identifier}})(\s+{{label}})*\s*\{) 740 | push: 741 | - body 742 | - generic-block-labels 743 | - block-declaration 744 | 745 | block-declaration: 746 | - match: '{{identifier}}' 747 | scope: keyword.declaration.terraform 748 | pop: 1 749 | - include: else-pop 750 | 751 | block-type-label: 752 | - match: \" 753 | scope: punctuation.definition.string.begin.terraform 754 | set: block-type-label-body 755 | - match: '{{identifier}}' 756 | scope: support.type.terraform 757 | pop: 1 758 | - include: else-pop 759 | 760 | block-type-label-body: 761 | - meta_scope: meta.string.terraform 762 | - meta_content_scope: support.type.terraform 763 | - match: \" 764 | scope: punctuation.definition.string.end.terraform 765 | pop: 1 766 | - include: character-escapes 767 | 768 | block-name-label: 769 | - match: \" 770 | scope: punctuation.definition.string.begin.terraform 771 | set: block-name-label-body 772 | - match: '{{identifier}}' 773 | scope: entity.name.label.terraform 774 | pop: 1 775 | - include: else-pop 776 | 777 | block-name-label-body: 778 | - meta_scope: meta.string.terraform 779 | - meta_content_scope: entity.name.label.terraform 780 | - match: \" 781 | scope: punctuation.definition.string.end.terraform 782 | pop: 1 783 | - include: character-escapes 784 | 785 | generic-block-labels: 786 | # Labels probably have a meaning, but we don't know which, 787 | # so we just scope them as (un-)quoted strings. 788 | - match: \" 789 | scope: punctuation.definition.string.begin.terraform 790 | push: generic-block-label-body 791 | - match: '{{identifier}}' 792 | scope: string.unquoted.double.terraform 793 | - include: else-pop 794 | 795 | generic-block-label-body: 796 | - meta_scope: meta.string.terraform string.quoted.double.terraform 797 | - match: \" 798 | scope: punctuation.definition.string.end.terraform 799 | pop: 1 800 | - include: character-escapes 801 | 802 | body: 803 | - meta_content_scope: meta.block.head.terraform 804 | - match: \{ 805 | scope: punctuation.section.block.begin.terraform 806 | set: body-body 807 | - include: else-pop 808 | 809 | body-body: 810 | - meta_scope: meta.block.body.terraform 811 | - match: \} 812 | scope: punctuation.section.block.end.terraform 813 | pop: 1 814 | - include: main 815 | 816 | else-pop: 817 | - match: (?=\S) 818 | pop: 1 819 | --------------------------------------------------------------------------------