🤏SimpleGPT is a Vim plugin designed to provide a simple (high transparency based on Jinja) yet flexible way (context-aware based on buffer, visual selection, LSP info, terminal etc.) to customize your LLM/ChatGPT prompts for your tasks (building chat or finishing tasks by replacing them with diff comparison, appending, SEARCH/REPLACE etc.) or building chat on nearly all kinds of LLM APIs.
For a long time, I've been looking for a simple way to chat in VIM with any LLM—just having a conversation, without pulling in my codebase as context (VIM is a tool far beyond code).
SimpleGPT aims to solve this problem.
<LocalLeader>gc
(to trigger chat completion or stop the chat completion stream). You can edit your conversation like a normal buffer and continue chat completion freely.What's more🎁!
Here is a Jinja template example (this shows how you can build rich, context-aware chat experiences):
You are an expert in programming.
{% if p %}
Here are a list of files for reference.
{{p-}}
{% endif %}
We have a file named {{filename}} with content:
````{{filetype}}
{{content}}
````
{%if terminal%}
You encountered error when running or compiling it
```
{{terminal}}
```
{% endif %}
{% if visual %}The error are potentially caused by the following code block(We call it *focused code block*).
```{{filetype}}
{{visual}}
```
Please only return the code to replace the *focused code block*{% else %}
{{f-}}
{% endif %}
{{q}}
🤏SimpleGPT's efforts can be categorized into the following parts:
This allows you to easily build a LLM-based toolbox with 🤏SimpleGPT.
We provide a tools gallery for basic usage, which also serves as examples for further customization.
Tool | Config | Demo |
---|---|---|
Grammar fixing | conf.lua | |
Text Rewriting | conf.lua | |
Code completing | conf.lua | Demo |
Function documentation (Docstring) | conf.lua | |
Variable documentation | conf.lua | |
Code Explanation | conf.lua | |
Bug Fixing | conf.lua | |
Translation with great formatting | conf.lua | Demo |
Dictionary with customized explanation | conf.lua | Demo |
Reading | My Config | |
Terminal with LLM supported | Config | Demo |
Code editing with LSP information | Config | Demo |
Code editing with terminal context | Config | Demo |
Chat
More tools are coming soon.
Our project aims to make customizing your LLM/ChatGPT prompts straightforward by using the yetone/avante.nvim as the backend API, ensuring we don't reinvent the wheel while supporting diverse models.
⚠️Please follow the installation guide of avante.nvim to make sure it works.
You can use :AvanteAsk
to start a chat and verify if it is working.
-- Lazy.nvim
{
"you-n-g/simplegpt.nvim",
dependencies = {
{
"yetone/avante.nvim", -- You should configure your avante.nvim make sure it works.
event = "VeryLazy",
opts = {<your config>},
dependencies = {
"MunifTanjim/nui.nvim",
"nvim-lua/plenary.nvim",
},
},
"you-n-g/jinja-engine.nvim",
"ibhagwan/fzf-lua",
},
config = true,
},
-- or packer.nvim
use({
"you-n-g/simplegpt.nvim",
config = function()
require("simplegpt").setup()
end,
requires = {
{
"yetone/avante.nvim", -- You should configure your avante.nvim make sure it works.
event = "VimEnter",
config = function()
require("avante").setup({<your config>})
end,
requires = {
"MunifTanjim/nui.nvim",
"nvim-lua/plenary.nvim",
},
},
"you-n-g/jinja-engine.nvim",
"ibhagwan/fzf-lua",
},
})
If you want to customize you <LocalLeader>
, please use following code:
vim.g.maplocalleader = "\\" -- change the localleader key to \
More detailed configuration are listed here. You can find my latest and preferred configuration here as an example.
<localleader>st
in a terminal buffer to open the LLM dialog.<c-a>
to add the chosen command to the terminal.<localleader>sl
to use the code editing feature and address LSP warnings or errors. <c-r>
to replace the selected text with the suggested fix.ls
and python <your script>
to gather live feedback from the terminal.<localleader>sF
to use the code editing feature and fix errors detected in the terminal output.<m-r>
to apply search and replace actions to quickly update your code based on the suggestions.I have attempted to summarize the key concepts and manual in one image.
The question is constructed by rendering a template. The 't' register serves as the template, encompassing:
{{content}}
, {{filetype}}
, {{visual}}
, and {{context_line_num}}
.{{a}}
, {{b}}
, and {{c}}
.<localleader>gc
to send current buffer as question to chat or continue chat.<localleader>gc
to stop the chat stream.<localleader>se
) to build according question based on context.Q
to convert the question into a new chat.<localleader>gc
to continue chat.Here is a gif demo that quickly showcases the customization process.
You can specify a custom template path for loading and dumping files by setting the custom_template_path
option in your configuration. If the specified path does not exist, it will be created automatically.
Example configuration:
require("simplegpt").setup({
custom_template_path = "~/my_custom_templates/"
})
When you set a custom_template_path:
Create a Template File: Navigate to your custom template path and create a .json
file.
Define Template Structure: Add your template with placeholders:
{
"t": "I am working on a {{filetype}} file. The content is: {{content}}. Selected lines: {{visual}}. Question: {{q}}."
}
Save: Save the file in custom_template_path
.
Set the 't' Register: In Vim, set the 't' register:
" setting it with command
:let @t = "I am working on a {{filetype}} file. The content is: {{content}}. Selected lines: {{visual}}. Question: {{q}}."
" or use `"ty` to copy the content to the 't' register
Dump the Register: Use the shortcut to dump the 't' register:
:<LocalLeader>gD
You can register custom shortcuts to use templates from the custom template path. Here is an example of how to configure custom shortcuts:
require("simplegpt").setup({
custom_template_path = "~/my_custom_templates/",
keymaps = {
custom_shortcuts = {
["<LocalLeader>sQ"] = {
mode = { "n", "v" },
tpl = "my_custom_template.json",
target = "popup",
opts = { noremap = true, silent = true, desc = "Use custom template" },
},
},
},
})
In this example, pressing <LocalLeader>sQ
in normal or visual mode will load the my_custom_template.json
from the custom template path and send it to the popup target.
The primary concepts that govern the functionality of this plugin are:
Register-based, template-driven question construction: This approach allows for the dynamic creation of questions by leveraging the power of Vim registers. The registers serve as placeholders within the template, which are then replaced with the appropriate content during the question construction process.
Dumping and loading of registers: This feature enables the preservation of register content across different sessions. It's important to note that temporary registers, denoted by {{p-}}
, are exempt from this process and their content is not saved to disk.
Response display targets: This refers to the destination where the response from ChatGPT is displayed. The plugin offers flexibility in choosing the target, allowing for a more tailored user experience.
To illustrate the core template rendering mechanism of SimpleGPT, consider the following example. We have a template in the 't' register:
"I am currently working on a {{filetype}} file. The content of the file is: {{content}}. I have selected the following lines: {{visual}}. My question is: {{q}}."
The register values are:
{{filetype}}
is 'markdown'{{content}}
is 'This is a sample markdown file.'{{visual}}
is 'This is a selected.'{{q}}
is 'How can I improve this line?'The constructed question becomes:
"I am currently working on a markdown file. The content of the file is: This is a sample markdown file. I have selected the following lines: This is a selected line. My question is: How can I improve this line?"
Registers are of two types:
{{content}}
, {{filetype}}
, {{visual}}
, and {{q}}
. They store special values used in the template process. The {{q}}
register allows for an editable question when rendering the whole content.Register | meaning |
---|---|
t | The register for the template. |
others | the variables to render the template |
You can use these variables in your jinja template.
key | meaning |
---|---|
content | Content around the cursor, limited by a configurable length |
full_content | Entire content of the current file |
filetype | Filetype of the current buffer |
visual | Lines selected in visual mode |
context | Context around the cursor, configurable lines up/down |
context_line_num | Like context but additionally shows absolute line numbers and marks the current line with >> for precise location |
all_buf | Content from all loaded buffers with files on disk |
lsp_diag | LSP diagnostics information for the selected lines |
md_context | Directly loading the content in .sgpt.md as the register value. |
filename | The name of the current file |
terminal | The content from the active (visiable) terminal buffer, capturing recent terminal output (if available) |
full_terminal | like terminal, but including all terminal output |
cword | The word under the cursor when the command was invoked |
p | If register p contains a list of file paths (one per line), its value becomes the concatenation of the content from each of those files. While editing the template, open the Files popup and press @ to fuzzy-search files with fzf-lua and append their paths automatically. Files that do not exist will be skipped and are now highlighted inside the popup (using the Comment highlight group) so you can immediately spot and fix stale paths. |
SimpleGPT uses a Jinja-like template engine (jinja-engine.nvim) to power its template system:
Variable Interpolation: Access registers using {{register_name}}
syntax
{
"t": "I am working on a {{filetype}} file. The content is: {{content}}. Selected lines: {{visual}}. Question: {{q}}."
}
Control Structures: Use Jinja-style control flow
{% if visual %}Selected: {{visual}}{% else %}No selection{% endif %}
The template engine provides familiar Jinja-style syntax while being fully integrated with Neovim.
After receiving a response from ChatGPT, you can perform several actions to integrate the output into your workflow:
<C-a>
key) to add the response to your original buffer.<C-r>
key) to substitute the selected text, current line, or entire file with the response.<C-y>
key) to copy the response to the clipboard.<m-r>
key) to apply automated modifications via SEARCH/REPLACE blocks.<m-c>
key) to continue the conversation or refine the response.{"q", "<C-c>", "<esc>"}
: Exit the dialog{"<C-k>"}
: Extract code block closest to cursor{"<C-j>"}
: Cycle to next window{"<C-h>"}
: Cycle to previous window{"<C-s>"}
: Save registers (for template editing only)K
: Show special value for placeholder under cursor (for template editing only)Q
: Send current question or conversation to a buffer for chatting.ChatDialog
(The dialog that can get responses){"<C-a>"}
: Append response to original buffer after selection/current line{"<C-y>"}
: Copy full response to clipboard{"<C-r>"}
: Replace selected text/current line with response{"<m-c>"}
: Instruction Editing:{"<m-r>"}
: Apply search and replace blocks to modify code based on the response[]
: Navigate(prev/next) between responses/answers<LocalLeader>g
(You can change it by setting keymaps.prefix
when you setup the plugin)<LocalLeader>gl
: load registers<LocalLeader>gD
: dump registers<LocalLeader>ge
: edit registers<LocalLeader>gs
: send question to clipboard<LocalLeader>gc
: send question to ChatGPT<LocalLeader>gr
: send to get direct response<LocalLeader>gd
: send to get response with diff<LocalLeader>gR
: toggle the dialog.<LocalLeader>gp
: load current file to reg<LocalLeader>gP
: append current file to reg<LocalLeader>c
: Start chatting in current buffer.<LocalLeader>s
(You can change it by setting keymaps.shortcuts.prefix
when you setup the plugin)<LocalLeader>sr
: (R)ewrite Text in Diff Mode.<LocalLeader>sC
: (C)omplete Code in Popup (with explanations).<LocalLeader>sc
: (C)omplete Code in Diff Mode (no explanation).<LocalLeader>sl
: Fix code using LSP diagnostics.<LocalLeader>sk
: Add documentation for the function.<LocalLeader>sv
: Add documentation for the variable under cursor or selection.<LocalLeader>sg
: (G)rammar Fix.<LocalLeader>sd
: (D)ense for condensing text.<LocalLeader>st
: (T)hread or Continue conversation.<LocalLeader>se
: (E)xplain Code or Text.<LocalLeader>sF
: (F)ix code with error messages.<LocalLeader>sE
: (E)xplain Text with Translation.<LocalLeader>sT
: (T)ranslate text.<LocalLeader>sq
: (Q)uestion with content.<LocalLeader>sf
: Edit Entire (F)ile in Diff Mode.<LocalLeader>s<m-f>
: Send current file for file edit via search/replace blocks.<LocalLeader>sD
: (D)ictionary lookup.An example to change the shortcuts prefix in lazy.nvim:
{
"you-n-g/simplegpt.nvim",
--- ... other configurations
opts = {
keymaps = {
shortcuts = {
prefix = "<m-g>",
},
prefix = "<m-g><m-g>",
},
},
--- ... other configurations
}
Welcome to contribute to this project.
You can test the plugin with minimal config with
vim -u tests/init_configs/lazy.lua -U NONE -N -i NONE
for lazy.nvimvim -u tests/init_configs/packer.lua -U NONE -N -i NONE
ChatCompletion
API (which is the most powerful and frequently used in the future trend).