feat: changed to and interactive workflow
This commit is contained in:
36
README.md
36
README.md
@@ -1,21 +1,29 @@
|
|||||||
# ChatGPT NeoVim Plugin
|
# ChatGPT NeoVim Plugin
|
||||||
|
|
||||||
This Plugin should help the user to integrate ChatGPT o1 model into the development workflow with neovim.
|
This plugin helps integrate the ChatGPT O1 model into the development workflow with Neovim.
|
||||||
It Provides two commands
|
It provides one main interactive command: `:ChatGPT`.
|
||||||
|
|
||||||
## :ChatGPT
|
## :ChatGPT
|
||||||
This command will ask the user for a prompt.
|
|
||||||
It will then gather the following context:
|
|
||||||
- The project structure based on the git which the currently open file belongs to.
|
|
||||||
- The README.md file content if it exists in the top folder of the project structure.
|
|
||||||
- The currently open file content.
|
|
||||||
|
|
||||||
It also appends to the prompt that every file should be in a code block and the first line of the block
|
**Workflow:**
|
||||||
should always just contain the file path for the file and nothing else. Regardless if it would destroy the code.
|
|
||||||
|
|
||||||
The generated prompt for the ChatGPT o1 model, will than be copied to the clipboard and the user will be asked
|
1. **Initial Prompt:**
|
||||||
to paste it into the website of ChatGPT.
|
When you run `:ChatGPT`, the plugin asks you for a prompt. After entering the prompt, it gathers context:
|
||||||
|
- The project structure based on the git repository of the currently open file.
|
||||||
|
- The `README.md` file content if it exists at the project root.
|
||||||
|
- The currently open file’s content.
|
||||||
|
|
||||||
## :ChatGPTPaste
|
It then constructs a combined prompt and automatically copies it to your system clipboard. You will be instructed to paste this prompt into the ChatGPT O1 model’s website.
|
||||||
This command will look if the clipboard contains a response where the first line is a filepath.
|
|
||||||
It then creates the file and pastes the rest of the response as content into the file.
|
2. **Pasting Prompt into ChatGPT:**
|
||||||
|
Switch to your browser, paste the prompt into ChatGPT’s interface, and submit it. ChatGPT will return one or multiple code blocks. Each code block should start with the file path on the first line, followed by the code.
|
||||||
|
|
||||||
|
3. **Interactive File Pasting:**
|
||||||
|
Return to Neovim. After pressing `<Enter>`, the plugin enters an interactive mode:
|
||||||
|
- It will prompt you to copy the file path (the first line of the returned code block) into your clipboard and press `<Enter>`.
|
||||||
|
- Once you do that, it will store that file path.
|
||||||
|
- Next, it will ask you to copy the file content (the rest of the returned code block) to your clipboard and press `<Enter>` again.
|
||||||
|
- The plugin will then write the pasted content into the file specified by the previously stored path.
|
||||||
|
- After this file is processed, it asks if you want to paste another file. Press `y` to process another file (repeat the steps above) or `n` to finish.
|
||||||
|
|
||||||
|
By following this interactive workflow, you can iteratively apply all changes suggested by ChatGPT O1 model directly into your project files without leaving Neovim.
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ function M.get_project_structure()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Fallback if not in a git repo
|
|
||||||
local dhandle = io.popen("find . -type f")
|
local dhandle = io.popen("find . -type f")
|
||||||
if dhandle then
|
if dhandle then
|
||||||
local dresult = dhandle:read("*a")
|
local dresult = dhandle:read("*a")
|
||||||
@@ -32,26 +31,21 @@ function M.get_project_structure()
|
|||||||
return "No files found."
|
return "No files found."
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Helper to find the git root directory
|
|
||||||
local function get_git_root()
|
local function get_git_root()
|
||||||
local handle = io.popen("git rev-parse --show-toplevel 2>/dev/null")
|
local handle = io.popen("git rev-parse --show-toplevel 2>/dev/null")
|
||||||
if handle then
|
if handle then
|
||||||
local root = handle:read("*l")
|
local root = handle:read("*l")
|
||||||
handle:close()
|
handle:close()
|
||||||
if root and root ~= "" then
|
|
||||||
return root
|
return root
|
||||||
end
|
end
|
||||||
end
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Attempt to read README.md from the root of the git repository
|
|
||||||
function M.get_readme_content()
|
function M.get_readme_content()
|
||||||
local root = get_git_root()
|
local root = get_git_root()
|
||||||
if not root then
|
if not root then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local readme_path = root .. "/README.md"
|
local readme_path = root .. "/README.md"
|
||||||
local f = io.open(readme_path, "r")
|
local f = io.open(readme_path, "r")
|
||||||
if f then
|
if f then
|
||||||
|
|||||||
@@ -1,39 +1,13 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
-- paste_code_from_clipboard:
|
-- Retrieves clipboard content and trims trailing whitespace/newlines
|
||||||
-- The user copies a code block from the website (which includes a first line with the file path),
|
function M.get_clipboard_content()
|
||||||
-- and then runs :ChatGPTPaste.
|
local content = vim.fn.getreg('+')
|
||||||
-- We retrieve the clipboard content, extract the first line as a path, and the rest as code.
|
content = content:gsub("%s+$", "")
|
||||||
function M.paste_code_from_clipboard()
|
return content
|
||||||
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
|
end
|
||||||
|
|
||||||
function M.write_file(filepath, content)
|
function M.write_file(filepath, content)
|
||||||
-- Create directories if needed
|
|
||||||
local dir = filepath:match("(.*/)")
|
local dir = filepath:match("(.*/)")
|
||||||
if dir and dir ~= "" then
|
if dir and dir ~= "" then
|
||||||
vim.fn.mkdir(dir, "p")
|
vim.fn.mkdir(dir, "p")
|
||||||
@@ -48,4 +22,8 @@ function M.write_file(filepath, content)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M.finish()
|
||||||
|
print("All files processed. You can now continue working.")
|
||||||
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local context = require('chatgpt_nvim.context')
|
local context = require('chatgpt_nvim.context')
|
||||||
|
local handler = require('chatgpt_nvim.handler')
|
||||||
|
|
||||||
function M.run_chatgpt_command()
|
function M.run_chatgpt_command()
|
||||||
vim.schedule(function()
|
|
||||||
-- Prompt the user for input
|
-- Prompt the user for input
|
||||||
local user_input = vim.fn.input("Message for O1 Model: ")
|
local user_input = vim.fn.input("Message for O1 Model: ")
|
||||||
if user_input == "" then
|
if user_input == "" then
|
||||||
@@ -16,24 +16,74 @@ function M.run_chatgpt_command()
|
|||||||
local readme_content = context.get_readme_content()
|
local readme_content = context.get_readme_content()
|
||||||
|
|
||||||
local sections = {
|
local sections = {
|
||||||
"User Message:\n" .. user_input,
|
"Following you will get instructions for a development project. First you get a prompt of the user which starts with \"<<<CGP User Message\" in a line and ends with \"<<<CGP User Message End\" in a line.",
|
||||||
"\nProject Structure:\n" .. project_structure,
|
"\nThen you get the project structure which starts with \"<<<CGPT Project Structure\" in a line and ends with \"<<<CGPT Project Structure End\" in a line",
|
||||||
"\nCurrent File:\nPath: " .. current_file_path .. "\n" .. current_file_content,
|
"\nThen you get the current file for context. It contains at the first line the file path, followed by its content.It starts with \"<<<CGPT Current File\" in a line and ends with \"<<<CGPT Current File End\" in a line",
|
||||||
"\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.",
|
"\nLastly you get the content of the README.md for context if it is present. It starts with \"<<<CGPT README\" in a line and ends with \"<<<CGPT README End\" in a line",
|
||||||
"Do not comment out the file path. Just plain text.",
|
"\nReturn code blocks for the changes.",
|
||||||
"If multiple files are needed, return multiple code blocks each starting with a file path."
|
"\nIf it makes sense, also update the README.md to reflect the changes made.",
|
||||||
|
"\n\n<<<CGPT User Message\n",
|
||||||
|
user_input,
|
||||||
|
"\n<<<CGPT User Message END",
|
||||||
|
"\n\n<<<CGPT Project Structure\n",
|
||||||
|
project_structure,
|
||||||
|
"\n<<<CGPT Project Structure END",
|
||||||
|
"\n\n<<<CGPT Current File\n",
|
||||||
|
current_file_path .. "\n" .. current_file_content,
|
||||||
|
"\n\n<<<CGPT Current File END\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
if readme_content then
|
if readme_content then
|
||||||
table.insert(sections, "\nREADME Content:\n" .. readme_content)
|
table.insert(sections, "\n\n<<<CGPT README\n" .. readme_content .. "\n<<<CGPT README END")
|
||||||
end
|
end
|
||||||
|
|
||||||
local prompt = table.concat(sections, "\n")
|
local prompt = table.concat(sections, "\n")
|
||||||
|
|
||||||
-- Copy prompt to clipboard so user can paste it into the website form.
|
-- Copy prompt to clipboard so user can paste it into the website form.
|
||||||
vim.fn.setreg('+', prompt)
|
vim.fn.setreg('+', prompt)
|
||||||
print("Prompt (including README if found) copied to clipboard! Paste it into the website form.")
|
print("Prompt copied to clipboard! Please paste it into the website form and get the response from the ChatGPT O1 model.")
|
||||||
end)
|
print("Press <Enter> once you've pasted the prompt into the website and have the first file ready to copy.")
|
||||||
|
vim.fn.input("") -- wait for user to press Enter
|
||||||
|
|
||||||
|
while true do
|
||||||
|
-- Ask user for filepath
|
||||||
|
local filepath = ""
|
||||||
|
while true do
|
||||||
|
print("Please copy the FILE PATH (the first line of the code block) to your clipboard.")
|
||||||
|
print("Press <Enter> when done.")
|
||||||
|
vim.fn.input("") -- Wait for user confirmation
|
||||||
|
filepath = handler.get_clipboard_content()
|
||||||
|
if filepath == "" then
|
||||||
|
vim.api.nvim_err_writeln("Clipboard is empty. Please copy the file path and try again.")
|
||||||
|
else
|
||||||
|
print("Got file path: " .. filepath)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Ask user for file content
|
||||||
|
local filecontent = ""
|
||||||
|
while true do
|
||||||
|
print("Now copy the FILE CONTENT (everything after the first line) to your clipboard.")
|
||||||
|
print("Press <Enter> when done.")
|
||||||
|
vim.fn.input("") -- Wait for user confirmation
|
||||||
|
filecontent = handler.get_clipboard_content()
|
||||||
|
if filecontent == "" then
|
||||||
|
vim.api.nvim_err_writeln("Clipboard is empty. Please copy the file content and try again.")
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
handler.write_file(filepath, filecontent)
|
||||||
|
print("Wrote file: " .. filepath)
|
||||||
|
|
||||||
|
local another = vim.fn.input("Do you want to paste another file? (y/n): ")
|
||||||
|
if another:lower() ~= "y" then
|
||||||
|
handler.finish()
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
" Defines the commands for the plugin
|
" Defines the :ChatGPT command
|
||||||
command! ChatGPT lua require('chatgpt_nvim').run_chatgpt_command()
|
command! ChatGPT lua require('chatgpt_nvim').run_chatgpt_command()
|
||||||
command! ChatGPTPaste lua require('chatgpt_nvim.handler').paste_code_from_clipboard()
|
|
||||||
|
|||||||
Reference in New Issue
Block a user