This commit is contained in:
raf 2026-01-27 08:04:18 +00:00 committed by GitHub
commit bb768d6821
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 163 additions and 8 deletions

View file

@ -181,14 +181,24 @@ vim.api.nvim_create_autocmd("User", {
}) })
``` ```
## 🫂 Special Thanks ## 🫂 Attributions / Special Thanks
I extend my thanks to the awesome [Lychee](https://github.com/itslychee), [direnv.vim]: https://github.com/direnv/direnv.vim
[mrshmllow](https://github.com/mrshmllow) and
[diniamo](https://github.com/diniamo) for their invaluable assistance in the My first thanks go first to the awesome [direnv.vim] (available under the MIT
creation of this plugin. I would also like to thank license) that this plugin draws a lot of inspiration from. It is a small,
[direnv.vim](https://github.com/direnv/direnv.vim) maintainers for their initial practical solution that has served me well.
work.
[diniamo]: https://github.com/diniamo
[lychee]: https://github.com/itslychee
[mrshmllow]: https://github.com/mrshmllow
I would also like to extend my thanks to
I extend my thanks to the awesome [diniamo], [Lychee], [mrshmllow] for their
invaluable assistance in the creation of this plugin. The earlier prototypes of
this plugin were nowhere near what it is today, and thanks to them many
improvements were made possible.
## 📜 License ## 📜 License

9
ftdetect/direnv.lua Normal file
View file

@ -0,0 +1,9 @@
-- Detect .envrc, .direnvrc, direnvrc files and set filetype to 'direnv'
local group = vim.api.nvim_create_augroup("direnv_ftdetect", { clear = true })
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
group = group,
pattern = { ".envrc*", ".direnvrc*", "direnvrc*" },
callback = function()
vim.bo.filetype = "direnv"
end,
})

47
ftplugin/direnv.lua Normal file
View file

@ -0,0 +1,47 @@
if vim.b.did_ftplugin then
return
end
vim.b.did_ftplugin = true
-- Set buffer-local commentstring
vim.bo.commentstring = "# %s"
-- Saving an .envrc (or related) should automatically trigger the plugin's
-- reload/refresh behavior without causing errors when the plugin/command
-- is not installed.
local group = vim.api.nvim_create_augroup("DirenvBuffer", { clear = false })
vim.api.nvim_create_autocmd("BufWritePost", {
group = group,
buffer = 0,
callback = function()
-- Trigger the Direnv reload command if available
if vim.fn.exists(":Direnv") == 2 then
pcall(vim.cmd, "Direnv reload")
end
end,
})
-- Decide whether to use tree-sitter or legacy syntax script. Tree-sitter
-- is more modern and is almost always preferrable to Regex-based highlighting
-- that the legacy method requires, but it's difficult to bundle a Tree-sitter
-- grammar, so we cannot unconditionally load my own Direnv grammar. Though, if
-- it IS available then we should skip legacy syntax highlighting.
local has_ts = false
local ok, parsers = pcall(require, "nvim-treesitter.parsers")
if ok and type(parsers.has_parser) == "function" then
has_ts = parsers.has_parser("direnv")
end
if has_ts then
-- If a parser exists, prefer tree-sitter highlighting. Nothing to do
-- here because nvim-treesitter will attach based on filetype by itself.
return
end
-- Set syntax to direnv so Vim will load the bundled syntax file. Only set
-- if no syntax is already active for this buffer, i.e., if tree-sitter is
-- not loaded/available.
if not vim.bo.syntax or vim.bo.syntax == "" then
-- setlocal syntax=direnv should cause Vim to load syntax/direnv.vim from runtime
pcall(vim.cmd, "setlocal syntax=direnv")
end

89
syntax/direnv.vim Normal file
View file

@ -0,0 +1,89 @@
" direnv.vim - support for direnv <http://direnv.net>
" Author: JINNOUCHI Yasushi <me@delphinus.dev>
" Version: 0.2
if exists('b:current_syntax')
finish
endif
" To use syntax for bash in sh.vim, set the g:is_bash value temporarily.
let s:current = get(g:, 'is_bash', '__NO_VALUE__')
let g:is_bash = 1
runtime! syntax/sh.vim
if s:current ==# '__NO_VALUE__'
unlet g:is_bash
else
let g:is_bash = s:current
endif
unlet s:current
let b:current_syntax = 'direnv'
" Func: with commands {{{
" `has` func takes one argument that represents a CLI command.
syn keyword direnvCommandFunc has nextgroup=direnvCommand,shSingleQuote,shDoubleQuote skipwhite
hi def link direnvCommandFunc shStatement
" command name is almost the same as direnvPath, but has a different color.
syn region direnvCommand start=/[^'"[:space:]]/ skip=/\\./ end=/\([][(){}#`'";\\[:space:]]\)\@=\|$/ contained nextgroup=shComment skipwhite
hi def link direnvCommand shCommandSub
" }}}
" Func: with paths {{{
" These funcs takes one argument that represents a file/dir path.
syn keyword direnvPathFunc dotenv dotenv_if_exists env_vars_required fetchurl join_args user_rel_path on_git_branch find_up has source_env source_env_if_exists source_up source_up_if_exists source_url PATH_add MANPATH_add load_prefix watch_file watch_dir semver_search strict_env unstrict_env nextgroup=direnvPath,shSingleQuote,shDoubleQuote skipwhite
hi def link direnvPathFunc shStatement
" path string can end before non-escaped [, ], (, ), {, }, #, `, ', ", ;, \, and spaces.
syn region direnvPath start=/[^'"[:space:]]/ skip=/\\./ end=/\([][(){}#`'";\\[:space:]]\)\@=\|$/ contained nextgroup=shComment skipwhite
hi def link direnvPath Directory
" `expand_path` takes one or two arguments that represents a dir path.
syn keyword direnvExpandPathFunc expand_path nextgroup=direnvExpandPathRel,shSingleQuote,shDoubleQuote skipwhite
hi def link direnvExpandPathFunc shStatement
syn region direnvExpandPathRel start=/[^'"[:space:]]/ skip=/\\./ end=/\%(\s\|\_$\)/ contained nextgroup=direnvPath,shSingleQuote,shDoubleQuote skipwhite
hi def link direnvExpandPathRel Directory
" `path_add` takes two arguments that represents a variable name and a dir
" path.
syn keyword direnvPathAddFunc PATH_add MANPATH_add PATH_rm path_rm path_add nextgroup=direnvVar skipwhite
hi def link direnvPathAddFunc shStatement
syn match direnvVar /\S\+/ nextgroup=direnvPath,shSingleQuote,shDoubleQuote contained skipwhite
hi def link direnvVar shCommandSub
" }}}
" Func: use {{{
syn keyword direnvUseFunc use use_flake use_guix use_julia use_nix use_node use_nodenv use_rbenv use_vim rvm nextgroup=direnvUseCommand skipwhite
hi def link direnvUseFunc shStatement
" `use rbenv/nix/guix` takes several arguments.
syn match direnvUseCommand /\S\+/ contained
hi def link direnvUseCommand shCommandSub
" }}}
" Func: layout {{{
" `layout` takes one argument that represents a language name.
syn keyword direnvLayoutFunc layout layout_anaconda layout_go layout_julia layout_node layout_perl layout_php layout_pipenv layout_pyenv layout_python layout_python2 layout_python3 layout_ruby nextgroup=direnvLayoutLanguage,direnvLayoutLanguagePath skipwhite
hi def link direnvLayoutFunc shStatement
syn keyword direnvLayoutLanguage go node perl python3 ruby contained
hi def link direnvLayoutLanguage shCommandSub
" `layout python` takes one more argument that represents a file path.
syn keyword direnvLayoutLanguagePath python nextgroup=direnvPath,shSingleQuote,shDoubleQuote contained skipwhite
hi def link direnvLayoutLanguagePath shCommandSub
" }}}
" Func: others {{{
" `direnv_load` takes several arguments.
syn keyword direnvFunc direnv_apply_dump direnv_layout_dir direnv_load direnv_version log_error log_status
hi def link direnvFunc shStatement
" }}}
syn cluster direnvStatement contains=direnvCommandFunc,direnvPathFunc,direnvExpandPathFunc,direnvPathAddFunc,direnvUseFunc,direnvLayoutFunc,direnvFunc
syn cluster shArithParenList add=@direnvStatement
syn cluster shCommandSubList add=@direnvStatement
" vim:se fdm=marker: