Repository navigation
Expand file tree
/
Copy pathkeymap.lua
More file actions
142 lines (125 loc) · 4.76 KB
/
Copy pathkeymap.lua
File metadata and controls
142 lines (125 loc) · 4.76 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
local M = {}
local commands = require('opencode.commands')
local store = require('opencode.state.store')
local window_keymaps = {}
local function normalize_lhs(lhs)
return vim.api.nvim_replace_termcodes(lhs, true, true, true)
end
local function is_completion_visible()
return require('opencode.ui.completion').is_completion_visible()
end
---@param key_binding string The key binding to feed if completion is visible
---@param callback function The callback to execute if completion is not visible
local function wrap_with_completion_check(key_binding, callback)
return function()
if is_completion_visible() then
return vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key_binding, true, false, true), 'n', false)
end
return callback()
end
end
---@param func_name string|function
---@param func_args any
---@return function|nil
local function resolve_callback(func_name, func_args)
if type(func_name) == 'function' then
return func_name
end
if type(func_name) == 'string' then
local command_defs = commands.get_commands()
if command_defs[func_name] then
return function()
local args = func_args and (type(func_args) == 'table' and vim.deepcopy(func_args) or { func_args }) or {}
local parsed = commands.build_parsed_intent(func_name, args)
return commands.execute_parsed_intent(parsed)
end
end
vim.notify('Cannot find keymap action: ' .. func_name, vim.log.levels.ERROR)
return nil
end
return nil
end
---@param keymap_config table The keymap configuration table
---@param default_modes table Default modes for these keymaps
---@param base_opts table Base options to use for all keymaps
---@param preserve_existing? boolean
local function process_keymap_entry(keymap_config, default_modes, base_opts, preserve_existing)
local command_defs = commands.get_commands()
for key_binding, config_entry in pairs(keymap_config) do
if config_entry == false then
-- Skip keymap if explicitly set to false (disabled)
elseif config_entry then
local func_name = config_entry[1]
local func_args = config_entry[2]
local callback = resolve_callback(func_name, func_args)
local modes = config_entry.mode or default_modes
if preserve_existing and base_opts.buffer then
local missing_modes = {}
for _, mode in ipairs(type(modes) == 'table' and modes or { modes }) do
local exists = false
for _, mapping in ipairs(vim.api.nvim_buf_get_keymap(base_opts.buffer, mode)) do
if normalize_lhs(mapping.lhs) == normalize_lhs(key_binding) then
exists = true
break
end
end
if not exists then
table.insert(missing_modes, mode)
end
end
modes = missing_modes
end
local opts = vim.tbl_deep_extend('force', {}, base_opts)
opts.nowait = config_entry.nowait
opts.desc = config_entry.desc or vim.tbl_get(command_defs, func_name, 'desc') or ''
if not callback then
if type(func_name) ~= 'string' then
vim.notify(string.format('No action found for keymap: %s -> %s', key_binding, func_name), vim.log.levels.WARN)
end
elseif #modes > 0 then
if config_entry.defer_to_completion then
callback = wrap_with_completion_check(key_binding, callback)
end
vim.keymap.set(modes, key_binding, callback, opts)
end
end
end
end
local function setup_panel_keymaps(_, windows, previous)
if not windows then
return
end
for _, name in ipairs({ 'input', 'output', 'tab_strip' }) do
local buf, win = windows[name .. '_buf'], windows[name .. '_win']
local changed = not previous or previous[name .. '_buf'] ~= buf or previous[name .. '_win'] ~= win
if
changed
and buf
and vim.api.nvim_buf_is_valid(buf)
and (name == 'tab_strip' or win and vim.api.nvim_win_is_valid(win))
then
M.setup_window_keymaps(window_keymaps[name .. '_window'], buf, true)
end
end
end
---@param keymap OpencodeKeymap The keymap configuration table
function M.setup(keymap)
process_keymap_entry(keymap.editor or {}, { 'n', 'v' }, { silent = false })
window_keymaps = keymap
store.subscribe('windows', setup_panel_keymaps)
setup_panel_keymaps(nil, store.get('windows'))
end
function M.teardown()
store.unsubscribe('windows', setup_panel_keymaps)
window_keymaps = {}
end
---@param keymap_config table Window keymap configuration
---@param buf_id integer Buffer ID to set keymaps for
---@param preserve_existing? boolean
function M.setup_window_keymaps(keymap_config, buf_id, preserve_existing)
if not vim.api.nvim_buf_is_valid(buf_id) then
return
end
process_keymap_entry(keymap_config or {}, { 'n' }, { silent = true, buffer = buf_id }, preserve_existing)
end
return M