From 01a482d91f93ae036120650ad18ae9c1d0106de8 Mon Sep 17 00:00:00 2001 From: Dominik Polakovics Date: Tue, 10 Dec 2024 22:59:20 +0100 Subject: [PATCH] initial commit --- lua/chatgpt_nvim/context.lua | 67 ++++++++++++++++++++++++++++++++++++ lua/chatgpt_nvim/handler.lua | 51 +++++++++++++++++++++++++++ lua/chatgpt_nvim/init.lua | 39 +++++++++++++++++++++ plugin/chatgpt.vim | 3 ++ 4 files changed, 160 insertions(+) create mode 100644 lua/chatgpt_nvim/context.lua create mode 100644 lua/chatgpt_nvim/handler.lua create mode 100644 lua/chatgpt_nvim/init.lua create mode 100644 plugin/chatgpt.vim diff --git a/lua/chatgpt_nvim/context.lua b/lua/chatgpt_nvim/context.lua new file mode 100644 index 0000000..0ddeb36 --- /dev/null +++ b/lua/chatgpt_nvim/context.lua @@ -0,0 +1,67 @@ +local M = {} + +function M.get_current_file() + local buf = vim.api.nvim_get_current_buf() + local path = vim.api.nvim_buf_get_name(buf) + if path == "" then + path = "untitled" + end + local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false) + local content = table.concat(lines, "\n") + return content, path +end + +function M.get_project_structure() + local handle = io.popen("git ls-files 2>/dev/null") + if handle then + local result = handle:read("*a") + handle:close() + if result and result ~= "" then + return "Files:\n" .. result + end + end + + -- Fallback if not in a git repo + local dhandle = io.popen("find . -type f") + if dhandle then + local dresult = dhandle:read("*a") + dhandle:close() + return "Files:\n" .. (dresult or "") + end + + return "No files found." +end + +-- Helper to find the git root directory +local function get_git_root() + local handle = io.popen("git rev-parse --show-toplevel 2>/dev/null") + if handle then + local root = handle:read("*l") + handle:close() + if root and root ~= "" then + return root + end + end + return nil +end + +-- Attempt to read README.md from the root of the git repository +function M.get_readme_content() + local root = get_git_root() + if not root then + return nil + end + + local readme_path = root .. "/README.md" + local f = io.open(readme_path, "r") + if f then + local content = f:read("*a") + f:close() + if content and content ~= "" then + return content + end + end + return nil +end + +return M diff --git a/lua/chatgpt_nvim/handler.lua b/lua/chatgpt_nvim/handler.lua new file mode 100644 index 0000000..b159a7c --- /dev/null +++ b/lua/chatgpt_nvim/handler.lua @@ -0,0 +1,51 @@ +local M = {} + +-- paste_code_from_clipboard: +-- The user copies a code block from the website (which includes a first line with the file path), +-- and then runs :ChatGPTPaste. +-- We retrieve the clipboard content, extract the first line as a path, and the rest as code. +function M.paste_code_from_clipboard() + local clipboard_content = vim.fn.getreg('+') + if clipboard_content == "" then + vim.api.nvim_err_writeln("Clipboard is empty. Copy the code block from the website first.") + return + end + + local lines = {} + for line in clipboard_content:gmatch("[^\r\n]+") do + table.insert(lines, line) + end + + if #lines == 0 then + vim.api.nvim_err_writeln("No content in clipboard to parse.") + return + end + + local filepath = lines[1] + local code_lines = {} + for i = 2, #lines do + table.insert(code_lines, lines[i]) + end + + local code = table.concat(code_lines, "\n") + M.write_file(filepath, code) + print("Wrote file: " .. filepath) +end + +function M.write_file(filepath, content) + -- Create directories if needed + local dir = filepath:match("(.*/)") + if dir and dir ~= "" then + vim.fn.mkdir(dir, "p") + end + + local f = io.open(filepath, "w") + if f then + f:write(content) + f:close() + else + vim.api.nvim_err_writeln("Failed to write file: " .. filepath) + end +end + +return M diff --git a/lua/chatgpt_nvim/init.lua b/lua/chatgpt_nvim/init.lua new file mode 100644 index 0000000..584f0eb --- /dev/null +++ b/lua/chatgpt_nvim/init.lua @@ -0,0 +1,39 @@ +local M = {} + +local context = require('chatgpt_nvim.context') + +function M.run_chatgpt_command() + vim.schedule(function() + -- Prompt the user for input + local user_input = vim.fn.input("Message for O1 Model: ") + if user_input == "" then + print("No input provided.") + return + end + + local project_structure = context.get_project_structure() + local current_file_content, current_file_path = context.get_current_file() + local readme_content = context.get_readme_content() + + local sections = { + "User Message:\n" .. user_input, + "\nProject Structure:\n" .. project_structure, + "\nCurrent File:\nPath: " .. current_file_path .. "\n" .. current_file_content, + "\nInstructions:\nPlease return code blocks for the changes. Each code block must start with the file path on the first line, followed by the code.", + "Do not comment out the file path. Just plain text.", + "If multiple files are needed, return multiple code blocks each starting with a file path." + } + + if readme_content then + table.insert(sections, "\nREADME Content:\n" .. readme_content) + end + + local prompt = table.concat(sections, "\n") + + -- Copy prompt to clipboard so user can paste it into the website form. + vim.fn.setreg('+', prompt) + print("Prompt (including README if found) copied to clipboard! Paste it into the website form.") + end) +end + +return M diff --git a/plugin/chatgpt.vim b/plugin/chatgpt.vim new file mode 100644 index 0000000..1ad2087 --- /dev/null +++ b/plugin/chatgpt.vim @@ -0,0 +1,3 @@ +" Defines the commands for the plugin +command! ChatGPT lua require('chatgpt_nvim').run_chatgpt_command() +command! ChatGPTPaste lua require('chatgpt_nvim.handler').paste_code_from_clipboard()