{ config, lib, ... }: let inherit (builtins) toJSON; inherit (lib.modules) mkIf; inherit (lib.strings) optionalString; cfg = config.vim.assistant.copilot; wrapPanelBinding = luaFunction: key: '' function() local s, _ = pcall(${luaFunction}) if not s then local termcode = vim.api.nvim_replace_termcodes(${toJSON key}, true, false, true) vim.fn.feedkeys(termcode, 'n') end end ''; mkLuaKeymap = mode: key: action: desc: opts: opts // { inherit mode key action desc; lua = true; }; in { config = mkIf cfg.enable { vim = { lazy.plugins = { copilot-lua = { package = "copilot-lua"; setupModule = "copilot"; inherit (cfg) setupOpts; after = mkIf cfg.cmp.enable "require('copilot_cmp').setup()"; cmd = ["Copilot" "CopilotAuth" "CopilotDetach" "CopilotPanel" "CopilotStop"]; keys = [ (mkLuaKeymap ["n"] cfg.mappings.panel.accept (wrapPanelBinding ''require("copilot.panel").accept'' cfg.mappings.panel.accept) "[copilot] Accept suggestion" {}) (mkLuaKeymap ["n"] cfg.mappings.panel.jumpNext (wrapPanelBinding "require(\"copilot.panel\").jump_next" cfg.mappings.panel.jumpNext) "[copilot] Next panel suggestion" {}) (mkLuaKeymap ["n"] cfg.mappings.panel.jumpPrev (wrapPanelBinding "require(\"copilot.panel\").jump_prev" cfg.mappings.panel.jumpPrev) "[copilot] Previous panel suggestion" {}) (mkLuaKeymap ["n"] cfg.mappings.panel.refresh (wrapPanelBinding "require(\"copilot.panel\").refresh" cfg.mappings.panel.refresh) "[copilot] Refresh suggestion" {}) (mkLuaKeymap ["n"] cfg.mappings.panel.open (wrapPanelBinding '' function() require("copilot.panel").open({ position = "${cfg.setupOpts.panel.layout.position}", ratio = ${toString cfg.setupOpts.panel.layout.ratio}, }) end '' cfg.mappings.panel.open) "[copilot] Open Panel" {}) (mkLuaKeymap ["i"] cfg.mappings.suggestion.accept "function() require('copilot.suggestion').accept() end" "[copilot] Accept suggestion" {}) (mkLuaKeymap ["i"] cfg.mappings.suggestion.acceptLine "function() require('copilot.suggestion').accept_line() end" "[copilot] Accept suggestion (line)" {}) (mkLuaKeymap ["i"] cfg.mappings.suggestion.acceptWord "function() require('copilot.suggestion').accept_word() end" "[copilot] Accept suggestion (word)" {}) (mkLuaKeymap ["i"] cfg.mappings.suggestion.dismiss "function() require('copilot.suggestion').dismiss() end" "[copilot] dismiss suggestion" {}) (mkLuaKeymap ["i"] cfg.mappings.suggestion.next "function() require('copilot.suggestion').next() end" "[copilot] next suggestion" {}) (mkLuaKeymap ["i"] cfg.mappings.suggestion.prev "function() require('copilot.suggestion').prev() end" "[copilot] previous suggestion" {}) ]; }; }; autocomplete.nvim-cmp = { sources = {copilot = "[Copilot]";}; sourcePlugins = ["copilot-cmp"]; }; # Disable plugin handled keymaps. # Setting it here so that it doesn't show up in user docs assistant.copilot.setupOpts = { panel.keymap = { jump_prev = lib.mkDefault false; jump_next = lib.mkDefault false; accept = lib.mkDefault false; refresh = lib.mkDefault false; open = lib.mkDefault false; }; suggestion.keymap = { accept = lib.mkDefault false; accept_word = lib.mkDefault false; accept_line = lib.mkDefault false; next = lib.mkDefault false; prev = lib.mkDefault false; dismiss = lib.mkDefault false; }; }; }; }; }