summaryrefslogtreecommitdiff
path: root/lua/vim/userregs/impl/fileregister.lua
blob: 0ec1715931a0944e5f4ce775c586b9f6a4d6f099 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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 {}