diff --git a/README.md b/README.md index 34e7c34..71ce895 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # direnv.nvim +[direnv]: https://direnv.net/ + Dead simple Neovim plugin to add automatic Direnv loading, inspired by `direnv.vim` and written in Lua for better performance and maintainability. @@ -15,13 +17,14 @@ Dead simple Neovim plugin to add automatic Direnv loading, inspired by ### 📓 TODO -There are things direnv.nvim can _not_ yet do. Mainly, we would like to -integrate Treesitter for **syntax highlighting** similar to direnv.vim. -Unfortunately there isn't a TS grammar for Direnv, but we can port syntax.vim -from direnv.vim. +`direnv.nvim` is generally feature complete. There are no major planned +features, and it should be considered stable for the most part. What +`direnv.nvim` _cannot_ do yet is **syntax highlighting** similar to `direnv.vim` +but this is planned to be remedied through either using Treesitter, or by +porting `direnv.vim`'s syntax.vim.' -Additionally, it might be worth adding an option to allow direnv on, e.g., -VimEnter if the user has configured to do so. +Feature requests are welcome. Please create an issue to describe the feature +that you would like to see. ## 📦 Installation @@ -31,7 +34,7 @@ You will need to call the setup function to load the plugin. ### Prerequisites - Neovim 0.8.0 or higher -- [direnv](https://direnv.net/) installed and available in your PATH +- [direnv] v2.33.0 or later installed and available in your PATH ### Using lazy.nvim diff --git a/lua/direnv.lua b/lua/direnv.lua index a4609e0..927932b 100644 --- a/lua/direnv.lua +++ b/lua/direnv.lua @@ -164,6 +164,14 @@ M._get_rc_status = function(callback) local ok, status = pcall(vim.json.decode, obj.stdout) if not ok or not status or not status.state then + vim.schedule(function() + notify( + "Failed to parse direnv status. Your version of direnv may not support JSON output. " + .. "Please ensure you have direnv v2.33.0 or later installed. " + .. "You can verify by running: direnv status --json", + vim.log.levels.ERROR + ) + end) for _, cb in ipairs(pending_callbacks) do cb(nil, nil) end @@ -199,6 +207,11 @@ M._get_rc_status = function(callback) ) end +M.refresh_status = function() + cache.status = nil + M._get_rc_status(function() end) +end + --- Initialize direnv for current directory --- @param path string Path to .envrc file M._init = function(path) @@ -224,32 +237,39 @@ M._init = function(path) end vim.schedule(function() - local env_commands = vim.split(obj.stdout, "\n") - if #env_commands > 0 then - for _, cmd in ipairs(env_commands) do - if cmd ~= "" then - pcall(function() - vim.cmd(cmd) - end) - end - end + local ok, env = pcall(vim.json.decode, obj.stdout) - if not silent then - notify( - "direnv environment loaded successfully", - vim.log.levels.INFO - ) + if not ok or type(env) ~= "table" then + notify("Failed to parse direnv JSON output", vim.log.levels.ERROR) + return + end + + for key, value in pairs(env) do + if value == vim.NIL or value == nil then + vim.env[key] = nil + else + if type(value) ~= "string" then + value = tostring(value) + end + vim.env[key] = value end - vim.api.nvim_exec_autocmds( - "User", - { pattern = "DirenvLoaded", modeline = false } + end + + if not silent then + notify( + "direnv environment loaded successfully", + vim.log.levels.INFO ) end + vim.api.nvim_exec_autocmds( + "User", + { pattern = "DirenvLoaded", modeline = false } + ) end) end vim.system( - { M.config.bin, "export", "vim" }, + { M.config.bin, "export", "json" }, { text = true, cwd = cwd }, on_exit ) @@ -609,7 +629,7 @@ M.setup = function(user_config) pattern = ".envrc", group = group_id, callback = function() - cache.status = nil + M.refresh_status() notify( ".envrc file changed. Run :Direnv allow to activate changes.", vim.log.levels.INFO @@ -619,8 +639,7 @@ M.setup = function(user_config) -- Expose a command to refresh the statusline value without triggering reload vim.api.nvim_create_user_command("DirenvStatuslineRefresh", function() - cache.last_check = 0 - M._get_rc_status(function() end) + M.refresh_status() end, {}) M._get_rc_status(function() end)