1local log = require("mise.log")
2
3local Mise = {}
4
5---@class MiseConfig
6local defaults = {
7 run = "mise",
8 args = "env --json",
9 initial_path = vim.env.PATH,
10 unset_vars = true,
11 load_on_setup = true,
12 force_run = false,
13}
14
15---@type MiseConfig
16local options
17
18local previous_vars = {}
19
20---@param data table
21local function set_previous(data)
22 previous_vars = {}
23 for var_name, var_value in pairs(data) do
24 if var_name ~= "PATH" then
25 previous_vars[var_name] = var_value
26 end
27 end
28end
29
30---@return table?
31local function get_data()
32 local full_command = options.run .. " " .. options.args
33 local env_sh = vim.fn.system(full_command)
34
35 -- mise will print out warnings: "mise WARN" without the "--quiet" flag
36 if string.find(env_sh, "^mise") then
37 local first_line = string.match(env_sh, "^[^\n]*")
38 log.error(first_line)
39 return nil
40 end
41
42 local ok, data = pcall(vim.json.decode, env_sh)
43 if not ok or data == nil then
44 log.error('Invalid json returned by "' .. full_command .. '"')
45 return nil
46 end
47
48 return data
49end
50
51---@param data table
52local function load_env(data)
53 if options.unset_vars then
54 for var_name, _ in pairs(previous_vars) do
55 vim.env[var_name] = nil
56 end
57 end
58
59 for var_name, var_value in pairs(data) do
60 vim.env[var_name] = var_value
61 end
62
63 set_previous(data)
64end
65
66local function dir_changed()
67 vim.env.PATH = options.initial_path
68
69 local data = get_data()
70 if data == nil then
71 return
72 end
73
74 load_env(data)
75end
76
77---@param opt? MiseConfig
78function Mise.setup(opt)
79 options = vim.tbl_deep_extend("force", {}, defaults, opt or {})
80
81 if vim.fn.executable(options.run) ~= 1 then
82 log.error('Cannot find "' .. options.run .. '" executable')
83 return
84 end
85
86 if options.run ~= "mise" and not options.force_run then
87 log.error(options.run .. ' not supported, set "force_run = true" in setup() if you know the data is correct.')
88 return
89 end
90
91 local data = get_data()
92 if data == nil then
93 return
94 end
95
96 if options.load_on_setup then
97 vim.env.PATH = options.initial_path
98 load_env(data)
99 else
100 set_previous(data)
101 end
102
103 local group = vim.api.nvim_create_augroup("mise.nvim", { clear = true })
104 vim.api.nvim_create_autocmd("DirChanged", {
105 group = group,
106 desc = "Run command to load env vars",
107 callback = function()
108 if vim.v.event.scope == "global" then
109 dir_changed()
110 end
111 end,
112 })
113
114 vim.api.nvim_create_user_command("Mise", function()
115 log.info(vim.inspect(get_data()))
116 end, {
117 desc = "Mise",
118 })
119end
120
121return Mise