diff --git a/lua/nvim-dap-envfile.lua b/lua/nvim-dap-envfile.lua index e3af1c8..08386b0 100644 --- a/lua/nvim-dap-envfile.lua +++ b/lua/nvim-dap-envfile.lua @@ -1,3 +1,5 @@ +local utils = require("utils") + local notify_opts = { title = "nvim-dap-envfile", icon = "", @@ -79,15 +81,25 @@ function M.load_env_file(path) local env = {} ---@type table local file = io.open(path, "r") if not file then + vim.notify("Can't load file: " .. path, vim.log.levels.ERROR, notify_opts) return env end for line in file:lines() do - ---@type string, string - local key, value = line:match("^%s*([%w_]+)%s*=%s*(.+)%s*$") - if key and value then - -- remove quotes - env[key] = value:gsub('^"(.*)"$', "%1"):gsub("^'(.*)'$", "%1") + local key, value = utils.str_split_once(line, "=") + + if value then + value = vim.trim(value) + + if vim.startswith(value, '"') then + value = utils.parse_double(value) + elseif vim.startswith(value, "'") then + value = utils.parse_single(value) + end + + env[key] = value + else + vim.notify('Unexpected format for "' .. key .. '"', vim.log.levels.WARN, notify_opts) end end diff --git a/lua/utils.lua b/lua/utils.lua new file mode 100644 index 0000000..ee8489d --- /dev/null +++ b/lua/utils.lua @@ -0,0 +1,43 @@ +local M = {} + +--- Splits a string into two parts at the first occurrence of a separator. +--- +--- @param str string The input string to split. +--- @param sep string The separator to split on, plain text. +--- @return string left The part before the first separator +--- @return string|nil right The part after the first separator, or nil if not found. +function M.str_split_once(str, sep) + local pos = string.find(str, sep, 1, true) -- plain search + if not pos then + return str, nil + end + return str:sub(1, pos - 1), str:sub(pos + #sep) +end + +---@param str string String in double quotes to parse. +---@return string +function M.parse_double(str) + if not vim.startswith(str, '"') or not vim.endswith(str, '"') then + return str + end + + str = vim.fn.strcharpart(str, 1, #str - 2) + str = str:gsub('\\"', '"'):gsub("\\n", "\n"):gsub("\\\\", "\\"):gsub("\\t", "\t") + + return str +end + +---@param str string String in single quotes to parse. +---@return string +function M.parse_single(str) + if not vim.startswith(str, "'") or not vim.endswith(str, "'") then + return str + end + + str = vim.fn.strcharpart(str, 1, #str - 2) + str = str:gsub("\\'", "'") + + return str +end + +return M diff --git a/tests/nvim-dap-envfile/load_env_file_spec.lua b/tests/nvim-dap-envfile/load_env_file_spec.lua new file mode 100644 index 0000000..5d556dd --- /dev/null +++ b/tests/nvim-dap-envfile/load_env_file_spec.lua @@ -0,0 +1,44 @@ +local M = require("nvim-dap-envfile") +local path = M.expand_path_vars("${fileDirname}/tests/nvim-dap-envfile/test.env") + +describe("load_env_file", function() + it("loads basic values", function() + local got = M.load_env_file(path) + assert.equal(got.basic, "value") + end) + + it("trims spaces", function() + local got = M.load_env_file(path) + assert.equal(got.with_spaces, "value") + end) + + it("trims double quotes", function() + local got = M.load_env_file(path) + assert.equal(got.double_quotes, "value") + end) + + it("trims spaces, then double quotes", function() + local got = M.load_env_file(path) + assert.equal(got.double_quotes_spaces, "value") + end) + + it("trims single quotes", function() + local got = M.load_env_file(path) + assert.equal(got.single_quotes, "value") + end) + + it("handles double escape", function() + local got = M.load_env_file(path) + assert.equal(got.double_escape, '"value"') + end) + + it("handles single escape", function() + local got = M.load_env_file(path) + assert.equal(got.single_escape, "'value'") + end) + + it("handles special characters", function() + local got = M.load_env_file(path) + assert.equal(got.double_special, '\n\t"\\') + end) +end) diff --git a/tests/nvim-dap-envfile/test.env b/tests/nvim-dap-envfile/test.env new file mode 100644 index 0000000..c0b7320 --- /dev/null +++ b/tests/nvim-dap-envfile/test.env @@ -0,0 +1,12 @@ +basic=value + +with_spaces= value + +double_quotes="value" +double_quotes_spaces= "value" +single_quotes='value' + +double_special="\n\t\"\\" + +double_escape="\"value\"" +single_escape='\'value\''