local M = {} local uv = vim.loop local config = require('chatgpt_nvim.config') local function ensure_dir(path) local st = uv.fs_stat(path) if st and st.type == 'directory' then return true end local parent = path:match("(.*)/") if parent and parent ~= "" then ensure_dir(parent) end uv.fs_mkdir(path, 511) return true end function M.get_clipboard_content() local conf = config.load() local content = vim.fn.getreg('+') if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] Clipboard content length: " .. #content .. "\n") end return content end function M.write_file(filepath, content) local conf = config.load() local dir = filepath:match("(.*)/") if dir and dir ~= "" then ensure_dir(dir) end local fd = uv.fs_open(filepath, "w", 438) if not fd then vim.api.nvim_err_writeln("Could not open file for writing: " .. filepath) if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] Failed to open file for writing: " .. filepath .. "\n") end return end uv.fs_write(fd, content, -1) uv.fs_close(fd) if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] Successfully wrote file: " .. filepath .. "\n") end end function M.delete_file(filepath) local conf = config.load() local st = uv.fs_stat(filepath) if st then local success, err = uv.fs_unlink(filepath) if not success then vim.api.nvim_err_writeln("Could not delete file: " .. filepath .. " - " .. (err or "unknown error")) if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] Failed to delete file: " .. filepath .. "\n") end else if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] Deleted file: " .. filepath .. "\n") end end else vim.api.nvim_err_writeln("File not found, cannot delete: " .. filepath) if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] File not found for deletion: " .. filepath .. "\n") end end end -- Applies a unified diff to the specified file. function M.apply_diff(filepath, diff_content) local conf = config.load() local tmp_original = vim.fn.tempname() local tmp_patch = vim.fn.tempname() -- 1) Read original file (or empty if it doesn't exist) local fd_in = uv.fs_open(filepath, "r", 438) local original_data = "" if fd_in then local stat = uv.fs_fstat(fd_in) original_data = uv.fs_read(fd_in, stat.size, 0) uv.fs_close(fd_in) end -- 2) Write original content to a temp file local fd_orig = uv.fs_open(tmp_original, "w", 438) if fd_orig then uv.fs_write(fd_orig, original_data, -1) uv.fs_close(fd_orig) end -- 3) Write diff to a temp file local fd_patch = uv.fs_open(tmp_patch, "w", 438) if fd_patch then uv.fs_write(fd_patch, diff_content, -1) uv.fs_close(fd_patch) else return false, "Could not open temporary file to write patch." end if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] Applying diff to: " .. filepath .. "\n") vim.api.nvim_out_write("[chatgpt_nvim:handler] Original file contents saved at: " .. tmp_original .. "\n") vim.api.nvim_out_write("[chatgpt_nvim:handler] Patch file saved at: " .. tmp_patch .. "\n") vim.api.nvim_out_write("[chatgpt_nvim:handler] Patch contents:\n" .. diff_content .. "\n") end -- 4) Attempt to run 'patch' local patch_cmd = "patch -u --reject-file=- " .. vim.fn.shellescape(tmp_original) .. " < " .. vim.fn.shellescape(tmp_patch) local handle = io.popen(patch_cmd) if not handle then return false, "Failed to run patch command." end local result = handle:read("*a") local success_close, errmsg = handle:close() if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] Patch command was: " .. patch_cmd .. "\n") vim.api.nvim_out_write("[chatgpt_nvim:handler] Patch command output:\n" .. (result or "") .. "\n") if not success_close then vim.api.nvim_out_write("[chatgpt_nvim:handler] Patch command closed with error: " .. (errmsg or "unknown") .. "\n") else vim.api.nvim_out_write("[chatgpt_nvim:handler] Patch command succeeded.\n") end end if not success_close then if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] Patch command failed: " .. (errmsg or "unknown") .. "\n") end return false, errmsg end -- If successful, read the patched file and write it back if conf.debug then local debug_read = uv.fs_open(tmp_original, "r", 438) if debug_read then local debug_stat = uv.fs_fstat(debug_read) local debug_data = uv.fs_read(debug_read, debug_stat.size, 0) uv.fs_close(debug_read) vim.api.nvim_out_write("[chatgpt_nvim:handler] Post-patch temp file:\n" .. debug_data .. "\n") vim.api.nvim_out_write("[chatgpt_nvim:handler] End of patched temp file content.\n") end end local fd_out = uv.fs_open(tmp_original, "r", 438) if fd_out then local stat_out = uv.fs_fstat(fd_out) local new_data = uv.fs_read(fd_out, stat_out.size, 0) uv.fs_close(fd_out) M.write_file(filepath, new_data) if conf.debug then vim.api.nvim_out_write("[chatgpt_nvim:handler] Successfully applied patch to: " .. filepath .. "\n") end else return false, "Could not read patched file." end return true end function M.finish() print("Finished processing files.") end return M