summaryrefslogtreecommitdiff
path: root/lua/vim/userregs/impl/fileregister.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/vim/userregs/impl/fileregister.lua')
-rw-r--r--lua/vim/userregs/impl/fileregister.lua73
1 files changed, 73 insertions, 0 deletions
diff --git a/lua/vim/userregs/impl/fileregister.lua b/lua/vim/userregs/impl/fileregister.lua
new file mode 100644
index 0000000..0ec1715
--- /dev/null
+++ b/lua/vim/userregs/impl/fileregister.lua
@@ -0,0 +1,73 @@
+--- Fileregister: maps the '&' register to an external file.
+---
+--- This register reads from or writes to a file defined by `g:fileregister_filename`
+--- or defaults to `${RUN_DIRECTORY}/fileregister`.
+---
+--- On yank, the content is saved as JSON.
+--- On put, the content is decoded from JSON (if valid) or interpreted as raw lines.
+
+local userregs = require("vim.userregs")
+local api = vim.api
+
+local handler = {}
+
+--- Get the filename used for this register.
+--- Defaults to /tmp/.vim.$USER.fileregister
+---@return string
+local function get_file_name()
+ return vim.g.fileregister_filename
+ or (vim.fn.stdpath("run") .. "/fileregister")
+end
+
+--- Write the yanked content into the fileregister as JSON.
+---@param _ string register name (ignored)
+---@param content table content from 'userregfunc'
+function handler.yank(_, content)
+ local filename = get_file_name()
+ local ok, encoded = pcall(vim.json.encode, content)
+ if not ok then
+ vim.notify("[fileregister] Failed to encode content to JSON", vim.log.levels.ERROR)
+ return
+ end
+
+ local f = io.open(filename, "w")
+ if not f then
+ vim.notify("[fileregister] Could not open file for writing: " .. filename, vim.log.levels.ERROR)
+ return
+ end
+
+ f:write(encoded)
+ f:close()
+end
+
+--- Read from the file. If it's valid JSON, decode as register content.
+--- Otherwise, interpret it as a list of lines.
+---@param _ string register name (ignored)
+---@return table|string
+function handler.put(_)
+ local filename = get_file_name()
+ local f = io.open(filename, "r")
+
+ if not f then
+ return {}
+ end
+
+ local content = f:read("*a")
+ f:close()
+
+ if content:sub(1, 1) == "{" then
+ local ok, decoded = pcall(vim.json.decode, content)
+ if ok then return decoded end
+ end
+
+ local lines = {}
+ for line in content:gmatch("[^\r\n]+") do
+ table.insert(lines, line)
+ end
+ return lines
+end
+
+-- Register the '&' fileregister
+userregs.register_handler('&', handler)
+
+return {}