neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

osc52.lua (2136B)


      1 local M = {}
      2 
      3 --- Return the OSC 52 escape sequence
      4 ---
      5 --- @param clipboard string The clipboard to read from or write to
      6 --- @param contents string The Base64 encoded contents to write to the clipboard, or '?' to read
      7 ---                        from the clipboard
      8 local function osc52(clipboard, contents)
      9  return string.format('\027]52;%s;%s\027\\', clipboard, contents)
     10 end
     11 
     12 function M.copy(reg)
     13  local clipboard = reg == '+' and 'c' or 'p'
     14  return function(lines)
     15    local s = table.concat(lines, '\n')
     16    -- The data to be written here can be quite long.
     17    vim.api.nvim_ui_send(osc52(clipboard, vim.base64.encode(s)))
     18  end
     19 end
     20 
     21 function M.paste(reg)
     22  local clipboard = reg == '+' and 'c' or 'p'
     23  return function()
     24    local contents = nil --- @type string?
     25    local id = vim.api.nvim_create_autocmd('TermResponse', {
     26      callback = function(args)
     27        local resp = args.data.sequence ---@type string
     28        local encoded = resp:match('\027%]52;%w?;([A-Za-z0-9+/=]*)')
     29        if encoded then
     30          contents = vim.base64.decode(encoded)
     31          return true
     32        end
     33      end,
     34    })
     35 
     36    vim.api.nvim_ui_send(osc52(clipboard, '?'))
     37 
     38    local ok, res
     39 
     40    -- Wait 1s first for terminals that respond quickly
     41    ok, res = vim.wait(1000, function()
     42      return contents ~= nil
     43    end)
     44 
     45    if res == -1 then
     46      -- If no response was received after 1s, print a message and keep waiting
     47      vim.api.nvim_echo(
     48        { { 'Waiting for OSC 52 response from the terminal. Press Ctrl-C to interrupt...' } },
     49        false,
     50        {}
     51      )
     52      ok, res = vim.wait(9000, function()
     53        return contents ~= nil
     54      end)
     55    end
     56 
     57    if not ok then
     58      vim.api.nvim_del_autocmd(id)
     59      if res == -1 then
     60        vim.notify(
     61          'Timed out waiting for a clipboard response from the terminal',
     62          vim.log.levels.WARN
     63        )
     64      elseif res == -2 then
     65        -- Clear message area
     66        vim.api.nvim_echo({ { '' } }, false, {})
     67      end
     68      return 0
     69    end
     70 
     71    -- If we get here, contents should be non-nil
     72    return vim.split(assert(contents), '\n')
     73  end
     74 end
     75 
     76 return M