Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add config.chat_template to be able to customize the chat file banner #117

Closed
wants to merge 12 commits into from
23 changes: 16 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@

<!-- panvimdoc-ignore-end -->

---

> **Note:** This repository is a fork of the original [gp.nvim](https://github.com/Robitx/gp.nvim) plugin. It includes a few small improvements which you can find in the [GitHub compare page](https://github.com/Robitx/gp.nvim/compare/main...argshook:gp.nvim:main).

> If you like this plugin, please share your love on the original repository: [gp.nvim](https://github.com/Robitx/gp.nvim)

---

<br>

**ChatGPT like sessions, Instructable text/code operations, Speech to text and Image generation in your favorite editor.**
Expand Down Expand Up @@ -105,19 +113,20 @@ require("gp").setup()

-- shortcuts might be setup here (see Usage > Shortcuts in Readme)
```

## 2. OpenAI API key

Make sure you have OpenAI API key. [Get one here](https://platform.openai.com/account/api-keys) and use it in the [4. Configuration](#4-configuration). Also consider setting up [usage limits](https://platform.openai.com/account/billing/limits) so you won't get suprised at the end of the month.

The OpenAI API key can be passed to the plugin in multiple ways:

| Method | Example | Security Level |
| ------------------------- | -------------------------------------------------------------- | ------------------- |
| hardcoded string | `openai_api_key: "sk-...",` | Low |
| default env var | set `OPENAI_API_KEY` environment variable in shell config | Medium |
| custom env var | `openai_api_key = os.getenv("CUSTOM_ENV_NAME"),` | Medium |
| read from file | `openai_api_key = { "cat", "path_to_api_key" },` | Medium-High |
| password manager | `openai_api_key = { "bw", "get", "password", "OAI_API_KEY" },` | High |
| Method | Example | Security Level |
| ---------------- | -------------------------------------------------------------- | -------------- |
| hardcoded string | `openai_api_key: "sk-...",` | Low |
| default env var | set `OPENAI_API_KEY` environment variable in shell config | Medium |
| custom env var | `openai_api_key = os.getenv("CUSTOM_ENV_NAME"),` | Medium |
| read from file | `openai_api_key = { "cat", "path_to_api_key" },` | Medium-High |
| password manager | `openai_api_key = { "bw", "get", "password", "OAI_API_KEY" },` | High |

If `openai_api_key` is a table, Gp runs it asynchronously to avoid blocking Neovim (password managers can take a second or two).

Expand Down
14 changes: 14 additions & 0 deletions lua/gp/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,20 @@ local config = {
-- just a static string is legacy and the [{{agent}}] element is added automatically
-- if you really want just a static string, make it a table with one element { "🤖:" }
chat_assistant_prefix = { "🤖:", "[{{agent}}]" },
-- The banner shown at the top of each chat file.
chat_template = [[
# topic: ?

- file: %s
%s
Write your queries after %s. Use `%s` or :%sChatRespond to generate a response.
Response generation can be terminated by using `%s` or :%sChatStop command.
Chats are saved automatically. To delete this chat, use `%s` or :%sChatDelete.
Be cautious of very long chats. Start a fresh chat by using `%s` or :%sChatNew.

---

%s]],
-- chat topic generation prompt
chat_topic_gen_prompt = "Summarize the topic of our conversation above"
.. " in two or three words. Respond only with those words.",
Expand Down
32 changes: 28 additions & 4 deletions lua/gp/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -622,12 +622,26 @@ M.repo_instructions = function()
return table.concat(lines, "\n")
end

local function get_git_root()
local handle = io.popen("git rev-parse --show-toplevel 2>/dev/null")
local result = handle:read("*a"):gsub("\n", "")
handle:close()
return result ~= "" and result or nil
end

local function get_relative_path(full_path, git_root)
return git_root and full_path:sub(#git_root + 2) or full_path
end

M.template_render = function(template, command, selection, filetype, filename)
local git_root = get_git_root()
local relative_filename = get_relative_path(filename, git_root)

local key_value_pairs = {
["{{command}}"] = command,
["{{selection}}"] = selection,
["{{filetype}}"] = filetype,
["{{filename}}"] = filename,
["{{filename}}"] = relative_filename,
}
return _H.template_render(template, key_value_pairs)
end
Expand Down Expand Up @@ -1466,7 +1480,17 @@ M.prep_chat = function(buf, file_name)
-- make last.md a symlink to the last opened chat file
local last = M.config.chat_dir .. "/last.md"
if file_name ~= last then
os.execute("ln -sf " .. file_name .. " " .. last)
local check_command = "if [[ -L " .. last .. " || ! -e " .. last .. " ]]; then echo 'ok'; else echo 'fail'; fi"
local handle = io.popen(check_command)
local result = handle:read("*a")
handle:close()

if result:find("ok") then
os.remove(last)
os.execute("ln -sf " .. file_name .. " " .. last)
else
print("Error: 'last.md' exists and is not a symbolic link.")
end
end
end

Expand Down Expand Up @@ -1677,7 +1701,7 @@ M.new_chat = function(params, model, system_prompt, toggle)
end

local template = string.format(
M.chat_template,
M.config.chat_template or M.chat_template,
string.match(filename, "([^/]+)$"),
model .. system_prompt,
M.config.chat_user_prefix,
Expand Down Expand Up @@ -2274,7 +2298,7 @@ M.cmd.ChatFinder = function()
end, gid)

-- when command buffer is written, execute it
_H.autocmd({ "TextChanged", "TextChangedI", "TextChangedP", "TextChangedT" }, { command_buf }, function()
_H.autocmd({ "TextChanged", "InsertLeave", "TextChangedP", "TextChangedT" }, { command_buf }, function()
vim.api.nvim_win_set_cursor(picker_win, { 1, 0 })
refresh_picker()
end, gid)
Expand Down