Skip to content

Add syntax highlight to ENV files#19260

Open
duckafire wants to merge 6 commits intovim:masterfrom
duckafire:syntax-to-env
Open

Add syntax highlight to ENV files#19260
duckafire wants to merge 6 commits intovim:masterfrom
duckafire:syntax-to-env

Conversation

@duckafire
Copy link

Add a simple syntax highlight to files named as:

  • *.env{rc,}; and
  • .env{rc,}.*.

Note

File type name is env.

Tip

Examples:

  • .env.example
  • backup.env
  • 000.envrc

It covers the follow items:

  • Fields (all texts they follow the match: /^\h\(\w\|\.\)*/);
  • Comments (lines started with #):
    • To do tags (CAUNTION, NOTE, TODO, WARN, WARNING),
    • Titles; and
  • Values (strings delimited by =, and end of the line).

Note

I did not use the "classic To do tags" because I think it does not fit into this context.

The main objective of this PR is to improve the syntax beauty*, code legibility,
and syntax extensibility**.

Note

  • * Now I used the correct word (see commit: 7ebf6a7a7189d2be7562c9da70f2c24ecdc9535b).
  • ** Even though there is not many what to extend now, but it can change a day).

Below there is an example code, copy it, and run the syntax script to see how it works.

# Generic comment

# TODO: do something to improve this syntax.

# FOO: based in VimScript "titles".

foo = bar

foo.example =

# Indentation is not recommended by
# this syntax highlight
  # No-recommended comment position

  bar = 0
  bar.example =

When I was making this, I’m a bit confused whether I need to add .env extension to
ft_from_ext or not, because there is no about .env there, even it is a valid
extension (without self syntax). So, for now, I do not added it.

Note

My English is a little bad, so they can have some gramatical errors here and in my
commits messages - I'm trying to improve it daily.

Before of this, SH syntax was used in ENV files. It was OK, but
it limited the extensible of the syntax, what it prevented add
support to specific characteristics of some "`.env processors",
like that from CodeIgniter4 (it supports dots: "foo.bar=0").

It also allows to improve the syntax pretty and code legibility
(mainly because the highlight is not breaked by spaces).

