Hans – Public Notes

Periodically backup terminal buffers in neovim

local backup_directory = vim.fn.expand("~/.config/nvim/terminal_backups/")

-- Ensure backup directory exists
if vim.fn.isdirectory(backup_directory) == 0 then
  vim.fn.mkdir(backup_directory, "p")
end

local function sanitize_filename(filename)
  return filename:gsub("[^%w_]", "_")
end

local function is_terminal_buffer(bufnr)
  local buftype = vim.api.nvim_buf_get_option(bufnr, "buftype")
  return buftype == "terminal"
end

local function backup_terminal_buffer(bufnr)
  if not is_terminal_buffer(bufnr) then return end

  local bufname = sanitize_filename(vim.api.nvim_buf_get_name(bufnr))
  local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
  local backup_file_path = backup_directory .. bufname .. ".txt"

  -- Read current backup file if exists
  local current_lines = {}
  if vim.fn.filereadable(backup_file_path) == 1 then
    local file = io.open(backup_file_path, "r")
    for line in file:lines() do
      table.insert(current_lines, line)
    end
    file:close()
  end

  -- Append new lines avoiding duplicates
  local line_set = {}
  for _, line in ipairs(current_lines) do
    line_set[line] = true
  end

  for _, line in ipairs(lines) do
    if not line_set[line] then
      table.insert(current_lines, line)
      line_set[line] = true
    end
  end

  -- Write back to the file
  local backup_file = io.open(backup_file_path, "w")
  if backup_file then
    for _, line in ipairs(current_lines) do
      backup_file:write(line .. "\n")
    end
    backup_file:close()
  else
    print("Error: Could not open backup file.")
  end
end

local function backup_all_terminal_buffers()
  for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
    backup_terminal_buffer(bufnr)
  end
end

-- Set up a timer to run the backup function
local backup_interval = 10000 -- 10 seconds in milliseconds
local timer = vim.loop.new_timer()
timer:start(0, backup_interval, vim.schedule_wrap(backup_all_terminal_buffers))
EOF