From cc37c8505c01e6d4ee6c2a02a3c8fff7f97a6233 Mon Sep 17 00:00:00 2001 From: Dominik Polakovics Date: Fri, 13 Dec 2024 02:30:54 +0100 Subject: [PATCH] feat: add the possibility to delete files. and restrict the editing of files to inside the project --- lua/chatgpt_nvim/config.lua | 2 +- lua/chatgpt_nvim/handler.lua | 12 ++++++++++++ lua/chatgpt_nvim/init.lua | 27 +++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/lua/chatgpt_nvim/config.lua b/lua/chatgpt_nvim/config.lua index 805fcb3..5bfc763 100644 --- a/lua/chatgpt_nvim/config.lua +++ b/lua/chatgpt_nvim/config.lua @@ -50,7 +50,7 @@ end local prompt_blocks = { ["go-development"] = "You are a coding assistant specialized in Go development. You will receive a project’s context and user instructions related to Go code, and you must return the requested modifications or guidance. When returning modifications, follow the specified YAML structure. Keep your suggestions aligned with Go best practices and idiomatic Go.", ["typo3-development"] = "You are a coding assistant specialized in TYPO3 development. You have access to the project’s context and the user’s instructions. Your answers should focus on TYPO3 coding guidelines, extension development best practices, and TSconfig or TypoScript recommendations. When returning modifications, follow the YAML structure given.", - ["basic-prompt"] = "You are a coding assistant who receives a project’s context and user instructions. The user will provide a prompt, and you will return modifications to the project in a YAML structure. The YAML must have a top-level key named files, which should be a list of file changes. Each element in files must be a mapping with the keys path and content. The path should be the file path relative to the project’s root directory, and content should contain the new file content as a multiline string. Do not include additional commentary outside of the YAML.\nAlso include a top-level key named project_name that must match the project's configured name." + ["basic-prompt"] = "You are a coding assistant who receives a project’s context and user instructions. The user will provide a prompt, and you will return modifications to the project in a YAML structure. The YAML must have a top-level key named files, which should be a list of file changes. Each element in files must be a mapping with the keys path and either content (for file creation or modification) or delete: true (if the file should be deleted). The path should be the file path relative to the project’s root directory. If content is provided, it should contain the new file content as a multiline string. If delete: true is used, do not include content. If more context is needed, tell it outside of the YAML.\nAlso include a top-level key named project_name that must match the project's configured name." } function M.load() diff --git a/lua/chatgpt_nvim/handler.lua b/lua/chatgpt_nvim/handler.lua index dfa1629..90c523b 100644 --- a/lua/chatgpt_nvim/handler.lua +++ b/lua/chatgpt_nvim/handler.lua @@ -32,6 +32,18 @@ function M.write_file(filepath, content) uv.fs_close(fd) end +function M.delete_file(filepath) + 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")) + end + else + vim.api.nvim_err_writeln("File not found, cannot delete: " .. filepath) + end +end + function M.finish() print("Finished processing files.") end diff --git a/lua/chatgpt_nvim/init.lua b/lua/chatgpt_nvim/init.lua index 4dea882..e68463f 100644 --- a/lua/chatgpt_nvim/init.lua +++ b/lua/chatgpt_nvim/init.lua @@ -31,6 +31,12 @@ local function estimate_tokens(text) return math.floor(length / approx_chars_per_token) end +local function is_subpath(root, path) + local root_abs = vim.fn.fnamemodify(root, ":p") + local target_abs = vim.fn.fnamemodify(path, ":p") + return target_abs:sub(1, #root_abs) == root_abs +end + function M.run_chatgpt_command() local conf = config.load() local user_input = vim.fn.input("Message for O1 Model: ") @@ -90,13 +96,30 @@ function M.run_chatgpt_paste_command() return end + local root = vim.fn.getcwd() + for _, fileinfo in ipairs(data.files) do - if fileinfo.path and fileinfo.content then + if not fileinfo.path then + vim.api.nvim_err_writeln("Invalid file entry. Must have 'path'.") + goto continue + end + + -- Ensure the path is within the project root + if not is_subpath(root, fileinfo.path) then + vim.api.nvim_err_writeln("Invalid file path outside project root: " .. fileinfo.path) + goto continue + end + + if fileinfo.delete == true then + handler.delete_file(fileinfo.path) + print("Deleted file: " .. fileinfo.path) + elseif fileinfo.content then handler.write_file(fileinfo.path, fileinfo.content) print("Wrote file: " .. fileinfo.path) else - vim.api.nvim_err_writeln("Invalid file entry. Must have 'path' and 'content'.") + vim.api.nvim_err_writeln("Invalid file entry. Must have 'content' or 'delete' set to true.") end + ::continue:: end end