Currently, it does not "allow" indentation (it breaks highlight
of fields/variables, and comments when they are not in line
start.

Signed-off-by: DuckAfire <155199080+duckafire@users.noreply.github.com>
I removed `*.env{rc,}` from `autocmd` used to set SH filetype.

Signed-off-by: DuckAfire <155199080+duckafire@users.noreply.github.com>
@duckafire
Copy link
Author

I think I undestand what it is wrong, but I do not have certain of how to fix it. Because of this I just will wait for the professionals.

Tip

The main is below:

./src/testdir/runtest.vim:636
└── ./src/testdir/runtest.vim:312
    └── ./src/testdir/test_filetype.vim:1046
        └── ./src/testdir/test_filetype.vim:1021
From test_filetype.vim:
Found errors in Test_filetype_detection():
command line..script /tmp/cirrus-ci-build/src/testdir/runtest.vim[636]..function RunTheTest[63]..Test_filetype_detection[8]..<SNR>8_CheckItems line 12: cannot edit ".env": Vim:E492: Not an editor command: .env{rc,}{.*,} setf env
command line..script /tmp/cirrus-ci-build/src/testdir/runtest.vim[636]..function RunTheTest[63]..Test_filetype_detection[8]..<SNR>8_CheckItems line 18: with file name: .env: Expected 'sh' but got ''
command line..script /tmp/cirrus-ci-build/src/testdir/runtest.vim[636]..function RunTheTest[63]..Test_filetype_detection[8]..<SNR>8_CheckItems line 12: cannot edit ".envrc": Vim:E492: Not an editor command: .env{rc,}{.*,} setf env
command line..script /tmp/cirrus-ci-build/src/testdir/runtest.vim[636]..function RunTheTest[63]..Test_filetype_detection[8]..<SNR>8_CheckItems line 18: with file name: .envrc: Expected 'sh' but got ''

duckafire and others added 3 commits January 27, 2026 09:44
Revised by github@zeertzjq

Signed-off-by: DuckAfire <155199080+duckafire@users.noreply.github.com>

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Its use and declaration was inspired in `json.vim`, but it is
unnecessary here.

Actually, I really do not know whether I understand the purpose
of this variable in `json.vim` context. But it is not important
in this context.

Signed-off-by: DuckAfire <155199080+duckafire@users.noreply.github.com>
Remove ENV files from object returned by `s:GetFilenameChecks()`
(from `sh` field), and add them, and new supported variantions,
to a new field (`env`) to ENV files.

Signed-off-by: DuckAfire <155199080+duckafire@users.noreply.github.com>
@duckafire
Copy link
Author

I understand what is wrong, but I do not know what causes these problems.

I think I did not edit nothing related with "server state".

# Summary
...WaitForAssert[2]..<SNR>4_WaitForCommon[11]..<lambda>10 line 1: Expected 'n' but got 'i'
...WaitForAssert[2]..<SNR>4_WaitForCommon[11]..<lambda>11 line 1: Expected '13' but got '14'
...WaitForAssert[2]..<SNR>4_WaitForCommon[11]..<lambda>12 line 1: Expected 'dead' but got 'run'
...Test_client_server_stopinsert line 36: Server did not exit

Tip

See ./src/testdir/test_clientserver.vim, lines: 233; 234; and 238.

Copy link
Contributor

@dkearns dkearns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. However, I'm not sure it's safe to restrict these files to simple parameter definitions, let's see what others think.

Linguists supports it as a dedicated filetype: https://github.com/github-linguist/linguist/blob/e51c227048a02a8a1b0fae6e72214e7c5f327c73/lib/linguist/languages.yml#L1762-L1784

Dotenv:
  type: data
  color: "#e5d559"
  extensions:
  - ".env"
  filenames:
  - ".env"
  - ".env.ci"
  - ".env.dev"
  - ".env.development"
  - ".env.development.local"
  - ".env.example"
  - ".env.local"
  - ".env.prod"
  - ".env.production"
  - ".env.sample"
  - ".env.staging"
  - ".env.template"
  - ".env.test"
  - ".env.testing"
  tm_scope: source.dotenv
  ace_mode: text
  language_id: 111148035

@duckafire duckafire requested a review from dkearns January 27, 2026 18:43
> 1 - Apply standard indent for VimScript (x2 spaces).
2 - Replace `\(\)` to `\%(\)` (`envField`; because capturing group is unused).
3 - Apply normal spelling of `:syntax` (`:syn`), instead shortest (`:sy`).
4 - Apply singular form to `envTitles` (syntax group name).
5 - Fix match of `envTitle` to avoid titles stacked in a same line.
6 - Remove `*.envrc` and `.envrc.*` from set of ENV files.
7 - Readd ENVRC files to:
  * `sh` field from object returned by `s:GetFilenameChecks()`.
  * `autocmd` used to set SH syntax highlight.
8 - Improve match of ENVRC.

Signed-off-by: DuckAfire <155199080+duckafire@users.noreply.github.com>
@chrisbra
Copy link
Member

I am confused, why is this line there:

au BufNewFile,BufRead */etc/profile,.profile,*.sh,*.envrc,.envrc.* call dist#ft#SetFileTypeSH(getline(1))

Doesn't this set the filetype to sh? Is that actually being used for any shell file? It should go to env filetype as well, no? I also think that the extension .env should go to autoload/dist/ft.vim to ft_from_ext instead.

@duckafire
Copy link
Author

I am confused, why is this line there:

au BufNewFile,BufRead */etc/profile,.profile,*.sh,*.envrc,.envrc.* call dist#ft#SetFileTypeSH(getline(1))

Doesn't this set the filetype to sh? Is that actually being used for any shell file? It should go to env filetype as well, no? I also think that the extension .env should go to autoload/dist/ft.vim to ft_from_ext instead.

Based on what I read and understood (from source code):

  • This line is used to call functions used to search possible shebangs (in SH Flavors) and "exec" commands hidden in comments (in shell-like files). The file type is set based in what is found (default is SH).

Based in what I know, ENV is not a SH file, it is a file to declarate environment variables. This means support of other resources of SH (keywords; operators; ...) does not always supported.

Note

Before this PR, ENV files use SH syntax highlight.

Why do you think ENV to be "moved"?

@duckafire
Copy link
Author

Thanks for the PR. However, I'm not sure it's safe to restrict these files to simple parameter definitions, let's see what others think.

Linguists supports it as a dedicated filetype: https://github.com/github-linguist/linguist/blob/e51c227048a02a8a1b0fae6e72214e7c5f327c73/lib/linguist/languages.yml#L1762-L1784

Dotenv:
  type: data
  color: "#e5d559"
  extensions:
  - ".env"
  filenames:
  - ".env"
  - ".env.ci"
  - ".env.dev"
  - ".env.development"
  - ".env.development.local"
  - ".env.example"
  - ".env.local"
  - ".env.prod"
  - ".env.production"
  - ".env.sample"
  - ".env.staging"
  - ".env.template"
  - ".env.test"
  - ".env.testing"
  tm_scope: source.dotenv
  ace_mode: text
  language_id: 111148035

Sorry for the errors related with code conventions, I am new here.

About the ENVRC, I did not know this file, nor its purpose. I throght it was legacy name to environment files, or a name low used.

I gave back ENVRC to the place where they were. I also improved the its match.

Do you think files names (.env.example; env.dev; ...) have to be defined to hidden files instead wildcard (.env.*)?

@dkearns
Copy link
Contributor

dkearns commented Jan 28, 2026

I am confused, why is this line there:

au BufNewFile,BufRead */etc/profile,.profile,*.sh,*.envrc,.envrc.* call dist#ft#SetFileTypeSH(getline(1))

Doesn't this set the filetype to sh? Is that actually being used for any shell file

That is the correct filetype for direnv rc files and .envrc, foo.envrc, .envrc.foo and foo.envrc.bar variants are all used.

It should go to env filetype as well, no? I also think that the extension .env should go to autoload/dist/ft.vim to ft_from_ext instead.

The change adding ft_from_ext wasn't really fully cooked so whether to split up the various patterns is a bit confusing. .envrc could be moved to ft_from_name and the *.envrc variant to ft_from_ext. However, there is also the less common *.envrc.* variant that's not currently matched.

@chrisbra
Copy link
Member

Thanks. The thing that threw me off was that this PR is about highlighting ENV files and did not talk about envrc files. We should separate those two things. into at least separate commits. One commits adds the .env filetype detection and uses the simple environment variable highlighting and the other commit just adds detection for .envrc.* as shell filetype.

@duckafire
Copy link
Author

Thanks. The thing that threw me off was that this PR is about highlighting ENV files and did not talk about envrc files. We should separate those two things. into at least separate commits. One commits adds the .env filetype detection and uses the simple environment variable highlighting and the other commit just adds detection for .envrc.* as shell filetype.

As said before, I just change ENVRC match because I thought I was a variation of ENV files.

After to be warnied about this, I putted it again in its original place - together with small improvements in its match pattern.

You are right, it would have been better to divide the fixing of the script syntax, and the eddition of the ENVRC match, I will take this into consideration in possible future PRs.

@chrisbra
Copy link
Member

Alright, the one thing that keeps me from including this right now is that it’s slightly backwards-incompatible: .env files would get their own filetype and no longer be handled as sh. After the release, I can handle any potential backlash a bit better 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants