diff --git a/extras/grammar/HCL.json-tmLanguage b/extras/grammar/HCL.json-tmLanguage
new file mode 100755
index 0000000..1025965
--- /dev/null
+++ b/extras/grammar/HCL.json-tmLanguage
@@ -0,0 +1,97 @@
+{
+ "fileTypes": [
+ "hcl",
+ "hcldec"
+ ],
+ "name": "HCL",
+ "patterns": [
+ {
+ "begin": "#|//",
+ "captures": {
+ "0": {
+ "name": "punctuation.definition.comment.hcl"
+ }
+ },
+ "comment": "Comments",
+ "end": "$\\n?",
+ "name": "comment.line.hcl"
+ },
+ {
+ "begin": "/\\*",
+ "captures": {
+ "0": {
+ "name": "punctuation.definition.comment.hcl"
+ }
+ },
+ "comment": "Block comments",
+ "end": "\\*/",
+ "name": "comment.block.hcl"
+ },
+ {
+ "begin": "{",
+ "beginCaptures": {
+ "0": {
+ "name": "punctuation.definition.block.hcl"
+ }
+ },
+ "comment": "Nested Blocks",
+ "end": "}",
+ "endCaptures": {
+ "0": {
+ "name": "punctuation.definition.block.hcl"
+ }
+ },
+ "name": "meta.block.hcl",
+ "patterns": [
+ {
+ "include": "$self"
+ }
+ ]
+ },
+ {
+ "captures": {
+ "1": {
+ "name": "string.hcl punctuation.definition.string.begin.hcl"
+ },
+ "2": {
+ "name": "string.value.hcl"
+ },
+ "3": {
+ "name": "string.hcl punctuation.definition.string.end.hcl"
+ }
+ },
+ "comment": "Quoted Block Labels",
+ "match": "(\")([^\"]+)(\")"
+ },
+ {
+ "begin": "(\\w+)\\s*(=)\\s*",
+ "beginCaptures": {
+ "1": {
+ "name": "variable.other.assignment.hcl"
+ },
+ "2": {
+ "name": "keyword.operator.hcl"
+ }
+ },
+ "comment": "Attribute Definitions",
+ "end": "$",
+ "name": "meta.attr.hcl",
+ "patterns": [
+ {
+ "include": "source.hclexpr"
+ }
+ ]
+ },
+ {
+ "captures": {
+ "0": {
+ "name": "keyword.other.hcl"
+ }
+ },
+ "comment": "Keywords",
+ "match": "[-\\w]+"
+ }
+ ],
+ "scopeName": "source.hcl",
+ "uuid": "55e8075d-e2e3-4e44-8446-744a9860e476"
+}
\ No newline at end of file
diff --git a/extras/grammar/HCL.tmLanguage b/extras/grammar/HCL.tmLanguage
new file mode 100755
index 0000000..d65d37f
--- /dev/null
+++ b/extras/grammar/HCL.tmLanguage
@@ -0,0 +1,157 @@
+
+
+
+
+ fileTypes
+
+ hcl
+ hcldec
+
+ name
+ HCL
+ patterns
+
+
+ begin
+ #|//
+ captures
+
+ 0
+
+ name
+ punctuation.definition.comment.hcl
+
+
+ comment
+ Comments
+ end
+ $\n?
+ name
+ comment.line.hcl
+
+
+ begin
+ /\*
+ captures
+
+ 0
+
+ name
+ punctuation.definition.comment.hcl
+
+
+ comment
+ Block comments
+ end
+ \*/
+ name
+ comment.block.hcl
+
+
+ begin
+ {
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.block.hcl
+
+
+ comment
+ Nested Blocks
+ end
+ }
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.block.hcl
+
+
+ name
+ meta.block.hcl
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ captures
+
+ 1
+
+ name
+ string.hcl punctuation.definition.string.begin.hcl
+
+ 2
+
+ name
+ string.value.hcl
+
+ 3
+
+ name
+ string.hcl punctuation.definition.string.end.hcl
+
+
+ comment
+ Quoted Block Labels
+ match
+ (")([^"]+)(")
+
+
+ begin
+ (\w+)\s*(=)\s*
+ beginCaptures
+
+ 1
+
+ name
+ variable.other.assignment.hcl
+
+ 2
+
+ name
+ keyword.operator.hcl
+
+
+ comment
+ Attribute Definitions
+ end
+ $
+ name
+ meta.attr.hcl
+ patterns
+
+
+ include
+ source.hclexpr
+
+
+
+
+ captures
+
+ 0
+
+ name
+ keyword.other.hcl
+
+
+ comment
+ Keywords
+ match
+ [-\w]+
+
+
+ scopeName
+ source.hcl
+ uuid
+ 55e8075d-e2e3-4e44-8446-744a9860e476
+
+
\ No newline at end of file
diff --git a/extras/grammar/HCL.yaml-tmLanguage b/extras/grammar/HCL.yaml-tmLanguage
new file mode 100644
index 0000000..0a23cfa
--- /dev/null
+++ b/extras/grammar/HCL.yaml-tmLanguage
@@ -0,0 +1,53 @@
+name: HCL
+scopeName: source.hcl
+fileTypes: [hcl, hcldec]
+uuid: 55e8075d-e2e3-4e44-8446-744a9860e476
+
+patterns:
+
+- comment: Comments
+ name: comment.line.hcl
+ begin: '#|//'
+ end: $\n?
+ captures:
+ '0': {name: punctuation.definition.comment.hcl}
+
+- comment: Block comments
+ name: comment.block.hcl
+ begin: /\*
+ end: \*/
+ captures:
+ '0': {name: punctuation.definition.comment.hcl}
+
+- comment: Nested Blocks
+ name: meta.block.hcl
+ begin: "{"
+ beginCaptures:
+ '0': {name: punctuation.definition.block.hcl}
+ end: "}"
+ endCaptures:
+ '0': {name: punctuation.definition.block.hcl}
+ patterns:
+ - include: "$self"
+
+- comment: Quoted Block Labels
+ match: '(")([^"]+)(")'
+ captures:
+ '1': {name: string.hcl punctuation.definition.string.begin.hcl}
+ '2': {name: string.value.hcl}
+ '3': {name: string.hcl punctuation.definition.string.end.hcl}
+
+- comment: Attribute Definitions
+ name: meta.attr.hcl
+ begin: '(\w+)\s*(=)\s*'
+ beginCaptures:
+ '1': {name: variable.other.assignment.hcl}
+ '2': {name: keyword.operator.hcl}
+ end: '$'
+ patterns:
+ - include: "source.hclexpr"
+
+- comment: Keywords
+ match: '[-\w]+'
+ captures:
+ '0': {name: keyword.other.hcl}
diff --git a/extras/grammar/HCLExpression.json-tmLanguage b/extras/grammar/HCLExpression.json-tmLanguage
new file mode 100755
index 0000000..91886c8
--- /dev/null
+++ b/extras/grammar/HCLExpression.json-tmLanguage
@@ -0,0 +1,212 @@
+{
+ "fileTypes": [],
+ "name": "HCL Expression",
+ "patterns": [
+ {
+ "begin": "#|//",
+ "captures": {
+ "0": {
+ "name": "punctuation.definition.comment.hcl"
+ }
+ },
+ "comment": "Comments",
+ "end": "$\\n?",
+ "name": "comment.line.hcl"
+ },
+ {
+ "begin": "/\\*",
+ "captures": {
+ "0": {
+ "name": "punctuation.definition.comment.hcl"
+ }
+ },
+ "comment": "Block comments",
+ "end": "\\*/",
+ "name": "comment.block.hcl"
+ },
+ {
+ "comment": "Language constants (true, false, null)",
+ "match": "\\b(true|false|null)\\b",
+ "name": "constant.language.hcl"
+ },
+ {
+ "comment": "Numbers",
+ "match": "\\b([0-9]+)(.[0-9]+)?([eE][0-9]+)?\\b",
+ "name": "constant.numeric.hcl"
+ },
+ {
+ "begin": "([-\\w]+)(\\()",
+ "beginCaptures": {
+ "1": {
+ "name": "keyword.other.function.inline.hcl"
+ },
+ "2": {
+ "name": "keyword.other.section.begin.hcl"
+ }
+ },
+ "comment": "Function Calls",
+ "end": "(\\))",
+ "endCaptures": {
+ "1": {
+ "name": "keyword.other.section.end.hcl"
+ }
+ },
+ "patterns": [
+ {
+ "include": "$self"
+ }
+ ]
+ },
+ {
+ "captures": {
+ "0": {
+ "name": "variable.other.hcl"
+ }
+ },
+ "comment": "Variables and Attribute Names",
+ "match": "[-\\w]+"
+ },
+ {
+ "begin": "(?\u003e\\s*\u003c\u003c(\\w+))",
+ "beginCaptures": {
+ "0": {
+ "name": "punctuation.definition.string.begin.hcl"
+ },
+ "1": {
+ "name": "keyword.operator.heredoc.hcl"
+ }
+ },
+ "comment": "Heredoc Templates",
+ "end": "^\\s*\\1$",
+ "endCaptures": {
+ "0": {
+ "name": "punctuation.definition.string.end.hcl keyword.operator.heredoc.hcl"
+ }
+ },
+ "patterns": [
+ {
+ "include": "source.hcltemplate"
+ }
+ ]
+ },
+ {
+ "begin": "\\\"",
+ "beginCaptures": {
+ "0": {
+ "name": "string.hcl punctuation.definition.string.begin.hcl"
+ }
+ },
+ "comment": "String Templates",
+ "end": "\\\"",
+ "endCaptures": {
+ "0": {
+ "name": "string.hcl punctuation.definition.string.end.hcl"
+ }
+ },
+ "patterns": [
+ {
+ "include": "source.hcltemplate"
+ },
+ {
+ "match": "(^\"|$\\{|%\\{)+",
+ "name": "string.quoted.double.hcl"
+ }
+ ]
+ },
+ {
+ "captures": {
+ "0": {
+ "name": "keyword.operator.hcl"
+ }
+ },
+ "comment": "Operators",
+ "match": "(!=|==|\u003e=|\u003c=|\u0026\u0026|\\|\\||[-+*/%\u003c\u003e!?:])"
+ },
+ {
+ "begin": "\\(",
+ "beginCaptures": {
+ "0": {
+ "name": "meta.brace.round.hcl"
+ }
+ },
+ "comment": "Parentheses",
+ "end": "\\)",
+ "endCaptures": {
+ "0": {
+ "name": "meta.brace.round.hcl"
+ }
+ },
+ "patterns": [
+ {
+ "include": "$self"
+ }
+ ]
+ },
+ {
+ "begin": "\\[",
+ "beginCaptures": {
+ "0": {
+ "name": "meta.brace.square.hcl"
+ }
+ },
+ "comment": "Tuple Constructor",
+ "end": "\\]",
+ "endCaptures": {
+ "0": {
+ "name": "meta.brace.square.hcl"
+ }
+ },
+ "patterns": [
+ {
+ "captures": {
+ "0": {
+ "name": "keyword.control.hcl"
+ }
+ },
+ "match": "(for|in)"
+ },
+ {
+ "include": "$self"
+ }
+ ]
+ },
+ {
+ "begin": "\\{",
+ "beginCaptures": {
+ "0": {
+ "name": "meta.brace.curly.hcl"
+ }
+ },
+ "comment": "Object Constructor",
+ "end": "\\}",
+ "endCaptures": {
+ "0": {
+ "name": "meta.brace.curly.hcl"
+ }
+ },
+ "patterns": [
+ {
+ "captures": {
+ "0": {
+ "name": "keyword.control.hcl"
+ }
+ },
+ "match": "(for|in)"
+ },
+ {
+ "captures": {
+ "0": {
+ "name": "keyword.operator.hcl"
+ }
+ },
+ "match": "(=\u003e|\\.\\.\\.)"
+ },
+ {
+ "include": "$self"
+ }
+ ]
+ }
+ ],
+ "scopeName": "source.hclexpr",
+ "uuid": "6c358551-0381-4128-9ea3-277b21943b5c"
+}
\ No newline at end of file
diff --git a/extras/grammar/HCLExpression.tmLanguage b/extras/grammar/HCLExpression.tmLanguage
new file mode 100755
index 0000000..3a5bb83
--- /dev/null
+++ b/extras/grammar/HCLExpression.tmLanguage
@@ -0,0 +1,336 @@
+
+
+
+
+ fileTypes
+
+
+ name
+ HCL Expression
+ patterns
+
+
+ begin
+ #|//
+ captures
+
+ 0
+
+ name
+ punctuation.definition.comment.hcl
+
+
+ comment
+ Comments
+ end
+ $\n?
+ name
+ comment.line.hcl
+
+
+ begin
+ /\*
+ captures
+
+ 0
+
+ name
+ punctuation.definition.comment.hcl
+
+
+ comment
+ Block comments
+ end
+ \*/
+ name
+ comment.block.hcl
+
+
+ comment
+ Language constants (true, false, null)
+ match
+ \b(true|false|null)\b
+ name
+ constant.language.hcl
+
+
+ comment
+ Numbers
+ match
+ \b([0-9]+)(.[0-9]+)?([eE][0-9]+)?\b
+ name
+ constant.numeric.hcl
+
+
+ begin
+ ([-\w]+)(\()
+ beginCaptures
+
+ 1
+
+ name
+ keyword.other.function.inline.hcl
+
+ 2
+
+ name
+ keyword.other.section.begin.hcl
+
+
+ comment
+ Function Calls
+ end
+ (\))
+ endCaptures
+
+ 1
+
+ name
+ keyword.other.section.end.hcl
+
+
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ captures
+
+ 0
+
+ name
+ variable.other.hcl
+
+
+ comment
+ Variables and Attribute Names
+ match
+ [-\w]+
+
+
+ begin
+ (?>\s*<<(\w+))
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.hcl
+
+ 1
+
+ name
+ keyword.operator.heredoc.hcl
+
+
+ comment
+ Heredoc Templates
+ end
+ ^\s*\1$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.hcl keyword.operator.heredoc.hcl
+
+
+ patterns
+
+
+ include
+ source.hcltemplate
+
+
+
+
+ begin
+ \"
+ beginCaptures
+
+ 0
+
+ name
+ string.hcl punctuation.definition.string.begin.hcl
+
+
+ comment
+ String Templates
+ end
+ \"
+ endCaptures
+
+ 0
+
+ name
+ string.hcl punctuation.definition.string.end.hcl
+
+
+ patterns
+
+
+ include
+ source.hcltemplate
+
+
+ match
+ (^"|$\{|%\{)+
+ name
+ string.quoted.double.hcl
+
+
+
+
+ captures
+
+ 0
+
+ name
+ keyword.operator.hcl
+
+
+ comment
+ Operators
+ match
+ (!=|==|>=|<=|&&|\|\||[-+*/%<>!?:])
+
+
+ begin
+ \(
+ beginCaptures
+
+ 0
+
+ name
+ meta.brace.round.hcl
+
+
+ comment
+ Parentheses
+ end
+ \)
+ endCaptures
+
+ 0
+
+ name
+ meta.brace.round.hcl
+
+
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ begin
+ \[
+ beginCaptures
+
+ 0
+
+ name
+ meta.brace.square.hcl
+
+
+ comment
+ Tuple Constructor
+ end
+ \]
+ endCaptures
+
+ 0
+
+ name
+ meta.brace.square.hcl
+
+
+ patterns
+
+
+ captures
+
+ 0
+
+ name
+ keyword.control.hcl
+
+
+ match
+ (for|in)
+
+
+ include
+ $self
+
+
+
+
+ begin
+ \{
+ beginCaptures
+
+ 0
+
+ name
+ meta.brace.curly.hcl
+
+
+ comment
+ Object Constructor
+ end
+ \}
+ endCaptures
+
+ 0
+
+ name
+ meta.brace.curly.hcl
+
+
+ patterns
+
+
+ captures
+
+ 0
+
+ name
+ keyword.control.hcl
+
+
+ match
+ (for|in)
+
+
+ captures
+
+ 0
+
+ name
+ keyword.operator.hcl
+
+
+ match
+ (=>|\.\.\.)
+
+
+ include
+ $self
+
+
+
+
+ scopeName
+ source.hclexpr
+ uuid
+ 6c358551-0381-4128-9ea3-277b21943b5c
+
+
\ No newline at end of file
diff --git a/extras/grammar/HCLExpression.yaml-tmLanguage b/extras/grammar/HCLExpression.yaml-tmLanguage
new file mode 100644
index 0000000..c8ba5c1
--- /dev/null
+++ b/extras/grammar/HCLExpression.yaml-tmLanguage
@@ -0,0 +1,111 @@
+name: HCL Expression
+scopeName: source.hclexpr
+fileTypes: []
+uuid: 6c358551-0381-4128-9ea3-277b21943b5c
+
+patterns:
+
+- comment: Comments
+ name: comment.line.hcl
+ begin: '#|//'
+ end: $\n?
+ captures:
+ '0': {name: punctuation.definition.comment.hcl}
+
+- comment: Block comments
+ name: comment.block.hcl
+ begin: /\*
+ end: \*/
+ captures:
+ '0': {name: punctuation.definition.comment.hcl}
+
+- comment: Language constants (true, false, null)
+ name: constant.language.hcl
+ match: \b(true|false|null)\b
+
+- comment: Numbers
+ name: constant.numeric.hcl
+ match: \b([0-9]+)(.[0-9]+)?([eE][0-9]+)?\b
+
+- comment: Function Calls
+ begin: ([-\w]+)(\()
+ beginCaptures:
+ '1': {name: keyword.other.function.inline.hcl}
+ '2': {name: keyword.other.section.begin.hcl}
+ end: (\))
+ endCaptures:
+ '1': {name: keyword.other.section.end.hcl}
+ patterns:
+ - include: '$self'
+
+- comment: Variables and Attribute Names
+ match: '[-\w]+'
+ captures:
+ '0': {name: variable.other.hcl}
+
+- comment: Heredoc Templates
+ begin: (?>\s*<<(\w+))
+ beginCaptures:
+ '0': {name: punctuation.definition.string.begin.hcl}
+ '1': {name: keyword.operator.heredoc.hcl}
+ end: ^\s*\1$
+ endCaptures:
+ '0': {name: punctuation.definition.string.end.hcl keyword.operator.heredoc.hcl}
+ patterns:
+ - include: 'source.hcltemplate'
+
+- comment: String Templates
+ begin: \"
+ beginCaptures:
+ '0': {name: string.hcl punctuation.definition.string.begin.hcl}
+ end: \"
+ endCaptures:
+ '0': {name: string.hcl punctuation.definition.string.end.hcl}
+ patterns:
+ - include: 'source.hcltemplate'
+ - match: '(^"|$\{|%\{)+'
+ name: "string.quoted.double.hcl"
+
+- comment: Operators
+ match: '(!=|==|>=|<=|&&|\|\||[-+*/%<>!?:])'
+ captures:
+ '0': {name: keyword.operator.hcl}
+
+- comment: Parentheses
+ begin: '\('
+ beginCaptures:
+ '0': {name: meta.brace.round.hcl}
+ end: '\)'
+ endCaptures:
+ '0': {name: meta.brace.round.hcl}
+ patterns:
+ - include: '$self'
+
+- comment: Tuple Constructor
+ begin: '\['
+ beginCaptures:
+ '0': {name: meta.brace.square.hcl}
+ end: '\]'
+ endCaptures:
+ '0': {name: meta.brace.square.hcl}
+ patterns:
+ - match: '(for|in)'
+ captures:
+ '0': {name: keyword.control.hcl}
+ - include: '$self'
+
+- comment: Object Constructor
+ begin: '\{'
+ beginCaptures:
+ '0': {name: meta.brace.curly.hcl}
+ end: '\}'
+ endCaptures:
+ '0': {name: meta.brace.curly.hcl}
+ patterns:
+ - match: '(for|in)'
+ captures:
+ '0': {name: keyword.control.hcl}
+ - match: '(=>|\.\.\.)'
+ captures:
+ '0': {name: keyword.operator.hcl}
+ - include: '$self'
diff --git a/extras/grammar/HCLTemplate.json-tmLanguage b/extras/grammar/HCLTemplate.json-tmLanguage
new file mode 100755
index 0000000..6d002c1
--- /dev/null
+++ b/extras/grammar/HCLTemplate.json-tmLanguage
@@ -0,0 +1,107 @@
+{
+ "fileTypes": [
+ "tmpl"
+ ],
+ "name": "HCL Template",
+ "patterns": [
+ {
+ "begin": "[^\\$]?(\\$\\{~?)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.tag.embedded.start.hcltemplate"
+ }
+ },
+ "comment": "Interpolation Sequences",
+ "end": "~?}",
+ "endCaptures": {
+ "0": {
+ "name": "entity.tag.embedded.end.hcltemplate"
+ }
+ },
+ "name": "meta.interp.hcltemplate",
+ "patterns": [
+ {
+ "include": "source.hclexpr"
+ }
+ ]
+ },
+ {
+ "begin": "[^\\%]?(\\%\\{~?)",
+ "beginCaptures": {
+ "1": {
+ "name": "entity.tag.embedded.start.hcltemplate"
+ }
+ },
+ "comment": "Control Sequences",
+ "end": "~?}",
+ "endCaptures": {
+ "0": {
+ "name": "entity.tag.embedded.end.hcltemplate"
+ }
+ },
+ "name": "meta.control.hcltemplate",
+ "patterns": [
+ {
+ "include": "#templateif"
+ },
+ {
+ "include": "#templatefor"
+ },
+ {
+ "include": "#templatesimplekw"
+ }
+ ]
+ }
+ ],
+ "repository": {
+ "templatefor": {
+ "begin": "(for)\\s*(\\w+)\\s*(,\\s*(\\w+)\\s*)?(in)",
+ "beginCaptures": {
+ "1": {
+ "name": "keyword.control.hcltemplate"
+ },
+ "2": {
+ "name": "variable.other.hcl"
+ },
+ "4": {
+ "name": "variable.other.hcl"
+ },
+ "5": {
+ "name": "keyword.control.hcltemplate"
+ }
+ },
+ "end": "(?=~?\\})",
+ "name": "meta.templatefor.hcltemplate",
+ "patterns": [
+ {
+ "include": "source.hclexpr"
+ }
+ ]
+ },
+ "templateif": {
+ "begin": "(if)\\s*",
+ "beginCaptures": {
+ "1": {
+ "name": "keyword.control.hcltemplate"
+ }
+ },
+ "end": "(?=~?\\})",
+ "name": "meta.templateif.hcltemplate",
+ "patterns": [
+ {
+ "include": "source.hclexpr"
+ }
+ ]
+ },
+ "templatesimplekw": {
+ "captures": {
+ "0": {
+ "name": "keyword.control.hcl"
+ }
+ },
+ "match": "(else|endif|endfor)"
+ }
+ },
+ "scopeName": "source.hcltemplate",
+ "uuid": "ac6be18e-d44f-4a73-bd8f-b973fd26df05"
+}
\ No newline at end of file
diff --git a/extras/grammar/HCLTemplate.tmLanguage b/extras/grammar/HCLTemplate.tmLanguage
new file mode 100755
index 0000000..6c05359
--- /dev/null
+++ b/extras/grammar/HCLTemplate.tmLanguage
@@ -0,0 +1,172 @@
+
+
+
+
+ fileTypes
+
+ tmpl
+
+ name
+ HCL Template
+ patterns
+
+
+ begin
+ [^\$]?(\$\{~?)
+ beginCaptures
+
+ 1
+
+ name
+ entity.tag.embedded.start.hcltemplate
+
+
+ comment
+ Interpolation Sequences
+ end
+ ~?}
+ endCaptures
+
+ 0
+
+ name
+ entity.tag.embedded.end.hcltemplate
+
+
+ name
+ meta.interp.hcltemplate
+ patterns
+
+
+ include
+ source.hclexpr
+
+
+
+
+ begin
+ [^\%]?(\%\{~?)
+ beginCaptures
+
+ 1
+
+ name
+ entity.tag.embedded.start.hcltemplate
+
+
+ comment
+ Control Sequences
+ end
+ ~?}
+ endCaptures
+
+ 0
+
+ name
+ entity.tag.embedded.end.hcltemplate
+
+
+ name
+ meta.control.hcltemplate
+ patterns
+
+
+ include
+ #templateif
+
+
+ include
+ #templatefor
+
+
+ include
+ #templatesimplekw
+
+
+
+
+ repository
+
+ templatefor
+
+ begin
+ (for)\s*(\w+)\s*(,\s*(\w+)\s*)?(in)
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.hcltemplate
+
+ 2
+
+ name
+ variable.other.hcl
+
+ 4
+
+ name
+ variable.other.hcl
+
+ 5
+
+ name
+ keyword.control.hcltemplate
+
+
+ end
+ (?=~?\})
+ name
+ meta.templatefor.hcltemplate
+ patterns
+
+
+ include
+ source.hclexpr
+
+
+
+ templateif
+
+ begin
+ (if)\s*
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.hcltemplate
+
+
+ end
+ (?=~?\})
+ name
+ meta.templateif.hcltemplate
+ patterns
+
+
+ include
+ source.hclexpr
+
+
+
+ templatesimplekw
+
+ captures
+
+ 0
+
+ name
+ keyword.control.hcl
+
+
+ match
+ (else|endif|endfor)
+
+
+ scopeName
+ source.hcltemplate
+ uuid
+ ac6be18e-d44f-4a73-bd8f-b973fd26df05
+
+
\ No newline at end of file
diff --git a/extras/grammar/HCLTemplate.yaml-tmLanguage b/extras/grammar/HCLTemplate.yaml-tmLanguage
new file mode 100644
index 0000000..bd4f99f
--- /dev/null
+++ b/extras/grammar/HCLTemplate.yaml-tmLanguage
@@ -0,0 +1,58 @@
+name: HCL Template
+scopeName: source.hcltemplate
+fileTypes: [tmpl]
+uuid: ac6be18e-d44f-4a73-bd8f-b973fd26df05
+
+patterns:
+
+- comment: Interpolation Sequences
+ name: meta.interp.hcltemplate
+ begin: '[^\$]?(\$\{~?)'
+ beginCaptures:
+ '1': {name: entity.tag.embedded.start.hcltemplate}
+ end: '~?}'
+ endCaptures:
+ '0': {name: entity.tag.embedded.end.hcltemplate}
+ patterns:
+ - include: "source.hclexpr"
+
+- comment: Control Sequences
+ name: meta.control.hcltemplate
+ begin: '[^\%]?(\%\{~?)'
+ beginCaptures:
+ '1': {name: entity.tag.embedded.start.hcltemplate}
+ end: '~?}'
+ endCaptures:
+ '0': {name: entity.tag.embedded.end.hcltemplate}
+ patterns:
+ - include: "#templateif"
+ - include: "#templatefor"
+ - include: "#templatesimplekw"
+
+repository:
+
+ templateif:
+ name: meta.templateif.hcltemplate
+ begin: '(if)\s*'
+ beginCaptures:
+ '1': {name: keyword.control.hcltemplate}
+ end: '(?=~?\})'
+ patterns:
+ - include: "source.hclexpr"
+
+ templatefor:
+ name: meta.templatefor.hcltemplate
+ begin: '(for)\s*(\w+)\s*(,\s*(\w+)\s*)?(in)'
+ beginCaptures:
+ '1': {name: keyword.control.hcltemplate}
+ '2': {name: variable.other.hcl}
+ '4': {name: variable.other.hcl}
+ '5': {name: keyword.control.hcltemplate}
+ end: '(?=~?\})'
+ patterns:
+ - include: "source.hclexpr"
+
+ templatesimplekw:
+ match: (else|endif|endfor)
+ captures:
+ '0': {name: keyword.control.hcl}
diff --git a/extras/grammar/build.go b/extras/grammar/build.go
new file mode 100644
index 0000000..224550d
--- /dev/null
+++ b/extras/grammar/build.go
@@ -0,0 +1,119 @@
+// This is a helper to transform the HCL.yaml-tmLanguage file (the source of
+// record) into both HCL.json-tmLanguage and HCL.tmLanguage (in plist XML
+// format).
+//
+// Run this after making updates to HCL.yaml-tmLanguage to generate the other
+// formats.
+//
+// This file is intended to be run with "go run":
+//
+// go run ./build.go
+//
+// This file is also set up to run itself under "go generate":
+//
+// go generate .
+
+package main
+
+//go:generate go run ./build.go
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+
+ plist "github.com/DHowett/go-plist"
+ yaml "gopkg.in/yaml.v2"
+
+ multierror "github.com/hashicorp/go-multierror"
+)
+
+func main() {
+ err := realMain()
+ if err != nil {
+ log.Fatal(err)
+ }
+ os.Exit(0)
+}
+
+func realMain() error {
+ var err error
+ buildErr := build("HCL")
+ if buildErr != nil {
+ err = multierror.Append(err, fmt.Errorf("in HCL: %s", buildErr))
+ }
+ buildErr = build("HCLTemplate")
+ if buildErr != nil {
+ err = multierror.Append(err, fmt.Errorf("in HCLTemplate: %s", buildErr))
+ }
+ buildErr = build("HCLExpression")
+ if buildErr != nil {
+ err = multierror.Append(err, fmt.Errorf("in HCLExpression: %s", buildErr))
+ }
+ return err
+}
+
+func build(basename string) error {
+ yamlSrc, err := ioutil.ReadFile(basename + ".yaml-tmLanguage")
+ if err != nil {
+ return err
+ }
+
+ var content interface{}
+ err = yaml.Unmarshal(yamlSrc, &content)
+ if err != nil {
+ return err
+ }
+
+ // Normalize the value so it's both JSON- and plist-friendly.
+ content = prepare(content)
+
+ jsonSrc, err := json.MarshalIndent(content, "", " ")
+ if err != nil {
+ return err
+ }
+
+ plistSrc, err := plist.MarshalIndent(content, plist.XMLFormat, " ")
+ if err != nil {
+ return err
+ }
+
+ err = ioutil.WriteFile(basename+".json-tmLanguage", jsonSrc, os.ModePerm)
+ if err != nil {
+ return err
+ }
+
+ err = ioutil.WriteFile(basename+".tmLanguage", plistSrc, os.ModePerm)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func prepare(v interface{}) interface{} {
+ switch tv := v.(type) {
+
+ case map[interface{}]interface{}:
+ var ret map[string]interface{}
+ if len(tv) == 0 {
+ return ret
+ }
+ ret = make(map[string]interface{}, len(tv))
+ for k, v := range tv {
+ ret[k.(string)] = prepare(v)
+ }
+ return ret
+
+ case []interface{}:
+ for i := range tv {
+ tv[i] = prepare(tv[i])
+ }
+ return tv
+
+ default:
+ return v
+ }
+}