Skip to content

Commit 8130b56

Browse files
committed
Allow customizable window_navigation and scrolling keymaps
1 parent c9a31e5 commit 8130b56

4 files changed

Lines changed: 81 additions & 27 deletions

File tree

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,18 @@ require("claude-code").setup({
146146
verbose = "<leader>cV", -- Normal mode keymap for Claude Code with verbose flag
147147
},
148148
},
149-
window_navigation = true, -- Enable window navigation keymaps (<C-h/j/k/l>)
150-
scrolling = true, -- Enable scrolling keymaps (<C-f/b>) for page up/down
149+
window_navigation = {
150+
enabled = true, -- Enable window navigation keymaps
151+
left = '<C-h>', -- Move to left window
152+
down = '<C-j>', -- Move to down window
153+
up = '<C-k>', -- Move to up window
154+
right = '<C-l>', -- Move to right window
155+
},
156+
scrolling = {
157+
enabled = true, -- Enable scrolling keymaps
158+
page_down = '<C-f>', -- Scroll down one page
159+
page_up = '<C-b>', -- Scroll up one page
160+
},
151161
}
152162
})
153163
```

lua/claude-code/config.lua

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ local M = {}
4242
--- ClaudeCodeKeymaps class for keymap configuration
4343
-- @table ClaudeCodeKeymaps
4444
-- @field toggle ClaudeCodeKeymapsToggle Keymaps for toggling Claude Code
45-
-- @field window_navigation boolean Enable window navigation keymaps
46-
-- @field scrolling boolean Enable scrolling keymaps
45+
-- @field window_navigation table|nil Window navigation keymaps
46+
-- @field window_navigation.enabled boolean Enable window navigation keymaps
47+
-- @field scrolling table|nil Scrolling keymaps
48+
-- @field scrolling.enabled boolean Enable scrolling keymaps
4749

4850
--- ClaudeCodeCommandVariants class for command variant configuration
4951
-- @table ClaudeCodeCommandVariants
@@ -131,8 +133,18 @@ M.default_config = {
131133
verbose = '<leader>cV', -- Normal mode keymap for Claude Code with verbose flag
132134
},
133135
},
134-
window_navigation = true, -- Enable window navigation keymaps (<C-h/j/k/l>)
135-
scrolling = true, -- Enable scrolling keymaps (<C-f/b>) for page up/down
136+
window_navigation = {
137+
enabled = true, -- Enable window navigation keymaps
138+
left = '<C-h>', -- Move to left window
139+
down = '<C-j>', -- Move to down window
140+
up = '<C-k>', -- Move to up window
141+
right = '<C-l>', -- Move to right window
142+
},
143+
scrolling = {
144+
enabled = true, -- Enable scrolling keymaps
145+
page_down = '<C-f>', -- Scroll down one page
146+
page_up = '<C-b>', -- Scroll up one page
147+
},
136148
},
137149
}
138150

@@ -351,12 +363,44 @@ local function validate_keymaps_config(keymaps)
351363
end
352364
end
353365

354-
if type(keymaps.window_navigation) ~= 'boolean' then
355-
return false, 'keymaps.window_navigation must be a boolean'
366+
if type(keymaps.window_navigation) ~= 'table' then
367+
return false, 'keymaps.window_navigation must be a table'
368+
end
369+
370+
if type(keymaps.window_navigation.enabled) ~= 'boolean' then
371+
return false, 'keymaps.window_navigation.enabled must be a table'
372+
end
373+
374+
if type(keymaps.window_navigation.left) ~= 'string' then
375+
return false, 'keymaps.window_navigation.left must be a string'
376+
end
377+
378+
if type(keymaps.window_navigation.down) ~= 'string' then
379+
return false, 'keymaps.window_navigation.down must be a string'
380+
end
381+
382+
if type(keymaps.window_navigation.up) ~= 'string' then
383+
return false, 'keymaps.window_navigation.up must be a string'
384+
end
385+
386+
if type(keymaps.window_navigation.right) ~= 'string' then
387+
return false, 'keymaps.window_navigation.right must be a string'
388+
end
389+
390+
if type(keymaps.scrolling) ~= 'table' then
391+
return false, 'keymaps.scrolling must be a btable'
392+
end
393+
394+
if type(keymaps.scrolling.enabled) ~= 'boolean' then
395+
return false, 'keymaps.scrolling.enabled must be a boolean'
396+
end
397+
398+
if type(keymaps.scrolling.page_down) ~= 'string' then
399+
return false, 'keymaps.scrolling.page_down must be a string'
356400
end
357401

358-
if type(keymaps.scrolling) ~= 'boolean' then
359-
return false, 'keymaps.scrolling must be a boolean'
402+
if type(keymaps.scrolling.page_up) ~= 'string' then
403+
return false, 'keymaps.scrolling.page_up must be a string'
360404
end
361405

362406
return true, nil

lua/claude-code/keymaps.lua

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -109,33 +109,33 @@ function M.setup_terminal_navigation(claude_code, config)
109109
)
110110

111111
-- Window navigation keymaps
112-
if config.keymaps.window_navigation then
112+
if config.keymaps.window_navigation.enabled then
113113
-- Window navigation keymaps with special handling to force insert mode in the target window
114114
vim.api.nvim_buf_set_keymap(
115115
buf,
116116
't',
117-
'<C-h>',
117+
config.keymaps.window_navigation.left,
118118
[[<C-\><C-n><C-w>h:lua require("claude-code").force_insert_mode()<CR>]],
119119
{ noremap = true, silent = true, desc = 'Window: move left' }
120120
)
121121
vim.api.nvim_buf_set_keymap(
122122
buf,
123123
't',
124-
'<C-j>',
124+
config.keymaps.window_navigation.down,
125125
[[<C-\><C-n><C-w>j:lua require("claude-code").force_insert_mode()<CR>]],
126126
{ noremap = true, silent = true, desc = 'Window: move down' }
127127
)
128128
vim.api.nvim_buf_set_keymap(
129129
buf,
130130
't',
131-
'<C-k>',
131+
config.keymaps.window_navigation.up,
132132
[[<C-\><C-n><C-w>k:lua require("claude-code").force_insert_mode()<CR>]],
133133
{ noremap = true, silent = true, desc = 'Window: move up' }
134134
)
135135
vim.api.nvim_buf_set_keymap(
136136
buf,
137137
't',
138-
'<C-l>',
138+
config.keymaps.window_navigation.right,
139139
[[<C-\><C-n><C-w>l:lua require("claude-code").force_insert_mode()<CR>]],
140140
{ noremap = true, silent = true, desc = 'Window: move right' }
141141
)
@@ -144,46 +144,46 @@ function M.setup_terminal_navigation(claude_code, config)
144144
vim.api.nvim_buf_set_keymap(
145145
buf,
146146
'n',
147-
'<C-h>',
147+
config.keymaps.window_navigation.left,
148148
[[<C-w>h:lua require("claude-code").force_insert_mode()<CR>]],
149149
{ noremap = true, silent = true, desc = 'Window: move left' }
150150
)
151151
vim.api.nvim_buf_set_keymap(
152152
buf,
153153
'n',
154-
'<C-j>',
154+
config.keymaps.window_navigation.down,
155155
[[<C-w>j:lua require("claude-code").force_insert_mode()<CR>]],
156156
{ noremap = true, silent = true, desc = 'Window: move down' }
157157
)
158158
vim.api.nvim_buf_set_keymap(
159159
buf,
160160
'n',
161-
'<C-k>',
161+
config.keymaps.window_navigation.up,
162162
[[<C-w>k:lua require("claude-code").force_insert_mode()<CR>]],
163163
{ noremap = true, silent = true, desc = 'Window: move up' }
164164
)
165165
vim.api.nvim_buf_set_keymap(
166166
buf,
167167
'n',
168-
'<C-l>',
168+
config.keymaps.window_navigation.right,
169169
[[<C-w>l:lua require("claude-code").force_insert_mode()<CR>]],
170170
{ noremap = true, silent = true, desc = 'Window: move right' }
171171
)
172172
end
173173

174174
-- Add scrolling keymaps
175-
if config.keymaps.scrolling then
175+
if config.keymaps.scrolling.enabled then
176176
vim.api.nvim_buf_set_keymap(
177177
buf,
178178
't',
179-
'<C-f>',
179+
config.keymaps.window_navigation.page_down,
180180
[[<C-\><C-n><C-f>i]],
181181
{ noremap = true, silent = true, desc = 'Scroll full page down' }
182182
)
183183
vim.api.nvim_buf_set_keymap(
184184
buf,
185185
't',
186-
'<C-b>',
186+
config.keymaps.window_navigation.page_up,
187187
[[<C-\><C-n><C-b>i]],
188188
{ noremap = true, silent = true, desc = 'Scroll full page up' }
189189
)

tests/spec/config_validation_spec.lua

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ describe('config validation', function()
8383

8484
local result = config.parse_config(invalid_config, true) -- silent mode
8585
assert.are.equal(config.default_config.window.position, result.window.position)
86-
-- Ensure invalid border doesn't bleed through
86+
-- Ensure invalid border doesn't bleed through
8787
assert.are.not_equal('invalid', result.window.float.border)
8888
assert.are.equal(config.default_config.window.float.border, result.window.float.border)
8989
end)
@@ -147,17 +147,17 @@ describe('config validation', function()
147147
assert.are.equal(config.default_config.keymaps.toggle.normal, result3.keymaps.toggle.normal)
148148
end)
149149

150-
it('should validate keymaps.window_navigation must be a boolean', function()
150+
it('should validate keymaps.window_navigation.enabled must be a boolean', function()
151151
-- Simplify this test to match others
152152
local invalid_config = vim.deepcopy(config.default_config)
153-
invalid_config.keymaps.window_navigation = 'enabled' -- String instead of boolean
153+
invalid_config.keymaps.window_navigation.enabled = 'enabled' -- String instead of boolean
154154

155155
-- Use silent mode to avoid pollution
156156
local result = config.parse_config(invalid_config, true)
157157

158158
assert.are.equal(
159-
config.default_config.keymaps.window_navigation,
160-
result.keymaps.window_navigation
159+
config.default_config.keymaps.window_navigation.enabled,
160+
result.keymaps.window_navigation.enabled
161161
)
162162
end)
163163
end)

0 commit comments

Comments
 (0)