From 3b0296358508da1eb258c8716df163dd04fa6449 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 25 Sep 2025 10:31:16 +0200 Subject: [PATCH] feat(copilot): added `copilot-native` extra to setup native inline completions in Neovim --- .../plugins/extras/ai/copilot-native.lua | 49 +++++++++++++++++++ lua/lazyvim/util/lualine.lua | 36 ++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 lua/lazyvim/plugins/extras/ai/copilot-native.lua diff --git a/lua/lazyvim/plugins/extras/ai/copilot-native.lua b/lua/lazyvim/plugins/extras/ai/copilot-native.lua new file mode 100644 index 00000000..8bcb9bfe --- /dev/null +++ b/lua/lazyvim/plugins/extras/ai/copilot-native.lua @@ -0,0 +1,49 @@ +---@diagnostic disable: missing-fields +if lazyvim_docs then + -- Native inline completions don't support being shown as regular completions + vim.g.ai_cmp = false +end + +if LazyVim.has_extra("ai.copilot-native") then + if not vim.lsp.inline_completion then + LazyVim.error("You need Neovim >= 0.12 to use the `ai.copilot-native` extra.") + return {} + end + if LazyVim.has_extra("ai.copilot") then + LazyVim.error("Please disable the `ai.copilot` extra if you want to use `ai.copilot-native`") + return {} + end +end + +vim.g.ai_cmp = false + +return { + desc = "Native Copilot LSP integration. Requires Neovim >= 0.12", + -- copilot-language-server + { + "neovim/nvim-lspconfig", + opts = { + servers = { + copilot = {}, + }, + setup = { + copilot = function(_, opts) + vim.lsp.inline_completion.enable() + LazyVim.cmp.actions.ai_accept = function() + return vim.lsp.inline_completion.get() + end + end, + }, + }, + }, + + -- lualine + { + "nvim-lualine/lualine.nvim", + optional = true, + event = "VeryLazy", + opts = function(_, opts) + table.insert(opts.sections.lualine_x, 2, LazyVim.lualine.lsp("copilot")) + end, + }, +} diff --git a/lua/lazyvim/util/lualine.lua b/lua/lazyvim/util/lualine.lua index a6aa24f3..af4b55f7 100644 --- a/lua/lazyvim/util/lualine.lua +++ b/lua/lazyvim/util/lualine.lua @@ -22,6 +22,42 @@ function M.status(icon, status) } end +--- Status indicator for LSP server activity +---@param server string +---@param opts? { methods?: string[], icon?: string } +function M.lsp(server, opts) + opts = opts or {} + local methods = opts.methods or { "textDocument/completion", "textDocument/inlineCompletion" } + local pending = {} ---@type table + vim.api.nvim_create_autocmd("LspRequest", { + group = vim.api.nvim_create_augroup("lazyvim.lualine.lsp." .. server, { clear = true }), + callback = function(args) + ---@class LspRequestData + ---@field client_id number + ---@field request { bufnr: number, method: string, type: "pending" | "cancel" | "complete" | string } + ---@field request_id number + local data = args.data + local client = vim.lsp.get_client_by_id(data.client_id) + if client and client.name == server and vim.tbl_contains(methods, data.request.method) then + pending[data.request_id] = data.request.type == "pending" or nil + end + end, + }) + return { + function() + return opts.icon + or LazyVim.config.icons.kinds[server:sub(1, 1):upper() .. server:sub(2)] + or LazyVim.config.icons.diagnostics.Hint + end, + cond = function() + return #vim.lsp.get_clients({ name = server, bufnr = 0 }) > 0 + end, + color = function() + return { fg = Snacks.util.color(vim.tbl_isempty(pending) and "Special" or "DiagnosticWarn") } + end, + } +end + ---@param name string ---@param icon? string function M.cmp_source(name, icon)