Skip to content

Commit e1fb24a

Browse files
authored
feat: add command :Copilot (zbirenbaum#59)
* feat(client): add functions to attach/detach copilot * feat: add copilot.command module * feat: add command :Copilot * feat: deprecate :CopilotAuth and :CopilotPanel
1 parent 29a045a commit e1fb24a

File tree

6 files changed

+215
-12
lines changed

6 files changed

+215
-12
lines changed

lua/copilot/auth.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ function M.setup(client)
101101
initiate_setup()
102102
end
103103

104+
function M.signin()
105+
local client = u.get_copilot_client()
106+
if not client then
107+
return
108+
end
109+
110+
M.setup(client)
111+
end
112+
104113
function M.signout()
105114
local client = u.get_copilot_client()
106115
if not client then

lua/copilot/client.lua

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,36 @@ local function is_ft_disabled(ft)
4848
return false
4949
end
5050

51-
M.buf_attach_copilot = function()
52-
if is_ft_disabled(vim.bo.filetype) then
53-
return
54-
end
51+
---@param force? boolean
52+
function M.buf_attach(client, force)
53+
if not force then
54+
if is_ft_disabled(vim.bo.filetype) then
55+
return
56+
end
5557

56-
if not vim.bo.buflisted or not vim.bo.buftype == "" then return end
57-
-- The filter param to get_active_clients() can be used on Neovim 0.8 and later.
58-
for _, client in pairs(vim.lsp.get_active_clients()) do
59-
if client.name == "copilot" and not vim.lsp.buf_is_attached(0, client.id) then
60-
vim.lsp.buf_attach_client(0, client.id)
61-
client.completion_function = M.params.extensions
58+
if not vim.bo.buflisted or not vim.bo.buftype == "" then
59+
return
6260
end
6361
end
62+
63+
client = client or util.get_copilot_client()
64+
if client and not util.is_attached(client) then
65+
vim.lsp.buf_attach_client(0, client.id)
66+
67+
---@todo unknown property, remove this
68+
client.completion_function = M.params.extensions
69+
end
70+
end
71+
72+
function M.buf_detach(client)
73+
client = client or util.get_copilot_client()
74+
if client and util.is_attached(client) then
75+
vim.lsp.buf_detach_client(0, client.id)
76+
end
77+
end
78+
79+
M.buf_attach_copilot = function()
80+
M.buf_attach()
6481
end
6582

6683
M.merge_server_opts = function (params)

lua/copilot/command.lua

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
local a = require("copilot.api")
2+
local c = require("copilot.client")
3+
local u = require("copilot.util")
4+
5+
local mod = {}
6+
7+
function mod.version()
8+
local info = u.get_editor_info()
9+
10+
local lines = {
11+
info.editorInfo.name .. " " .. info.editorInfo.version,
12+
info.editorPluginInfo.name .. " " .. info.editorPluginInfo.version,
13+
"copilot.lua" .. " " .. u.get_copilot_lua_version(),
14+
}
15+
16+
local client = u.get_copilot_client()
17+
18+
coroutine.wrap(function()
19+
if client then
20+
local _, data = a.get_version(client)
21+
lines[#lines + 1] = "copilot/dist/agent.js" .. " " .. data.version
22+
else
23+
lines[#lines + 1] = "copilot/dist/agent.js" .. " " .. "not running"
24+
end
25+
26+
vim.api.nvim_echo(
27+
vim.tbl_map(function(line)
28+
return { line .. "\n" }
29+
end, lines),
30+
true,
31+
{}
32+
)
33+
end)()
34+
end
35+
36+
function mod.status()
37+
local function on_output(err)
38+
print("[Copilot] " .. err)
39+
end
40+
41+
local client = u.get_copilot_client()
42+
if not client then
43+
on_output("Not running")
44+
return
45+
end
46+
47+
coroutine.wrap(function()
48+
---@todo check startup error
49+
50+
local cserr, status = a.check_status(client)
51+
if cserr then
52+
on_output(cserr)
53+
return
54+
end
55+
56+
---@todo check enabled status
57+
58+
if not status.user then
59+
on_output("Not authenticated. Run ':Copilot auth'")
60+
return
61+
end
62+
63+
if string.lower(a.status.data.status) == "error" then
64+
on_output(a.status.data.message)
65+
return
66+
end
67+
68+
on_output("Enabled and online")
69+
end)()
70+
end
71+
72+
---@param opts? { force?: boolean }
73+
function mod.toggle(opts)
74+
opts = opts or {}
75+
print(vim.inspect(opts))
76+
77+
local client = u.get_copilot_client()
78+
if not client then
79+
return
80+
end
81+
82+
if u.is_attached(client) then
83+
c.buf_detach(client)
84+
else
85+
c.buf_attach(client, opts.force)
86+
end
87+
end
88+
89+
return mod

lua/copilot/init.lua

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,13 @@ local create_cmds = function (_)
4848
end, {})
4949

5050
vim.api.nvim_create_user_command("CopilotPanel", function ()
51-
require("copilot.panel").open()
51+
vim.deprecate("':CopilotPanel'", "':Copilot panel'", "in future", "copilot.lua")
52+
vim.cmd("Copilot panel")
5253
end, {})
5354

5455
vim.api.nvim_create_user_command("CopilotAuth", function()
55-
require("copilot.util").auth()
56+
vim.deprecate("':CopilotAuth'", "':Copilot auth'", "in future", "copilot.lua")
57+
vim.cmd("Copilot auth")
5658
end, {})
5759
end
5860

lua/copilot/util.lua

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ function M.get_editor_info()
2121
return info
2222
end
2323

24+
local copilot_lua_version = nil
25+
function M.get_copilot_lua_version()
26+
if not copilot_lua_version then
27+
local plugin_version_ok, plugin_version = pcall(function()
28+
return vim.fn.systemlist("git rev-parse HEAD")[1]
29+
end)
30+
copilot_lua_version = plugin_version_ok and plugin_version or "dev"
31+
end
32+
return copilot_lua_version
33+
end
34+
2435
-- keep for debugging reasons
2536
local get_capabilities = function ()
2637
return {
@@ -46,6 +57,11 @@ M.get_copilot_client = function()
4657
end
4758
end
4859

60+
function M.is_attached(client)
61+
client = client or M.get_copilot_client()
62+
return client and vim.lsp.buf_is_attached(0, client.id) or false
63+
end
64+
4965
local eol_by_fileformat = {
5066
unix = "\n",
5167
dos = "\r\n",

plugin/copilot.lua

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
local completion_store = {
2+
[""] = { "auth", "panel", "suggestion", "status", "toggle", "version" },
3+
auth = { "signin", "signout" },
4+
panel = { "accept", "jump_next", "jump_prev", "open", "refresh" },
5+
suggestion = { "accept", "dismiss", "next", "prev", "toggle_auto_trigger" },
6+
}
7+
8+
vim.api.nvim_create_user_command("Copilot", function(opts)
9+
local params = vim.split(opts.args, "%s+", { trimempty = true })
10+
11+
local mod_name, action_name = params[1], params[2]
12+
13+
local u = require("copilot.util")
14+
15+
local ok, mod = pcall(require, "copilot." .. mod_name)
16+
if not ok then
17+
action_name = mod_name
18+
mod_name = "command"
19+
mod = require("copilot.command")
20+
end
21+
22+
if not action_name then
23+
if mod_name == "auth" then
24+
action_name = "signin"
25+
elseif mod_name == "panel" then
26+
action_name = "open"
27+
elseif mod_name == "suggestion" then
28+
action_name = "toggle_auto_trigger"
29+
end
30+
end
31+
32+
if not mod[action_name] then
33+
print("[Copilot] Unknown params: " .. opts.args)
34+
return
35+
end
36+
37+
if not u.get_copilot_client() then
38+
print("[Copilot] Not running")
39+
return
40+
end
41+
42+
mod[action_name]({
43+
force = opts.bang,
44+
})
45+
end, {
46+
bang = true,
47+
nargs = "?",
48+
complete = function(_, cmd_line)
49+
local has_space = string.match(cmd_line, "%s$")
50+
local params = vim.split(cmd_line, "%s+", { trimempty = true })
51+
52+
if #params == 1 then
53+
return completion_store[""]
54+
elseif #params == 2 and not has_space then
55+
return vim.tbl_filter(function(cmd)
56+
return not not string.find(cmd, "^" .. params[2])
57+
end, completion_store[""])
58+
end
59+
60+
if #params >= 2 and completion_store[params[2]] then
61+
if #params == 2 then
62+
return completion_store[params[2]]
63+
elseif #params == 3 and not has_space then
64+
return vim.tbl_filter(function(cmd)
65+
return not not string.find(cmd, "^" .. params[3])
66+
end, completion_store[params[2]])
67+
end
68+
end
69+
end,
70+
})

0 commit comments

Comments
 (0)