Files
chatgpt.vim/lua/chatgpt_nvim/config.lua

195 lines
6.1 KiB
Lua

local M = {}
local uv = vim.loop
local ok_yaml, lyaml = pcall(require, "lyaml")
local prompts = require("chatgpt_nvim.prompts")
-- Determines the Git root or fallback directory.
local function get_project_root()
local current_file = vim.fn.expand("%:p")
local root_dir
if current_file == "" then
root_dir = vim.fn.getcwd()
else
local file_dir = current_file:match("(.*)/")
if not file_dir then
root_dir = vim.fn.getcwd()
else
local cmd = string.format("cd %s && git rev-parse --show-toplevel 2>/dev/null", vim.fn.shellescape(file_dir))
local git_root = vim.fn.systemlist(cmd)
if vim.v.shell_error == 0 and git_root and #git_root > 0 then
root_dir = git_root[1]
else
root_dir = file_dir
end
end
end
return root_dir
end
-- Attempt to locate either .chatgpt_config.yaml or chatgpt_config.yaml, returning whichever exists first.
local function get_config_path()
local root = get_project_root()
local dot_config = root .. "/.chatgpt_config.yaml"
local non_dot_config = root .. "/chatgpt_config.yaml"
local dot_fd = uv.fs_open(dot_config, "r", 438)
if dot_fd then
uv.fs_close(dot_fd)
return dot_config
end
local non_dot_fd = uv.fs_open(non_dot_config, "r", 438)
if non_dot_fd then
uv.fs_close(non_dot_fd)
return non_dot_config
end
return nil
end
function M.load()
-- Attempt to find either config file, else fallback
local path = get_config_path()
local config = {
initial_prompt = "",
directories = { "." },
default_prompt_blocks = {},
prompt_char_limit = 300000,
project_name = "",
debug = false,
initial_files = {},
include_file_contents = false, -- NEW FLAG: include file contents in prompt if true
preview_changes = false,
interactive_file_selection = false,
partial_acceptance = false,
improved_debug = false,
enable_chunking = false,
enable_step_by_step = true,
-- If auto_lint is true, we only do LSP-based checks.
auto_lint = false,
tool_auto_accept = {
read_file = false,
edit_file = false,
replace_in_file = false,
executeCommand = false,
}
}
-- If no config file found, alert user and return default config
if not path then
config.initial_prompt = "You are a coding assistant who receives a project's context and user instructions..."
vim.notify(
"No config file found (tried .chatgpt_config.yaml, chatgpt_config.yaml). Using defaults.",
vim.log.levels.WARN
)
return config
end
local fd = uv.fs_open(path, "r", 438)
if fd then
local stat = uv.fs_fstat(fd)
local data = uv.fs_read(fd, stat.size, 0)
uv.fs_close(fd)
if data and ok_yaml then
local ok, result = pcall(lyaml.load, data)
if ok and type(result) == "table" then
if type(result.initial_prompt) == "string" then
config.initial_prompt = result.initial_prompt
end
if type(result.directories) == "table" then
config.directories = result.directories
end
if type(result.default_prompt_blocks) == "table" then
config.default_prompt_blocks = result.default_prompt_blocks
end
if type(result.prompt_char_limit) == "number" then
config.prompt_char_limit = result.prompt_char_limit
end
if type(result.project_name) == "string" then
config.project_name = result.project_name
end
if type(result.debug) == "boolean" then
config.debug = result.debug
end
if type(result.initial_files) == "table" then
config.initial_files = result.initial_files
end
if type(result.include_file_contents) == "boolean" then -- LOAD NEW FLAG
config.include_file_contents = result.include_file_contents
end
if type(result.preview_changes) == "boolean" then
config.preview_changes = result.preview_changes
end
if type(result.interactive_file_selection) == "boolean" then
config.interactive_file_selection = result.interactive_file_selection
end
if type(result.partial_acceptance) == "boolean" then
config.partial_acceptance = result.partial_acceptance
end
if type(result.improved_debug) == "boolean" then
config.improved_debug = result.improved_debug
end
if type(result.enable_chunking) == "boolean" then
config.enable_chunking = result.enable_chunking
end
if type(result.enable_step_by_step) == "boolean" then
config.enable_step_by_step = result.enable_step_by_step
end
if type(result.auto_lint) == "boolean" then
config.auto_lint = result.auto_lint
end
if type(result.tool_auto_accept) == "table" then
for k, v in pairs(result.tool_auto_accept) do
if config.tool_auto_accept[k] ~= nil and type(v) == "boolean" then
config.tool_auto_accept[k] = v
end
end
end
end
end
else
config.initial_prompt = "You are a coding assistant who receives a project's context and user instructions..."
end
-- Merge default prompt blocks
if type(config.default_prompt_blocks) == "table" and #config.default_prompt_blocks > 0 then
local merged_prompt = {}
for _, block_name in ipairs(config.default_prompt_blocks) do
if prompts[block_name] then
table.insert(merged_prompt, prompts[block_name])
end
end
if #merged_prompt > 0 then
local combined_blocks = table.concat(merged_prompt, "\n\n")
if config.initial_prompt ~= "" then
config.initial_prompt = config.initial_prompt .. "\n\n" .. combined_blocks
else
config.initial_prompt = combined_blocks
end
end
end
-- Include project name in the final initial prompt, if set
if config.project_name ~= "" then
config.initial_prompt =
"[Project Name: " .. config.project_name .. "]\n\n" .. config.initial_prompt
end
if config.debug then
vim.api.nvim_out_write("[chatgpt_nvim:config] Loaded config from: " .. path .. "\n")
vim.api.nvim_out_write("[chatgpt_nvim:config] Debug logging is enabled.\n")
end
return config
end
return M