Share your v1 config #27
Replies: 5 comments 3 replies
-
ok I finally got it working! it definitley is path based issues for Windows. The following message on Discord pointed me down the right path: Message link: https://discord.com/channels/1200633211236122665/1200633212041449606/1203895226553339944 " python3 plugins
call remote#host#RegisterPlugin('python3', 'C:\\\\Users\\\\zhaog\\\\AppData\\\\Local\\\\nvim-data\\\\lazy\\\\CopilotChat.nvim\\\\rplugin\\\\python3\\\\CopilotChat', [
\ {'sync': v:false, 'name': 'CopilotChat', 'type': 'command', 'opts': {'nargs': '1'}},
\ {'sync': v:false, 'name': 'CopilotChatReset', 'type': 'command', 'opts': {}},
\ {'sync': v:false, 'name': 'CopilotChatVisual', 'type': 'command', 'opts': {'nargs': '1', 'range': ''}},
\ {'sync': v:false, 'name': 'CopilotChatVsplitToggle', 'type': 'command', 'opts': {}},
\ {'sync': v:false, 'name': 'CopilotChatInPlace', 'type': 'command', 'opts': {'nargs': '*', 'range': ''}},
\ {'sync': v:false, 'name': 'CopilotChatAutocmd', 'type': 'command', 'opts': {'nargs': '*'}},
\ {'sync': v:false, 'name': 'CopilotChatMapping', 'type': 'command', 'opts': {'nargs': '*'}},
\ ]) But there are a couple important caveats that were not clear to me at first so I will try to explain:
If you follow these steps then it should work for you on Windows! As an additional note, for some reason I still had to activate / approve copilot api access even though I have the copilot lua plugin already approved. So the first command I ran was CopilotChat help and then authenticated. Then the plugin started to work as expected! |
Beta Was this translation helpful? Give feedback.
-
The latest config for CopilotChat.nvim v1.5, adds those commands:
--- Get all the changes in the git repository
---@param staged? boolean
---@return string
local function get_git_diff(staged)
local cmd = staged and "git diff --staged" or "git diff"
local handle = io.popen(cmd)
if not handle then
return ""
end
local result = handle:read("*a")
handle:close()
return result
end
local prompts = {
-- Code related prompts
Explain = "Please explain how the following code works.",
Review = "Please review the following code and provide suggestions for improvement.",
Tests = "Please explain how the selected code works, then generate unit tests for it.",
Refactor = "Please refactor the following code to improve its clarity and readability.",
FixCode = "Please fix the following code to make it work as intended.",
BetterNamings = "Please provide better names for the following variables and functions.",
Documentation = "Please provide documentation for the following code.",
SwaggerApiDocs = "Please provide documentation for the following API using Swagger.",
SwaggerJsDocs = "Please write JSDoc for the following API using Swagger.",
-- Text related prompts
Summarize = "Please summarize the following text.",
Spelling = "Please correct any grammar and spelling errors in the following text.",
Wording = "Please improve the grammar and wording of the following text.",
Concise = "Please rewrite the following text to make it more concise.",
}
return {
-- Import the copilot plugin
{ import = "lazyvim.plugins.extras.coding.copilot" },
{
"CopilotC-Nvim/CopilotChat.nvim",
dependencies = {
{ "nvim-telescope/telescope.nvim" }, -- Use telescope for help actions
{ "nvim-lua/plenary.nvim" },
},
opts = {
show_help = "yes",
prompts = prompts,
debug = false, -- Set to true to see the response from GitHub Copilot API. The log file will be in ~/.local/state/nvim/CopilotChat.nvim.log.
disable_extra_info = "no", -- Disable extra information (e.g.: system prompt, token count) in the response.
hide_system_prompt = "yes", -- Show user prompts only and hide system prompts.
proxy = "", -- Proxies requests via https or socks
},
build = function()
vim.notify("Please update the remote plugins by running ':UpdateRemotePlugins', then restart Neovim.")
end,
event = "VeryLazy",
keys = {
-- Show help actions with telescope
{
"<leader>cch",
function()
require("CopilotChat.code_actions").show_help_actions()
end,
desc = "CopilotChat - Help actions",
},
-- Show prompts actions with telescope
{
"<leader>ccp",
function()
require("CopilotChat.code_actions").show_prompt_actions()
end,
desc = "CopilotChat - Prompt actions",
},
{
"<leader>ccp",
":lua require('CopilotChat.code_actions').show_prompt_actions(true)<CR>",
mode = "x",
desc = "CopilotChat - Prompt actions",
},
-- Code-related commands
{ "<leader>cce", "<cmd>CopilotChatExplain<cr>", desc = "CopilotChat - Explain code" },
{ "<leader>cct", "<cmd>CopilotChatTests<cr>", desc = "CopilotChat - Generate tests" },
{ "<leader>ccr", "<cmd>CopilotChatReview<cr>", desc = "CopilotChat - Review code" },
{ "<leader>ccR", "<cmd>CopilotChatRefactor<cr>", desc = "CopilotChat - Refactor code" },
{ "<leader>ccn", "<cmd>CopilotChatBetterNamings<cr>", desc = "CopilotChat - Better Naming" },
-- Chat with Copilot in visual mode
{
"<leader>ccv",
":CopilotChatVisual",
mode = "x",
desc = "CopilotChat - Open in vertical split",
},
{
"<leader>ccx",
":CopilotChatInPlace<cr>",
mode = "x",
desc = "CopilotChat - Run in-place code",
},
-- Custom input for CopilotChat
{
"<leader>cci",
function()
local input = vim.fn.input("Ask Copilot: ")
if input ~= "" then
vim.cmd("CopilotChat " .. input)
end
end,
desc = "CopilotChat - Ask input",
},
-- Generate commit message based on the git diff
{
"<leader>ccm",
function()
local diff = get_git_diff()
if diff ~= "" then
vim.fn.setreg('"', diff)
vim.cmd("CopilotChat Write commit message for the change with commitizen convention.")
end
end,
desc = "CopilotChat - Generate commit message for all changes",
},
{
"<leader>ccM",
function()
local diff = get_git_diff(true)
if diff ~= "" then
vim.fn.setreg('"', diff)
vim.cmd("CopilotChat Write commit message for the change with commitizen convention.")
end
end,
desc = "CopilotChat - Generate commit message for staged changes",
},
-- Quick chat with Copilot
{
"<leader>ccq",
function()
local input = vim.fn.input("Quick Chat: ")
if input ~= "" then
-- Copy all the lines to the unnamed register
vim.cmd('normal! ggVG"*y')
vim.cmd("CopilotChat " .. input)
end
end,
desc = "CopilotChat - Quick chat",
},
-- Debug
{ "<leader>ccd", "<cmd>CopilotChatDebugInfo<cr>", desc = "CopilotChat - Debug Info" },
-- Fix the issue with the diagnostic
{ "<leader>ccf", "<cmd>CopilotChatFixDiagnostic<cr>", desc = "CopilotChat - Fix Diagnostic" },
-- Clear buffer and chat history
{ "<leader>ccl", "<cmd>CopilotChatReset<cr>", desc = "CopilotChat - Clear buffer and chat history" },
-- Toggle Copilot Chat Vsplit
{ "<leader>ccv", "<cmd>CopilotChatVsplitToggle<cr>", desc = "CopilotChat - Toggle Vsplit" },
},
},
} |
Beta Was this translation helpful? Give feedback.
-
Here's my packer setup (crude packer port). I need to spend a bit more time w/ the plugin to see what it can really do. Corporate laptop is running ubuntu 20, so you'll have to install your own python 3.10+.
Original (copilot.py:127) response = self.session.post(
url, headers=self._headers(), json=data, stream=True
) Turn off verification(copilot.py:127)
use {
'CopilotC-Nvim/CopilotChat.nvim',
config = function()
local copilot_chat = require("CopilotChat")
copilot_chat.setup({
debug = true,
show_help = "yes",
prompts = {
Explain = "Explain how it works by English language.",
Review = "Review the following code and provide concise suggestions.",
Tests = "Briefly explain how the selected code works, then generate unit tests.",
Refactor = "Refactor the code to improve clarity and readability.",
},
proxy = "******",
build = function()
vim.notify(
"Please update the remote plugins by running ':UpdateRemotePlugins', then restart Neovim.")
end,
event = "VeryLazy",
dependencies = {
{ "nvim-telescope/telescope.nvim" }, -- Use telescope for help actions
{ "nvim-lua/plenary.nvim" }
}
})
end
}
vim.keymap.set("n", "<leader>cc", ':CopilotChat ', { remap=false })
vim.keymap.set("x", "<leader>cc", ':CopilotChatVisual ', { remap=false })
vim.keymap.set("n", "<leader>ccb", ':CopilotChatBuffer ', { remap=false })
vim.keymap.set("x", "<leader>ccx", ':CopilotChatInPlace<CR>', { remap=false })
-- telescope
local ccca = require("CopilotChat.code_actions")
vim.keymap.set("n", "<leader>cch", function() ccca.show_help_actions() end, { remap=false })
vim.keymap.set("n", "<leader>ccp", function() ccca.show_prompt_actions() end, { remap=false })
vim.keymap.set("x", "<leader>ccp", function() ccca.show_prompt_actions(true) end, { remap=false }) |
Beta Was this translation helpful? Give feedback.
-
I follow @jellydn config, Here is code: local select = require("CopilotChat.select")
local prompts = {
Explain = { prompt = "Explain how the code works." },
FixError = { prompt = "please explain the errors in the text above and provide a solution." },
Suggestion = { prompt = "Please review the code above and provide suggestions for improvement." },
Refactor = { prompt = "Please refactor the following code to improve its clarity and readability." },
Tests = { prompt = "Briefly explain how the selected code works and then generate a unit test." },
Annotations = { prompt = "Add comments to the above code" },
Commit = {
prompt = 'Write commit message for the change with commitizen convention. Make sure the title has maximum 50 characters and message is wrapped at 72 characters. Wrap the whole message in code block with language gitcommit.',
selection = select.gitdiff,
},
CommitStaged = {
prompt = 'Write commit message for the change with commitizen convention. Make sure the title has maximum 50 characters and message is wrapped at 72 characters. Wrap the whole message in code block with language gitcommit.',
selection = function(source)
return select.gitdiff(source, true)
end,
},
}
local Chat_cmd = "CopilotChat"
local options = {}
for key, value in pairs(prompts) do
table.insert(options, key)
end
local pickers = require "telescope.pickers"
local finders = require "telescope.finders"
local conf = require("telescope.config").values
local actions = require "telescope.actions"
local action_state = require "telescope.actions.state"
local Telescope_CopilotActions = function(opts)
opts = opts or {}
pickers.new(opts, {
prompt_title = "Select Copilot prompt",
finder = finders.new_table {
results = options
},
sorter = conf.generic_sorter(opts),
attach_mappings = function(prompt_bufnr, map)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
local choice = selection[1]
if choice ~= nil then
local msg = ""
-- Find the item message base on the choice
for item, body in pairs(prompts) do
if item == choice then
msg = body.prompt
break
end
end
local get_type = vim.api.nvim_buf_get_option(0, 'filetype')
local Ask_msg = Chat_cmd .. " " .. "This is a ".. get_type .. " code, ".. msg
-- vim.print(Ask_msg)
require("CopilotChat").ask(Ask_msg)
end
end)
return true
end,
}):find()
end
vim.api.nvim_create_user_command("CopilotActions",
function() Telescope_CopilotActions(require("telescope.themes").get_dropdown{}) end,
{ nargs = "*", range = true }
) |
Beta Was this translation helpful? Give feedback.
-
Configuration ExplanationThis is my customized configuration for Key Features1. Modularized Prompts
2. Git Commit Message Optimization
3. ReviewClear Command
My Configlocal context = require('CopilotChat.context')
local select = require('CopilotChat.select')
local buffer = require('CopilotChat.select').buffer
local utils = require('CopilotChat.utils')
select.diagnostics = function(source)
local bufnr = source.bufnr
local winnr = source.winnr
local select_buffer = buffer(source)
if not select_buffer then
return nil
end
local cursor = vim.api.nvim_win_get_cursor(winnr)
local line_diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr, cursor[1] - 1)
if #line_diagnostics == 0 then
return nil
end
local diagnostics = {}
for _, diagnostic in ipairs(line_diagnostics) do
table.insert(diagnostics, diagnostic.message)
end
local result = table.concat(diagnostics, '. ')
result = result:gsub('^%s*(.-)%s*$', '%1'):gsub('\n', ' ')
local file_name = vim.api.nvim_buf_get_name(bufnr)
local out = {
content = file_name .. ':' .. cursor[1] .. '. ' .. result,
filename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ':p:.'),
filetype = vim.bo[bufnr].filetype,
start_line = cursor[1],
end_line = cursor[1],
bufnr = bufnr,
}
return out
end
select.gitdiff = function(source, staged)
local select_buffer = buffer(source)
if not select_buffer then
return nil
end
local file_path = vim.api.nvim_buf_get_name(source.bufnr)
local file_dir = vim.fn.fnamemodify(file_path, ':h')
-- check file dir is exist, or use current dir instead
if vim.fn.isdirectory(file_dir) == 0 then
file_dir = vim.fn.getcwd()
end
-- NOTE: Fix vulnerability #417 in CopilotC-Nvim/CopilotChat.nvim
file_dir = file_dir:gsub('.git$', '')
local cmd_diff = 'git -C ' ..
file_dir .. ' diff --no-color --no-ext-diff' .. (staged and ' --staged' or '') .. ' 2>/dev/null'
local cmd_diff_stat = 'git -C ' ..
file_dir .. ' diff --stat --no-color --no-ext-diff' .. (staged and ' --staged' or '') .. ' 2>/dev/null'
local handle = io.popen(cmd_diff)
if not handle then
return nil
end
local result = handle:read('*a')
handle:close()
-- jugde if the diff is too large (> 30000 characters) to handle, use diff --stat to instead
if #result > 30000 then
handle = io.popen(cmd_diff_stat)
if not handle then
return nil
end
result = handle:read('*a')
handle:close()
end
if not result or result == '' then
return nil
end
return {
content = result,
filename = 'git_diff_' .. (staged and 'staged' or 'unstaged'),
filetype = 'diff',
}
end
local function read_copilot_prompt(file)
-- Get the current Neovim configuration directory
local config_dir = vim.fn.stdpath('config')
-- Directory containing the .md files
local prompt_directory = config_dir .. '/docs/CopilotChatPrompts'
local prompt_file = prompt_directory .. '/' .. file
local f = io.open(prompt_file, 'r')
local prompts = ""
if f then
local content = f:read('*all')
prompts = content
f:close()
else
prompts = ""
end
return prompts
end
require("CopilotChat").setup {
debug = false, -- Enable debug logging (same as 'log_level = 'debug')
log_level = 'info', -- Log level to use, 'trace', 'debug', 'info', 'warn', 'error', 'fatal'
proxy = nil, -- [protocol://]host[:port] Use this proxy
allow_insecure = false, -- Allow insecure server connections
-- system_prompt = require("CopilotChat").prompts().COPILOT_INSTRUCTIONS, -- System prompt to use (can be specified manually in prompt via /).
model = 'gpt-4o', -- Default model to use, see ':CopilotChatModels' for available models (can be specified manually in prompt via $).
agent = 'copilot', -- Default agent to use, see ':CopilotChatAgents' for available agents (can be specified manually in prompt via @).
context = nil, -- Default context to use (can be specified manually in prompt via #).
temperature = 0.1, -- GPT result temperature
question_header = '## User ', -- Header to use for user questions
answer_header = '## Copilot ', -- Header to use for AI answers
error_header = '> [!ERROR] Error', -- Header to use for errors (default is '## Error ')
separator = '───', -- Separator to use in chat
chat_autocomplete = true, -- Enable chat autocompletion (when disabled, requires manual `mappings.complete` trigger)
show_folds = true, -- Shows folds for sections in chat
show_help = true, -- Shows help message as virtual lines when waiting for user input
auto_follow_cursor = true, -- Auto-follow cursor in chat
auto_insert_mode = false, -- Automatically enter insert mode when opening window and on new prompt
insert_at_end = false, -- Move cursor to end of buffer when inserting text
clear_chat_on_new_prompt = false, -- Clears chat on every new prompt
highlight_selection = true, -- Highlight selection in the source buffer when in the chat window
highlight_headers = true, -- Highlight headers in chat, disable if using markdown renderers (like render-markdown.nvim)
history_path = vim.fn.stdpath('data') .. '/copilotchat_history', -- Default path to stored history
callback = nil, -- Callback to use when ask response is received
no_chat = false, -- Do not write to chat buffer and use chat history (useful for using callback for custom processing)
-- default selection
selection = function(source)
return select.visual(source) or select.buffer(source)
end,
prompts = {
Explain = '> /COPILOT_EXPLAIN\n\n' .. read_copilot_prompt('Explain.md'),
Ask = '> /COPILOT_EXPLAIN\n\n' .. read_copilot_prompt('Ask.md'),
Review = {
prompt = '> /COPILOT_REVIEW\n\n' .. read_copilot_prompt('Review.md'),
callback = function(response, source)
local diagnostics = {}
for line in response:gmatch('[^\r\n]+') do
if line:find('^line=') then
local start_line = nil
local end_line = nil
local message = nil
local single_match, message_match = line:match('^line=(%d+): (.*)$')
if not single_match then
local start_match, end_match, m_message_match = line:match('^line=(%d+)-(%d+): (.*)$')
if start_match and end_match then
start_line = tonumber(start_match)
end_line = tonumber(end_match)
message = m_message_match
end
else
start_line = tonumber(single_match)
end_line = start_line
message = message_match
end
if start_line and end_line then
table.insert(diagnostics, {
lnum = start_line - 1,
end_lnum = end_line - 1,
col = 0,
message = message,
severity = vim.diagnostic.severity.WARN,
source = 'Copilot Review',
})
end
end
end
vim.diagnostic.set(
vim.api.nvim_create_namespace('copilot_diagnostics'),
source.bufnr,
diagnostics
)
end,
},
ReviewClear = {
prompt = '> /COPILOT_REVIEW\n\n' .. read_copilot_prompt('ReviewClear.md'),
callback = function(response, source)
local ns = vim.api.nvim_create_namespace('copilot_review')
local diagnostics = {}
for line in response:gmatch('[^\r\n]+') do
if line:find('^line=') then
local start_line = nil
local end_line = nil
local message = nil
local single_match, message_match = line:match('^line=(%d+): (.*)$')
if not single_match then
local start_match, end_match, m_message_match = line:match('^line=(%d+)-(%d+): (.*)$')
if start_match and end_match then
start_line = tonumber(start_match)
end_line = tonumber(end_match)
message = m_message_match
end
else
start_line = tonumber(single_match)
end_line = start_line
message = message_match
end
if start_line and end_line then
table.insert(diagnostics, {
lnum = start_line - 1,
end_lnum = end_line - 1,
col = 0,
message = message,
severity = vim.diagnostic.severity.WARN,
source = 'Copilot Review',
})
end
end
end
vim.diagnostic.set(ns, source.bufnr, diagnostics)
end
},
Fix = '> /COPILOT_GENERATE\n\n' .. read_copilot_prompt('Fix.md'),
Optimize = '> /COPILOT_GENERATE\n\n' .. read_copilot_prompt('Optimize.md'),
OneLineComment = '> /COPILOT_GENERATE\n\n' .. read_copilot_prompt('OneLineComment.md'),
OneParagraphComment = '> /COPILOT_GENERATE\n\n' .. read_copilot_prompt('OneParagraphComment.md'),
Docs = '> /COPILOT_GENERATE\n\n' .. read_copilot_prompt('Docs.md'),
Tests = '> /COPILOT_GENERATE\n\n' .. read_copilot_prompt('Tests.md'),
CodeGraph = '> /COPILOT_EXPLAIN\n\n' .. read_copilot_prompt('CodeGraph.md'),
FixDiagnostic = {
prompt = read_copilot_prompt('FixDiagnostic.md'),
selection = select.diagnostics,
},
-- Commit = {
-- prompt = '> #git:staged\n\nWrite commit message for the change with commitizen convention. Make sure the title has maximum 50 characters and message is wrapped at 72 characters. Wrap the whole message in code block with language gitcommit.',
-- },
Commit = {
prompt = read_copilot_prompt('Commit.md'),
selection = select.gitdiff,
},
CommitStaged = {
prompt = read_copilot_prompt('CommitStaged.md'),
selection = function(source)
return select.gitdiff(source, true)
end,
},
},
window = {
layout = 'vertical', -- 'vertical', 'horizontal', 'float', 'replace'
width = 0.5, -- fractional width of parent, or absolute width in columns when > 1
height = 0.5, -- fractional height of parent, or absolute height in rows when > 1
-- Options below only apply to floating windows
relative = 'editor', -- 'editor', 'win', 'cursor', 'mouse'
border = 'single', -- 'none', single', 'double', 'rounded', 'solid', 'shadow'
row = nil, -- row position of the window, default is centered
col = nil, -- column position of the window, default is centered
title = 'Copilot Chat', -- title of chat window
footer = nil, -- footer of chat window
zindex = 1, -- determines if window is on top or below other floating windows
},
-- default mappings
mappings = {
complete = {
insert = '<Tab>',
},
close = {
normal = 'q',
insert = '<C-c>'
},
reset = {
normal = '<C-l>',
insert = '<C-l>'
},
submit_prompt = {
normal = '<CR>',
insert = '<C-s>'
},
toggle_sticky = {
detail = 'Makes line under cursor sticky or deletes sticky line.',
normal = 'gr',
},
accept_diff = {
normal = '<C-y>',
insert = '<C-y>'
},
jump_to_diff = {
normal = 'gD',
},
quickfix_diffs = {
normal = 'gq',
},
yank_diff = {
normal = 'gy',
register = '"',
},
show_diff = {
normal = 'gd'
},
show_system_prompt = {
normal = 'gp'
},
show_user_selection = {
normal = 'gs'
},
},
} |
Beta Was this translation helpful? Give feedback.
-
Here is my config with LazyVim on mac.
Let's share your working config, especially for Windows users 👍
Beta Was this translation helpful? Give feedback.
All reactions