forked from zbirenbaum/copilot.lua
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinit.lua
More file actions
193 lines (164 loc) · 5.78 KB
/
init.lua
File metadata and controls
193 lines (164 loc) · 5.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
local logger = require("copilot.logger")
local M = {}
local previous_keymaps = {}
---@param bufnr integer
---@param mode string
---@param key string
local function get_keymap_key(bufnr, mode, key)
if not bufnr or not mode or not key then
logger.error("Invalid parameters to get_keymap_key" .. vim.inspect({ bufnr, mode, key }))
return "invalid"
end
return bufnr .. ":" .. mode .. ":" .. key
end
---@param mode string
---@param key string
---@param action function
---@param desc string
---@param bufnr integer
function M.register_keymap(mode, key, action, desc, bufnr)
if not key then
return
end
if not mode or not action then
logger.error("Invalid parameters to register_keymap" .. vim.inspect({ mode, key, action, desc, bufnr }))
return
end
local keymap_key = get_keymap_key(bufnr, mode, key)
if previous_keymaps[keymap_key] then
logger.trace("Keymap already registered for " .. keymap_key)
M.unset_keymap_if_exists(mode, key, bufnr)
end
vim.keymap.set(mode, key, function()
action()
end, {
desc = desc,
silent = true,
buffer = bufnr,
})
previous_keymaps[keymap_key] = { type = "none", value = nil }
end
---@param mode string
---@param key string
---@param keymap_key string
local function save_existing_keymap(mode, key, keymap_key)
local existing = vim.fn.maparg(key, mode, false, true)
if existing then
if existing.rhs and existing.rhs ~= "" then
previous_keymaps[keymap_key] = { type = "rhs", value = existing.rhs }
logger.trace("Saved existing keymap for " .. keymap_key .. ": " .. existing.rhs)
return
elseif existing.callback then
previous_keymaps[keymap_key] = { type = "callback", value = existing.callback }
logger.trace("Saved existing keymap callback for " .. keymap_key)
return
end
end
previous_keymaps[keymap_key] = { type = "none", value = nil }
logger.trace("No existing keymap for " .. keymap_key)
end
---@param mode string
---@param key string
---@param action function: boolean
---@param desc string
---@param bufnr integer
function M.register_keymap_with_passthrough(mode, key, action, desc, bufnr)
if not key then
return
end
if not mode or not action then
logger.error("Invalid parameters to register_keymap_with_passthrough" .. vim.inspect({ mode, key, action, desc }))
return
end
local keymap_key = get_keymap_key(bufnr, mode, key)
if previous_keymaps[keymap_key] then
M.unset_keymap_if_exists(mode, key, bufnr)
logger.trace("Keymap already registered for " .. keymap_key)
end
save_existing_keymap(mode, key, keymap_key)
vim.keymap.set(mode, key, function()
logger.trace("Keymap triggered for " .. keymap_key)
if action() then
logger.trace("Action handled the keymap for " .. keymap_key)
return "<Ignore>"
end
local prev = previous_keymaps[keymap_key]
if prev then
if prev.type == "rhs" then
logger.trace("Passing through to previous keymap for " .. keymap_key .. ": " .. prev.value)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(prev.value, true, false, true), mode, true)
return "<Ignore>"
elseif prev.type == "callback" then
logger.trace("Passing through to previous keymap callback for " .. keymap_key)
prev.value()
return "<Ignore>"
end
end
logger.trace("No previous keymap to pass through for " .. keymap_key)
return key
end, {
desc = desc,
expr = true,
silent = true,
buffer = bufnr,
})
end
---@param mode string
---@param key string|false
---@param bufnr integer
function M.unset_keymap_if_exists(mode, key, bufnr)
if not key or not bufnr then
return
end
local ok, err = pcall(vim.api.nvim_buf_del_keymap, bufnr, mode, key)
-- restore previous keymap if it existed
if previous_keymaps[get_keymap_key(bufnr, mode, key)] then
local prev = previous_keymaps[get_keymap_key(bufnr, mode, key)]
if prev.type == "rhs" and prev.value then
vim.keymap.set(mode, key, prev.value, {
silent = true,
buffer = bufnr,
})
logger.trace("Restored previous keymap for " .. get_keymap_key(bufnr, mode, key) .. ": " .. prev.value)
elseif prev.type == "callback" and prev.value then
vim.keymap.set(mode, key, prev.value, {
silent = true,
buffer = bufnr,
})
logger.trace("Restored previous keymap callback for " .. get_keymap_key(bufnr, mode, key))
else
logger.trace("No previous keymap to restore for " .. get_keymap_key(bufnr, mode, key))
end
end
previous_keymaps[get_keymap_key(bufnr, mode, key)] = nil
if not ok then
logger.trace("Could not unset keymap for " .. (mode or "nil") .. " " .. key .. ", bufnr " .. bufnr .. ": " .. err)
end
end
---@param config CopilotConfig
function M.validate(config)
local suggestion_keymaps = config.suggestion.keymap or {}
local nes_keymaps = config.nes.keymap or {}
local panel_keymaps = config.panel.keymap or {}
local seen = {}
local duplicates = {}
for _, cfg in ipairs({ suggestion_keymaps, nes_keymaps, panel_keymaps }) do
for action, km in pairs(cfg) do
if km then
-- TODO: find a better way to determine mode, this is prone to maintenance bugs
-- TODO: Not sure how to validate keymaps, since some COULD be duplicates and valid
local mode = (action == config.panel.keymap.open or vim.tbl_contains(config.nes.keymap, action)) and "n" or "i"
local keymap_key = get_keymap_key(0, mode, km)
if seen[keymap_key] then
duplicates[keymap_key] = (duplicates[keymap_key] or 1) + 1
else
seen[keymap_key] = true
end
end
end
end
for key, count in pairs(duplicates) do
logger.error("Duplicate keymap detected: " .. key .. " (" .. count .. " times), please review your configuration.")
end
end
return M