Files
chatgpt.vim/lua/chatgpt_nvim/init.lua

127 lines
3.8 KiB
Lua

-- lua/chatgpt_nvim/init.lua
local M = {}
local context = require('chatgpt_nvim.context')
local handler = require('chatgpt_nvim.handler')
local config = require('chatgpt_nvim.config')
local ok_yaml, lyaml = pcall(require, "lyaml")
local function copy_to_clipboard(text)
vim.fn.setreg('+', text)
end
local function parse_response(raw)
if not ok_yaml then
vim.api.nvim_err_writeln("lyaml not available. Install with `luarocks install lyaml`.")
return nil
end
local ok, data = pcall(lyaml.load, raw)
if not ok or not data then
vim.api.nvim_err_writeln("Failed to parse YAML response.")
return nil
end
return data
end
-- A simple token estimation function (approx. 4 chars per token)
local function estimate_tokens(text)
local approx_chars_per_token = 4
local length = #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: ")
if user_input == "" then
print("No input provided.")
return
end
local dirs = conf.directories or {"."}
local project_structure = context.get_project_structure(dirs)
local all_files = context.get_project_files(dirs)
local file_sections = context.get_file_contents(all_files)
local sections = {
conf.initial_prompt .. "\n" .. user_input,
"\n\nProject name: " .. (conf.project_name or "") .. "\n",
"\n\nProject Structure:\n",
project_structure,
"\n\nBelow are the files from the project, each preceded by its filename in backticks and enclosed in triple backticks.\n"
}
table.insert(sections, file_sections)
local prompt = table.concat(sections, "\n")
local token_limit = conf.token_limit or 8000
local token_count = estimate_tokens(prompt)
if token_count > token_limit then
print("Too many files attached. The request exceeds the O1 model limit of " .. token_limit .. " tokens.")
return
end
copy_to_clipboard(prompt)
print("Prompt copied to clipboard! Paste it into the ChatGPT O1 model.")
end
function M.run_chatgpt_paste_command()
print("Reading ChatGPT YAML response from clipboard...")
local conf = config.load()
local raw = handler.get_clipboard_content()
if raw == "" then
vim.api.nvim_err_writeln("Clipboard is empty. Please copy the YAML response from ChatGPT first.")
return
end
local data = parse_response(raw)
if not data or not data.files then
vim.api.nvim_err_writeln("No 'files' field found in the YAML response.")
return
end
if not data.project_name or data.project_name ~= conf.project_name then
vim.api.nvim_err_writeln("Project name mismatch. The provided changes are for project '" ..
(data.project_name or "unknown") .. "' but current project is '" ..
(conf.project_name or "unconfigured") .. "'. Aborting changes.")
return
end
local root = vim.fn.getcwd()
for _, fileinfo in ipairs(data.files) do
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 'content' or 'delete' set to true.")
end
::continue::
end
end
return M