183 lines
6.5 KiB
Lua
183 lines
6.5 KiB
Lua
local M = {}
|
||
local uv = vim.loop
|
||
|
||
local ok_yaml, lyaml = pcall(require, "lyaml")
|
||
|
||
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.
|
||
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.
|
||
]],
|
||
["rust-development"] = [[
|
||
You are a coding assistant specialized in Rust development.
|
||
You will receive a project’s context and user instructions related to Rust code.
|
||
Keep your suggestions aligned with Rust best practices and idiomatic Rust.
|
||
]],
|
||
["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 guide them through a workflow:
|
||
1. Analyse which files you need. Ask for file contents in YAML if needed.
|
||
2. Request additional context outside YAML if necessary.
|
||
3. When ready, provide final changes in YAML with:
|
||
- 'project_name'
|
||
- 'files', each having:
|
||
* 'path'
|
||
* 'diff' (for patching an existing file) OR 'content' (for a new file) OR 'delete'
|
||
Important: do not provide entire file content for updates; instead provide a unified diff in 'diff'.
|
||
Only modify or delete files whose contents you have explicitly requested and seen beforehand.
|
||
]],
|
||
["secure-coding"] = [[
|
||
You are a coding assistant specialized in secure software development.
|
||
Always consider security impacts. Use diffs for updates, new content for new files,
|
||
and 'delete: true' for removals.
|
||
]],
|
||
["workflow-prompt"] = [[
|
||
You are a coding assistant focusing on making the Neovim ChatGPT workflow straightforward and user-friendly.
|
||
Remind the user to:
|
||
- List needed files for further context
|
||
- Request additional information outside YAML if needed
|
||
- Provide final changes in YAML with 'project_name' and 'files', using:
|
||
* 'diff' for existing file modifications
|
||
* 'content' for new files
|
||
* 'delete: true' for file deletions
|
||
]]
|
||
}
|
||
|
||
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
|
||
|
||
local function get_config_path()
|
||
local root = get_project_root()
|
||
return root .. "/.chatgpt_config.yaml"
|
||
end
|
||
|
||
function M.load()
|
||
local path = get_config_path()
|
||
local fd = uv.fs_open(path, "r", 438)
|
||
local config = {
|
||
initial_prompt = "",
|
||
directories = { "." },
|
||
default_prompt_blocks = {},
|
||
token_limit = 16384,
|
||
project_name = "",
|
||
debug = false,
|
||
initial_files = {},
|
||
preview_changes = false,
|
||
interactive_file_selection = false,
|
||
partial_acceptance = false,
|
||
improved_debug = false,
|
||
enable_chunking = false,
|
||
enable_step_by_step = true,
|
||
enable_debug_commands = false
|
||
}
|
||
|
||
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.token_limit) == "number" then
|
||
config.token_limit = result.token_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.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.enable_debug_commands) == "boolean" then
|
||
config.enable_debug_commands = result.enable_debug_commands
|
||
end
|
||
end
|
||
end
|
||
else
|
||
config.initial_prompt = "You are a coding assistant who receives a project's context and user instructions..."
|
||
end
|
||
|
||
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 prompt_blocks[block_name] then
|
||
table.insert(merged_prompt, prompt_blocks[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
|
||
|
||
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
|