summaryrefslogtreecommitdiff
path: root/lua/vim/userregs
diff options
context:
space:
mode:
Diffstat (limited to 'lua/vim/userregs')
-rw-r--r--lua/vim/userregs/impl/basename.lua28
-rw-r--r--lua/vim/userregs/impl/buffercontents.lua39
-rw-r--r--lua/vim/userregs/impl/dirname.lua27
-rw-r--r--lua/vim/userregs/impl/fileregister.lua73
-rw-r--r--lua/vim/userregs/impl/timestamp.lua22
-rw-r--r--lua/vim/userregs/impl/uuid_register.lua18
-rw-r--r--lua/vim/userregs/impl/visualselection.lua51
7 files changed, 258 insertions, 0 deletions
diff --git a/lua/vim/userregs/impl/basename.lua b/lua/vim/userregs/impl/basename.lua
new file mode 100644
index 0000000..a46a381
--- /dev/null
+++ b/lua/vim/userregs/impl/basename.lua
@@ -0,0 +1,28 @@
+--- Basename Register: returns the current filename without path and extension.
+---
+--- This is similar to the "%" register (full filename), but returns only
+--- the basename with one extension removed. Useful, for example, when referencing
+--- Java class names based on the file name.
+---
+--- This register is read-only and assigned to the character '$'.
+
+local userregs = require("vim.userregs")
+local api = vim.api
+
+---@type table<string, fun(regname: string): any>
+local handler = {}
+
+--- Return the current buffer's basename without extension.
+--- Equivalent to `expand('%:t:r')`
+function handler.put(regname)
+ return vim.fn.expand('%:t:r')
+end
+
+-- Make this register read-only by omitting the yank handler.
+handler.yank = nil
+
+-- Register this handler under the user register '$'.
+userregs.register_handler('$', handler)
+
+
+return {}
diff --git a/lua/vim/userregs/impl/buffercontents.lua b/lua/vim/userregs/impl/buffercontents.lua
new file mode 100644
index 0000000..016b4e5
--- /dev/null
+++ b/lua/vim/userregs/impl/buffercontents.lua
@@ -0,0 +1,39 @@
+local userregs = require("vim.userregs")
+
+-- Register name: "|"
+-- This register represents the full contents of the current buffer.
+-- Yank into it → saves the buffer.
+-- Put from it → replaces the buffer contents.
+
+local regname = "|"
+
+--- Reads the full contents of the current buffer as a list of lines.
+--- This is returned in the format expected by 'userregfunc'.
+--- @return table a 'put' dictionary with `lines`, `type`, and `additional_data`
+local function read_current_buffer()
+ local bufnr = vim.api.nvim_get_current_buf()
+ local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
+
+ return {
+ lines = lines,
+ type = "V", -- linewise register
+ additional_data = {},
+ }
+end
+
+--- Replaces the entire contents of the current buffer with the given content.
+--- Used when yanking into the "|" register.
+--- @param _ string -- register name (ignored here)
+--- @param content table -- dictionary with `lines` from yankreg_T
+local function write_current_buffer(_, content)
+ local bufnr = vim.api.nvim_get_current_buf()
+
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, content.lines or {})
+end
+
+-- Register the "|" register with the userregs framework
+userregs.register_handler(regname, {
+ put = function(_) return read_current_buffer() end,
+ yank = write_current_buffer,
+})
+
diff --git a/lua/vim/userregs/impl/dirname.lua b/lua/vim/userregs/impl/dirname.lua
new file mode 100644
index 0000000..503601d
--- /dev/null
+++ b/lua/vim/userregs/impl/dirname.lua
@@ -0,0 +1,27 @@
+--- Dirname Register: returns the direction for the filename.
+---
+--- This is similar to the "%" register (full filename), but returns only
+--- the the directory.
+---
+--- This register is read-only and assigned to the character '<C-d>'.
+
+local userregs = require("vim.userregs")
+local api = vim.api
+
+---@type table<string, fun(regname: string): any>
+local handler = {}
+
+--- Return the current buffer's basename without extension.
+--- Equivalent to `expand('%:t:r')`
+function handler.put(regname)
+ return vim.fn.expand('%:p:h') .. '/'
+end
+
+-- Make this register read-only by omitting the yank handler.
+handler.yank = nil
+
+-- Register this handler under the user register '<C-d>'.
+userregs.register_handler('\4', handler)
+
+
+return {}
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 {}
diff --git a/lua/vim/userregs/impl/timestamp.lua b/lua/vim/userregs/impl/timestamp.lua
new file mode 100644
index 0000000..517dd43
--- /dev/null
+++ b/lua/vim/userregs/impl/timestamp.lua
@@ -0,0 +1,22 @@
+local userregs = require("vim.userregs")
+
+-- Get format from g:timestamp_register_format or use fallback
+local function get_timestamp_format()
+ return vim.g.timestamp_register_format or "%Y-%m-%d %H:%M:%S"
+end
+
+local function generate_timestamp()
+ local ok, result = pcall(os.date, get_timestamp_format())
+ if not ok then
+ vim.notify("[userregs] Invalid timestamp format", vim.log.levels.WARN)
+ return os.date("%Y-%m-%d %H:%M:%S")
+ end
+ return result
+end
+
+userregs.register_handler('\20', {
+ put = function()
+ return generate_timestamp()
+ end,
+ yank = nil, -- read-only
+})
diff --git a/lua/vim/userregs/impl/uuid_register.lua b/lua/vim/userregs/impl/uuid_register.lua
new file mode 100644
index 0000000..de45de1
--- /dev/null
+++ b/lua/vim/userregs/impl/uuid_register.lua
@@ -0,0 +1,18 @@
+local userregs = require("vim.userregs")
+
+local function generate_uuid()
+ local random = math.random
+ local template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
+ return string.gsub(template, "[xy]", function(c)
+ local v = (c == "x") and random(0, 0xf) or random(8, 0xb)
+ return string.format("%x", v)
+ end)
+end
+
+userregs.register_handler("\21", { -- Ctrl+U
+ put = function()
+ return generate_uuid()
+ end,
+ yank = nil, -- read-only
+})
+
diff --git a/lua/vim/userregs/impl/visualselection.lua b/lua/vim/userregs/impl/visualselection.lua
new file mode 100644
index 0000000..93cb370
--- /dev/null
+++ b/lua/vim/userregs/impl/visualselection.lua
@@ -0,0 +1,51 @@
+local userregs = require("vim.userregs")
+
+-- ASCII-safe register name
+local regname = "\22"
+
+-- Return the contents of the last visual selection
+local function read_last_visual()
+ local bufnr = vim.api.nvim_get_current_buf()
+
+ local start_pos = vim.fn.getpos("'<")
+ local end_pos = vim.fn.getpos("'>")
+
+ if not start_pos or not end_pos then
+ vim.notify("[userregs] No visual selection", vim.log.levels.WARN)
+ return { lines = {}, type = "V" }
+ end
+
+ local start_lnum = start_pos[2] - 1 -- 0-indexed
+ local end_lnum = end_pos[2] -- end line is exclusive
+
+ local lines = vim.api.nvim_buf_get_lines(bufnr, start_lnum, end_lnum, false)
+ return {
+ lines = lines,
+ type = "V", -- Assume linewise for now
+ additional_data = {},
+ }
+end
+
+-- Replace the last visual selection with new content
+local function write_last_visual(_, content)
+ local bufnr = vim.api.nvim_get_current_buf()
+
+ local start_pos = vim.fn.getpos("'<")
+ local end_pos = vim.fn.getpos("'>")
+
+ if not start_pos or not end_pos then
+ vim.notify("[userregs] No visual selection to write into", vim.log.levels.ERROR)
+ return
+ end
+
+ local start_lnum = start_pos[2] - 1
+ local end_lnum = end_pos[2]
+
+ -- Replace the range with the new content
+ vim.api.nvim_buf_set_lines(bufnr, start_lnum, end_lnum, false, content.lines or {})
+end
+
+userregs.register_handler(regname, {
+ put = function() return read_last_visual() end,
+ yank = write_last_visual,
+})