local api = vim.api local ag = api.nvim_create_augroup('sops', {}) local function path_from_uri(uri) return string.sub(uri, string.len('sops://') + 1) end local function write_buf(buf) local file = path_from_uri(api.nvim_buf_get_name(buf)) local cmd = vim.system({ 'sh', '-c', vim.fn.printf( 'sops encrypt --filename-override %s --output %s <(cat)', -- ugly work around /dev/stdout not existing in vim.system() vim.fn.shellescape(file), vim.fn.shellescape(file)), }, { stdin = api.nvim_buf_get_lines(buf, 0, -1, true), }) local res = cmd:wait() if res.code > 0 then vim.notify('Could not encrypt ' .. vim.fn.fnamemodify(file, ':p:.') .. ': ' .. res.stderr, vim.log.levels.WARN) return end api.nvim_set_option_value('modified', false, { buf = buf }) vim.notify('Saved encrypted file ' .. vim.fn.fnamemodify(file, ':p:.'), vim.log.levels.INFO) end -- @param buf number local function setup_buffer(buf) if api.nvim_get_option_value('buftype', { buf = buf }) == 'acwrite' then -- was here already return end api.nvim_set_option_value('buftype', 'acwrite', { buf = buf }) api.nvim_set_option_value('swapfile', false, { buf = buf }) -- encrypted data shouldn't be laying around.... api.nvim_create_autocmd('BufWriteCmd', { group = ag, buffer = buf, callback = function(ev) write_buf(ev.buf) end, }) end -- @param file string -- @return string local function load_buf(buf) local file = path_from_uri(api.nvim_buf_get_name(buf)) local res = vim.system({ 'sops', 'decrypt', file }, { text = true }):wait() if res.code > 0 then vim.notify('Could not decrypt ' .. file .. ': ' .. res.stderr, vim.log.levels.WARN) return end vim.cmd.doautocmd({"BufReadPre", file}) api.nvim_buf_set_lines(buf, 0, -1, true, vim.split(res.stdout, '\n')) setup_buffer(buf) vim.notify('Decrypted file ' .. vim.fn.fnamemodify(file, ':p:.'), vim.log.levels.INFO) vim.cmd.doautocmd({"BufReadPost", file}) end api.nvim_create_autocmd('BufReadCmd', { group = ag, pattern = 'sops://*', callback = function(ev) local buf = ev.buf load_buf(buf) end, }) api.nvim_create_user_command('SopsEdit', function(opts) local fargs = opts.fargs local file = nil local args = { args = {}, bang = opts.bang } if #fargs == 0 then file = api.nvim_buf_get_name(0) if string.sub(file, 0, string.len('sops://')) ~= 'sops://' then args.args = { 'sops://' .. file } end else file = fargs[1] if string.sub(file, 0, string.len('sops://')) ~= 'sops://' then file = 'sops://' .. vim.fn.fnamemodify(file, ':p') end args.args = { file } end vim.cmd.edit(args) end, { bang = true, complete = 'file', nargs = '?', })