Skip to content

Commit 43c48ef

Browse files
committed
feat: initial support for workspaces
fixes zbirenbaum#375
1 parent 061fd4f commit 43c48ef

File tree

5 files changed

+127
-1
lines changed

5 files changed

+127
-1
lines changed

lua/copilot/client.lua

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,31 @@ local function prepare_client_config(overrides)
186186
["copilot/openURL"] = api.handlers["copilot/openURL"],
187187
}
188188

189+
local workspace = config.get("workspace") --[[@as copilot_config_workspace]]
190+
local workspace_config = {}
191+
192+
if workspace then
193+
if workspace.auto_add_root_dir then
194+
local workspace_folders = workspace.workspace_folders
195+
196+
--- @type workspace_folder
197+
local workspace_folder = {
198+
uri = vim.uri_from_fname(vim.fn.getcwd()),
199+
name = "Root Folder",
200+
}
201+
202+
table.insert(workspace_folders, workspace_folder)
203+
workspace.workspace_folders = workspace_folders
204+
end
205+
end
206+
207+
-- Code fails further down if included empty or nil
208+
if #workspace.workspace_folders > 0 then
209+
workspace_config = {
210+
workspace_folders = workspace.workspace_folders,
211+
}
212+
end
213+
189214
return vim.tbl_deep_extend("force", {
190215
cmd = {
191216
node,
@@ -237,7 +262,7 @@ local function prepare_client_config(overrides)
237262
init_options = {
238263
copilotIntegrationId = "vscode-chat",
239264
},
240-
}, overrides)
265+
}, workspace_config, overrides)
241266
end
242267

243268
function M.setup()
@@ -250,6 +275,7 @@ function M.setup()
250275

251276
is_disabled = false
252277

278+
M.id = nil
253279
vim.api.nvim_create_augroup(M.augroup, { clear = true })
254280

255281
vim.api.nvim_create_autocmd("FileType", {
@@ -274,4 +300,57 @@ function M.teardown()
274300
end
275301
end
276302

303+
function M.add_workspace_folder(folder_path)
304+
if type(folder_path) ~= "string" then
305+
vim.notify("[Copilot] Workspace folder path must be a string", vim.log.levels.ERROR)
306+
return false
307+
end
308+
309+
if vim.fn.isdirectory(folder_path) ~= 1 then
310+
vim.notify("[Copilot] Invalid workspace folder: " .. folder_path, vim.log.levels.ERROR)
311+
return false
312+
end
313+
314+
-- Normalize path
315+
folder_path = vim.fn.fnamemodify(folder_path, ":p")
316+
317+
--- @type workspace_folder
318+
local workspace_folder = {
319+
uri = vim.uri_from_fname(folder_path),
320+
name = folder_path,
321+
}
322+
323+
local workspace = config.get("workspace") --[[@as copilot_config_workspace]]
324+
local workspace_folders = workspace.workspace_folders
325+
326+
local exists = false
327+
for _, existing_folder in ipairs(workspace_folders) do
328+
if existing_folder.uri == workspace_folder.uri then
329+
exists = true
330+
break
331+
end
332+
end
333+
334+
if not exists then
335+
table.insert(workspace_folders, workspace_folder)
336+
workspace.workspace_folders = workspace_folders
337+
config.set("workspace", workspace)
338+
end
339+
340+
local client = M.get()
341+
if client and client.initialized then
342+
client.notify("workspace/didChangeWorkspaceFolders", {
343+
event = {
344+
added = { workspace_folder },
345+
removed = {},
346+
},
347+
})
348+
vim.notify("[Copilot] Added workspace folder: " .. folder_path, vim.log.levels.INFO)
349+
else
350+
vim.notify("[Copilot] Workspace folder added for next session: " .. folder_path, vim.log.levels.INFO)
351+
end
352+
353+
return true
354+
end
355+
277356
return M

lua/copilot/config.lua

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ local default_config = {
1717
ratio = 0.4,
1818
},
1919
},
20+
---@class copilot_config_workspace
21+
workspace = {
22+
---@type workspace_folder[]
23+
workspace_folders = {},
24+
auto_add_root_dir = true,
25+
},
2026
---@class copilot_config_suggestion
2127
suggestion = {
2228
enabled = true,
@@ -82,4 +88,14 @@ function mod.get(key)
8288
return mod.config
8389
end
8490

91+
---@param key string
92+
---@param value any
93+
function mod.set(key, value)
94+
if not mod.config then
95+
error("[Copilot] not initialized")
96+
end
97+
98+
mod.config[key] = value
99+
end
100+
85101
return mod

lua/copilot/init.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ local create_cmds = function ()
2424
vim.deprecate("':CopilotAuth'", "':Copilot auth'", "in future", "copilot.lua")
2525
vim.cmd("Copilot auth")
2626
end, {})
27+
28+
vim.api.nvim_create_user_command("CopilotAddWorkspaceFolder", function(opts)
29+
require("copilot.workspace").add(opts)
30+
end, {
31+
desc = "Add a workspace folder to Copilot",
32+
nargs = "?",
33+
complete = "dir",
34+
})
2735
end
2836

2937
M.setup = function(opts)

lua/copilot/workspace.lua

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
local mod = {}
2+
---@class workspace_folder
3+
---@field uri string The URI of the workspace folder
4+
---@field name string The name of the workspace folder
5+
function mod.add(opts)
6+
local folder = opts.args
7+
if not folder or folder == "" then
8+
folder = vim.fn.getcwd()
9+
end
10+
11+
folder = vim.fn.fnamemodify(folder, ":p")
12+
13+
require("copilot.client").add_workspace_folder(folder)
14+
end
15+
16+
return mod

plugin/copilot.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ local completion_store = {
33
auth = { "signin", "signout" },
44
panel = { "accept", "jump_next", "jump_prev", "open", "refresh" },
55
suggestion = { "accept", "accept_line", "accept_word", "dismiss", "next", "prev", "toggle_auto_trigger" },
6+
workspace = { "add" },
67
}
78

89
vim.api.nvim_create_user_command("Copilot", function(opts)
@@ -42,9 +43,15 @@ vim.api.nvim_create_user_command("Copilot", function(opts)
4243
return
4344
end
4445

46+
local remaining_args = ""
47+
if #params > 2 then
48+
remaining_args = table.concat(params, " ", 3)
49+
end
50+
4551
require("copilot.client").use_client(function()
4652
mod[action_name]({
4753
force = opts.bang,
54+
args = remaining_args,
4855
})
4956
end)
5057
end, {

0 commit comments

Comments
 (0)