aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/clipboard/osc52.lua
blob: 035a6abb864191c613820a3b0231d86b181a5e79 (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
local M = {}

function M.copy(lines)
  local s = table.concat(lines, '\n')
  io.stdout:write(string.format('\027]52;;%s\027\\', vim.base64.encode(s)))
end

function M.paste()
  local contents = nil
  local id = vim.api.nvim_create_autocmd('TermResponse', {
    callback = function(args)
      local resp = args.data ---@type string
      local encoded = resp:match('\027%]52;%w?;([A-Za-z0-9+/=]*)')
      if encoded then
        contents = vim.base64.decode(encoded)
        return true
      end
    end,
  })

  io.stdout:write('\027]52;;?\027\\')

  local ok, res

  -- Wait 1s first for terminals that respond quickly
  ok, res = vim.wait(1000, function()
    return contents ~= nil
  end)

  if res == -1 then
    -- If no response was received after 1s, print a message and keep waiting
    vim.api.nvim_echo(
      { { 'Waiting for OSC 52 response from the terminal. Press Ctrl-C to interrupt...' } },
      false,
      {}
    )
    ok, res = vim.wait(9000, function()
      return contents ~= nil
    end)
  end

  if not ok then
    vim.api.nvim_del_autocmd(id)
    if res == -1 then
      vim.notify(
        'Timed out waiting for a clipboard response from the terminal',
        vim.log.levels.WARN
      )
    elseif res == -2 then
      -- Clear message area
      vim.api.nvim_echo({ { '' } }, false, {})
    end
    return 0
  end

  -- If we get here, contents should be non-nil
  return vim.split(assert(contents), '\n')
end

return M