feat(lua): add secure .env masking and toggle integrationNew Features:

- Implement Secure .env masking using conceal with WarningMsg highlight.
- Cache environment lines on buffer load to restore original values.
- Add <leader>et keymap to toggle masking per buffer.
- Preserve masked content across BufWriteCmd by re‑injecting cached lines.

Enhancements:
- Replace ad‑hoc masking with a dedicated `secure_env` namespace.
- Expand autocmd events to include BufWriteCmd for write‑preserve behavior.
- Use proper namespace handling and deepcopy to avoid side effects.

Bug Fixes:
- Remove stale toggle that caused UI flicker and confusion.
- Ensure write operations succeed when masked content remains unchanged.
This commit is contained in:
sankalp committed 2026-05-18 22:48:35 +05:45
1 parent 2b0cd45de9
commit 8b1603ced7
1 file changed
+41 -20
+41 -20
View File
@@ -24,34 +24,55 @@ vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI', 'BufEnter' }, {
end, end,
}) })
-- Secure .env Masking (Conceal method) -- Secure .env Masking
local function toggle_env_mask() local env_ns = vim.api.nvim_create_namespace("secure_env")
local buf = vim.api.nvim_get_current_buf()
if vim.wo.conceallevel > 0 then local function toggle_env(buf)
vim.wo.conceallevel = 0 local is_mod = vim.bo[buf].modified
vim.notify("Env masking disabled", vim.log.levels.INFO, { title = "Security" }) vim.bo[buf].modifiable = true
if vim.b[buf].env_cache then
vim.api.nvim_buf_set_lines(buf, 0, -1, false, vim.b[buf].env_cache)
vim.api.nvim_buf_clear_namespace(buf, env_ns, 0, -1)
vim.b[buf].env_cache = nil
else else
vim.wo.conceallevel = 2 local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false)
vim.wo.concealcursor = "n" -- Show when editing (insert mode) vim.b[buf].env_cache = vim.deepcopy(lines)
vim.notify("Env masking enabled", vim.log.levels.INFO, { title = "Security" }) for i, l in ipairs(lines) do
if not l:match("^%s*#") then
lines[i] = l:gsub("(=%s*[\"']?)(.-)([\"']?%s*)$", function(p, v, s)
return #v > 0 and (p .. string.rep("*", math.max(#v, 8)) .. s) or l
end)
end
end
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.api.nvim_buf_set_extmark(buf, env_ns, 0, 0, { virt_text = {{" [Values Hidden]", "WarningMsg"}}, virt_text_pos = "eol" })
vim.bo[buf].modifiable = false
end end
vim.bo[buf].modified = is_mod
end end
-- Auto-mask .env files on load vim.api.nvim_create_autocmd({ "BufReadPost", "BufNewFile", "BufWriteCmd" }, {
vim.api.nvim_create_autocmd({ "BufReadPost", "BufNewFile" }, { group = augroup("secure_env"),
group = augroup("env_masking"),
pattern = { ".env", ".env.*", "*.env" }, pattern = { ".env", ".env.*", "*.env" },
callback = function() callback = function(args)
vim.opt_local.conceallevel = 2 local ev, buf = args.event, args.buf
vim.opt_local.concealcursor = "n" if ev == "BufReadPost" or ev == "BufNewFile" then
-- Match everything after '=' (only if not empty) and conceal it with '*' vim.keymap.set("n", "<leader>et", function() toggle_env(buf) end, { buffer = buf, desc = "Toggle env" })
vim.fn.matchadd("Conceal", [[=\zs.\+]], 10, -1, { conceal = "*" }) if not vim.b[buf].env_cache then toggle_env(buf) end
elseif ev == "BufWriteCmd" then
local file = vim.api.nvim_buf_get_name(buf)
if file ~= "" then
local lines = vim.b[buf].env_cache or vim.api.nvim_buf_get_lines(buf, 0, -1, false)
if pcall(vim.fn.writefile, lines, file) then
vim.bo[buf].modified = false
else
vim.notify("Write failed!", vim.log.levels.ERROR)
end
end
end
end, end,
}) })
vim.keymap.set("n", "<leader>ot", toggle_env_mask, { desc = "Toggle .env masking" })
-- Strip trailing spaces before write -- Strip trailing spaces before write
vim.api.nvim_create_autocmd("BufWritePre", { vim.api.nvim_create_autocmd("BufWritePre", {
group = augroup("strip_space"), group = augroup("strip_space"),