Add dotenv support (#273074)

* Add dotenv support

This adds basic language support for the dotenv language. This includes
syntax highlighting and a language configuration file.

The dotenv language is applied to files with the `.env` extension, files
named `.env`, `.flaskenv`, or `user-dirs.dirs`, and file names starting
with `.env.`.

The grammar is downloaded from https://github.com/dotenv-org/dotenv-vscode.

Closes #267333

* Add tests

* Remove ini and shellscript language conflicting with dotenv

---------

Co-authored-by: Alex Ross <38270282+alexr00@users.noreply.github.com>
This commit is contained in:
Remco Haszing
2025-10-30 10:51:57 +01:00
committed by GitHub
parent 0ed832c5d9
commit ec7b5e7fa4
11 changed files with 351 additions and 7 deletions

View File

@@ -0,0 +1,2 @@
test/**
cgmanifest.json

View File

@@ -0,0 +1,40 @@
{
"registrations": [
{
"component": {
"type": "git",
"git": {
"name": "dotenv-org/dotenv-vscode",
"repositoryUrl": "https://github.com/dotenv-org/dotenv-vscode",
"commitHash": "e7e41baa5b23e01c1ff0567a4e596c24860e7def"
}
},
"licenseDetail": [
"MIT License",
"",
"Copyright (c) 2022 Scott Motte",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in all",
"copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
"SOFTWARE."
],
"license": "MIT License",
"version": "0.26.0"
}
],
"version": 1
}

View File

@@ -0,0 +1,24 @@
{
"comments": {
"lineComment": "#"
},
"brackets": [
["{", "}"],
["[", "]"],
["(", ")"]
],
"autoClosingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["\"", "\""],
["'", "'"]
],
"surroundingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["\"", "\""],
["'", "'"]
]
}

View File

@@ -0,0 +1,48 @@
{
"name": "dotenv",
"displayName": "%displayName%",
"description": "%description%",
"version": "1.0.0",
"publisher": "vscode",
"license": "MIT",
"engines": {
"vscode": "*"
},
"scripts": {
"update-grammar": "node ../node_modules/vscode-grammar-updater/bin dotenv-org/dotenv-vscode syntaxes/dotenv.tmLanguage.json ./syntaxes/dotenv.tmLanguage.json"
},
"categories": ["Programming Languages"],
"contributes": {
"languages": [
{
"id": "dotenv",
"extensions": [
".env"
],
"filenames": [
".env",
".flaskenv",
"user-dirs.dirs"
],
"filenamePatterns": [
".env.*"
],
"aliases": [
"Dotenv"
],
"configuration": "./language-configuration.json"
}
],
"grammars": [
{
"language": "dotenv",
"scopeName": "source.dotenv",
"path": "./syntaxes/dotenv.tmLanguage.json"
}
]
},
"repository": {
"type": "git",
"url": "https://github.com/microsoft/vscode.git"
}
}

View File

@@ -0,0 +1,4 @@
{
"displayName": "Dotenv Language Basics",
"description": "Provides syntax highlighting and bracket matching in dotenv files."
}

View File

@@ -0,0 +1,127 @@
{
"information_for_contributors": [
"This file has been converted from https://github.com/dotenv-org/dotenv-vscode/blob/master/syntaxes/dotenv.tmLanguage.json",
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/dotenv-org/dotenv-vscode/commit/e7e41baa5b23e01c1ff0567a4e596c24860e7def",
"scopeName": "source.dotenv",
"patterns": [
{
"comment": "Full Line Comment",
"match": "^\\s?(#.*$)\\n",
"captures": {
"1": {
"patterns": [
{
"include": "#line-comment"
}
]
}
}
},
{
"comment": "ENV entry",
"match": "^\\s?(.*?)\\s?(\\=)(.*)$",
"captures": {
"1": {
"patterns": [
{
"include": "#key"
}
]
},
"2": {
"name": "keyword.operator.assignment.dotenv"
},
"3": {
"name": "property.value.dotenv",
"patterns": [
{
"include": "#line-comment"
},
{
"include": "#double-quoted-string"
},
{
"include": "#single-quoted-string"
},
{
"include": "#interpolation"
}
]
}
}
}
],
"repository": {
"variable": {
"comment": "env variable",
"match": "[a-zA-Z_]+[a-zA-Z0-9_]*"
},
"line-comment": {
"comment": "Comment",
"match": "#.*$",
"name": "comment.line.dotenv"
},
"interpolation": {
"comment": "Interpolation (variable substitution)",
"match": "(\\$\\{)(.*)(\\})",
"captures": {
"1": {
"name": "keyword.interpolation.begin.dotenv"
},
"2": {
"name": "variable.interpolation.dotenv"
},
"3": {
"name": "keyword.interpolation.end.dotenv"
}
}
},
"escape-characters": {
"comment": "Escape characters",
"match": "\\\\[nrtfb\"'\\\\]|\\\\u[0123456789ABCDEF]{4}",
"name": "constant.character.escape.dotenv"
},
"double-quoted-string": {
"comment": "Double Quoted String",
"match": "\"(.*)\"",
"name": "string.quoted.double.dotenv",
"captures": {
"1": {
"patterns": [
{
"include": "#interpolation"
},
{
"include": "#escape-characters"
}
]
}
}
},
"single-quoted-string": {
"comment": "Single Quoted String",
"match": "'(.*)'",
"name": "string.quoted.single.dotenv"
},
"key": {
"comment": "Key",
"match": "(export\\s)?(.*)",
"captures": {
"1": {
"name": "keyword.key.export.dotenv"
},
"2": {
"name": "variable.key.dotenv",
"patterns": [
{
"include": "#variable"
}
]
}
}
}
}
}

View File

@@ -40,13 +40,11 @@
".repo"
],
"filenames": [
"gitconfig",
".env"
"gitconfig"
],
"filenamePatterns": [
"**/.config/git/config",
"**/.git/config",
".*.env"
"**/.git/config"
],
"aliases": [
"Properties",

View File

@@ -69,9 +69,6 @@
"bashrc_Apple_Terminal",
"zshrc_Apple_Terminal"
],
"filenamePatterns": [
".env.*"
],
"firstLine": "^#!.*\\b(bash|fish|zsh|sh|ksh|dtksh|pdksh|mksh|ash|dash|yash|sh|csh|jcsh|tcsh|itcsh).*|^#\\s*-\\*-[^*]*mode:\\s*shell-script[^*]*-\\*-",
"configuration": "./language-configuration.json",
"mimetypes": [

View File

@@ -0,0 +1,3 @@
# dev
HELLO=123
GOODBYE=456

View File

@@ -0,0 +1,100 @@
[
{
"c": "# dev",
"t": "source.dotenv comment.line.dotenv",
"r": {
"dark_plus": "comment: #6A9955",
"light_plus": "comment: #008000",
"dark_vs": "comment: #6A9955",
"light_vs": "comment: #008000",
"hc_black": "comment: #7CA668",
"dark_modern": "comment: #6A9955",
"hc_light": "comment: #515151",
"light_modern": "comment: #008000"
}
},
{
"c": "HELLO",
"t": "source.dotenv variable.key.dotenv",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE",
"dark_modern": "variable: #9CDCFE",
"hc_light": "variable: #001080",
"light_modern": "variable: #001080"
}
},
{
"c": "=",
"t": "source.dotenv keyword.operator.assignment.dotenv",
"r": {
"dark_plus": "keyword.operator: #D4D4D4",
"light_plus": "keyword.operator: #000000",
"dark_vs": "keyword.operator: #D4D4D4",
"light_vs": "keyword.operator: #000000",
"hc_black": "keyword.operator: #D4D4D4",
"dark_modern": "keyword.operator: #D4D4D4",
"hc_light": "keyword.operator: #000000",
"light_modern": "keyword.operator: #000000"
}
},
{
"c": "123",
"t": "source.dotenv property.value.dotenv",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF",
"dark_modern": "default: #CCCCCC",
"hc_light": "default: #292929",
"light_modern": "default: #3B3B3B"
}
},
{
"c": "GOODBYE",
"t": "source.dotenv variable.key.dotenv",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE",
"dark_modern": "variable: #9CDCFE",
"hc_light": "variable: #001080",
"light_modern": "variable: #001080"
}
},
{
"c": "=",
"t": "source.dotenv keyword.operator.assignment.dotenv",
"r": {
"dark_plus": "keyword.operator: #D4D4D4",
"light_plus": "keyword.operator: #000000",
"dark_vs": "keyword.operator: #D4D4D4",
"light_vs": "keyword.operator: #000000",
"hc_black": "keyword.operator: #D4D4D4",
"dark_modern": "keyword.operator: #D4D4D4",
"hc_light": "keyword.operator: #000000",
"light_modern": "keyword.operator: #000000"
}
},
{
"c": "456",
"t": "source.dotenv property.value.dotenv",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF",
"dark_modern": "default: #CCCCCC",
"hc_light": "default: #292929",
"light_modern": "default: #3B3B3B"
}
}
]