-
-
Notifications
You must be signed in to change notification settings - Fork 65
Expand file tree
/
Copy pathconfig.lua
More file actions
376 lines (322 loc) · 13.8 KB
/
config.lua
File metadata and controls
376 lines (322 loc) · 13.8 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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
---@mod claude-code.config Configuration management for claude-code.nvim
---@brief [[
--- This module handles configuration management and validation for claude-code.nvim.
--- It provides the default configuration, validation, and merging of user config.
---@brief ]]
local M = {}
--- ClaudeCodeWindow class for window configuration
-- @table ClaudeCodeWindow
-- @field split_ratio number Percentage of screen for the terminal window (height for horizontal, width for vertical splits)
-- @field position string Position of the window: "botright", "topleft", "vertical", "floating", etc.
-- @field enter_insert boolean Whether to enter insert mode when opening Claude Code
-- @field start_in_normal_mode boolean Whether to start in normal mode instead of insert mode when opening Claude Code
-- @field hide_numbers boolean Hide line numbers in the terminal window
-- @field hide_signcolumn boolean Hide the sign column in the terminal window
-- @field floating ClaudeCodeFloating Floating window configuration (used when position = "floating")
--- ClaudeCodeFloating class for floating window configuration
-- @table ClaudeCodeFloating
-- @field width number Percentage of screen width for the floating window (0.0 to 1.0)
-- @field height number Percentage of screen height for the floating window (0.0 to 1.0)
-- @field border string|table Border style for the floating window
--- ClaudeCodeRefresh class for file refresh configuration
-- @table ClaudeCodeRefresh
-- @field enable boolean Enable file change detection
-- @field updatetime number updatetime when Claude Code is active (milliseconds)
-- @field timer_interval number How often to check for file changes (milliseconds)
-- @field show_notifications boolean Show notification when files are reloaded
--- ClaudeCodeGit class for git integration configuration
-- @table ClaudeCodeGit
-- @field use_git_root boolean Set CWD to git root when opening Claude Code (if in git project)
-- @field multi_instance boolean Use multiple Claude instances (one per git root)
--- ClaudeCodeKeymapsToggle class for toggle keymap configuration
-- @table ClaudeCodeKeymapsToggle
-- @field normal string|boolean Normal mode keymap for toggling Claude Code, false to disable
-- @field terminal string|boolean Terminal mode keymap for toggling Claude Code, false to disable
--- ClaudeCodeKeymaps class for keymap configuration
-- @table ClaudeCodeKeymaps
-- @field toggle ClaudeCodeKeymapsToggle Keymaps for toggling Claude Code
-- @field window_navigation boolean Enable window navigation keymaps
-- @field scrolling boolean Enable scrolling keymaps
--- ClaudeCodeCommandVariants class for command variant configuration
-- @table ClaudeCodeCommandVariants
-- Conversation management:
-- @field continue string|boolean Resume the most recent conversation
-- @field resume string|boolean Display an interactive conversation picker
-- Output options:
-- @field verbose string|boolean Enable verbose logging with full turn-by-turn output
-- Additional options can be added as needed
--- ClaudeCodeShell class for shell configuration
-- @table ClaudeCodeShell
-- @field separator string Command separator used in shell commands (e.g., '&&', ';', '|')
-- @field pushd_cmd string Command to push directory onto stack (e.g., 'pushd' for bash/zsh)
-- @field popd_cmd string Command to pop directory from stack (e.g., 'popd' for bash/zsh)
--- ClaudeCodeConfig class for main configuration
-- @table ClaudeCodeConfig
-- @field window ClaudeCodeWindow Terminal window settings
-- @field refresh ClaudeCodeRefresh File refresh settings
-- @field git ClaudeCodeGit Git integration settings
-- @field shell ClaudeCodeShell Shell-specific configuration
-- @field command string Command used to launch Claude Code
-- @field command_variants ClaudeCodeCommandVariants Command variants configuration
-- @field keymaps ClaudeCodeKeymaps Keymaps configuration
--- Default configuration options
--- @type ClaudeCodeConfig
M.default_config = {
-- Terminal window settings
window = {
split_ratio = 0.3, -- Percentage of screen for the terminal window (height or width)
height_ratio = 0.3, -- DEPRECATED: Use split_ratio instead
position = 'botright', -- Position of the window: "botright", "topleft", "vertical", "floating", etc.
enter_insert = true, -- Whether to enter insert mode when opening Claude Code
start_in_normal_mode = false, -- Whether to start in normal mode instead of insert mode
hide_numbers = true, -- Hide line numbers in the terminal window
hide_signcolumn = true, -- Hide the sign column in the terminal window
-- Floating window configuration (used when position = "floating")
floating = {
width = 0.8, -- Percentage of screen width for the floating window
height = 0.8, -- Percentage of screen height for the floating window
border = 'rounded', -- Border style: 'none', 'single', 'double', 'rounded', 'solid', 'shadow'
},
},
-- File refresh settings
refresh = {
enable = true, -- Enable file change detection
updatetime = 100, -- updatetime to use when Claude Code is active (milliseconds)
timer_interval = 1000, -- How often to check for file changes (milliseconds)
show_notifications = true, -- Show notification when files are reloaded
},
-- Git integration settings
git = {
use_git_root = true, -- Set CWD to git root when opening Claude Code (if in git project)
multi_instance = true, -- Use multiple Claude instances (one per git root)
},
-- Shell-specific settings
shell = {
separator = '&&', -- Command separator used in shell commands
pushd_cmd = 'pushd', -- Command to push directory onto stack
popd_cmd = 'popd', -- Command to pop directory from stack
},
-- Command settings
command = 'claude', -- Command used to launch Claude Code
-- Command variants
command_variants = {
-- Conversation management
continue = '--continue', -- Resume the most recent conversation
resume = '--resume', -- Display an interactive conversation picker
-- Output options
verbose = '--verbose', -- Enable verbose logging with full turn-by-turn output
},
-- Keymaps
keymaps = {
toggle = {
normal = '<C-,>', -- Normal mode keymap for toggling Claude Code
terminal = '<C-,>', -- Terminal mode keymap for toggling Claude Code
variants = {
continue = '<leader>cC', -- Normal mode keymap for Claude Code with continue flag
verbose = '<leader>cV', -- Normal mode keymap for Claude Code with verbose flag
},
},
window_navigation = true, -- Enable window navigation keymaps (<C-h/j/k/l>)
scrolling = true, -- Enable scrolling keymaps (<C-f/b>) for page up/down
},
}
--- Validate the configuration
--- @param config ClaudeCodeConfig
--- @return boolean valid
--- @return string? error_message
local function validate_config(config)
-- Validate window settings
if type(config.window) ~= 'table' then
return false, 'window config must be a table'
end
if
type(config.window.split_ratio) ~= 'number'
or config.window.split_ratio <= 0
or config.window.split_ratio > 1
then
return false, 'window.split_ratio must be a number between 0 and 1'
end
if type(config.window.position) ~= 'string' then
return false, 'window.position must be a string'
end
if type(config.window.enter_insert) ~= 'boolean' then
return false, 'window.enter_insert must be a boolean'
end
if type(config.window.start_in_normal_mode) ~= 'boolean' then
return false, 'window.start_in_normal_mode must be a boolean'
end
if type(config.window.hide_numbers) ~= 'boolean' then
return false, 'window.hide_numbers must be a boolean'
end
if type(config.window.hide_signcolumn) ~= 'boolean' then
return false, 'window.hide_signcolumn must be a boolean'
end
-- Validate floating window settings if they exist
if config.window.floating then
if type(config.window.floating) ~= 'table' then
return false, 'window.floating config must be a table'
end
if
type(config.window.floating.width) ~= 'number'
or config.window.floating.width <= 0
or config.window.floating.width > 1
then
return false, 'window.floating.width must be a number between 0 and 1'
end
if
type(config.window.floating.height) ~= 'number'
or config.window.floating.height <= 0
or config.window.floating.height > 1
then
return false, 'window.floating.height must be a number between 0 and 1'
end
if
not (
type(config.window.floating.border) == 'string'
or type(config.window.floating.border) == 'table'
)
then
return false, 'window.floating.border must be a string or table'
end
end
-- Validate refresh settings
if type(config.refresh) ~= 'table' then
return false, 'refresh config must be a table'
end
if type(config.refresh.enable) ~= 'boolean' then
return false, 'refresh.enable must be a boolean'
end
if type(config.refresh.updatetime) ~= 'number' or config.refresh.updatetime <= 0 then
return false, 'refresh.updatetime must be a positive number'
end
if type(config.refresh.timer_interval) ~= 'number' or config.refresh.timer_interval <= 0 then
return false, 'refresh.timer_interval must be a positive number'
end
if type(config.refresh.show_notifications) ~= 'boolean' then
return false, 'refresh.show_notifications must be a boolean'
end
-- Validate git settings
if type(config.git) ~= 'table' then
return false, 'git config must be a table'
end
if type(config.git.use_git_root) ~= 'boolean' then
return false, 'git.use_git_root must be a boolean'
end
if type(config.git.multi_instance) ~= 'boolean' then
return false, 'git.multi_instance must be a boolean'
end
-- Validate shell settings
if type(config.shell) ~= 'table' then
return false, 'shell config must be a table'
end
if type(config.shell.separator) ~= 'string' then
return false, 'shell.separator must be a string'
end
if type(config.shell.pushd_cmd) ~= 'string' then
return false, 'shell.pushd_cmd must be a string'
end
if type(config.shell.popd_cmd) ~= 'string' then
return false, 'shell.popd_cmd must be a string'
end
-- Validate command settings
if type(config.command) ~= 'string' then
return false, 'command must be a string'
end
-- Validate command variants settings
if type(config.command_variants) ~= 'table' then
return false, 'command_variants config must be a table'
end
-- Check each command variant
for variant_name, variant_args in pairs(config.command_variants) do
if not (variant_args == false or type(variant_args) == 'string') then
return false, 'command_variants.' .. variant_name .. ' must be a string or false'
end
end
-- Validate keymaps settings
if type(config.keymaps) ~= 'table' then
return false, 'keymaps config must be a table'
end
if type(config.keymaps.toggle) ~= 'table' then
return false, 'keymaps.toggle must be a table'
end
if
not (config.keymaps.toggle.normal == false or type(config.keymaps.toggle.normal) == 'string')
then
return false, 'keymaps.toggle.normal must be a string or false'
end
if
not (
config.keymaps.toggle.terminal == false or type(config.keymaps.toggle.terminal) == 'string'
)
then
return false, 'keymaps.toggle.terminal must be a string or false'
end
-- Validate variant keymaps if they exist
if config.keymaps.toggle.variants then
if type(config.keymaps.toggle.variants) ~= 'table' then
return false, 'keymaps.toggle.variants must be a table'
end
-- Check each variant keymap
for variant_name, keymap in pairs(config.keymaps.toggle.variants) do
if not (keymap == false or type(keymap) == 'string') then
return false, 'keymaps.toggle.variants.' .. variant_name .. ' must be a string or false'
end
-- Ensure variant exists in command_variants
if keymap ~= false and not config.command_variants[variant_name] then
return false,
'keymaps.toggle.variants.' .. variant_name .. ' has no corresponding command variant'
end
end
end
if type(config.keymaps.window_navigation) ~= 'boolean' then
return false, 'keymaps.window_navigation must be a boolean'
end
if type(config.keymaps.scrolling) ~= 'boolean' then
return false, 'keymaps.scrolling must be a boolean'
end
return true, nil
end
--- Parse user configuration and merge with defaults
--- @param user_config? table
--- @param silent? boolean Set to true to suppress error notifications (for tests)
--- @return ClaudeCodeConfig
function M.parse_config(user_config, silent)
-- Handle backward compatibility first
if user_config and user_config.window then
if user_config.window.height_ratio and not user_config.window.split_ratio then
-- Copy height_ratio to split_ratio for backward compatibility
user_config.window.split_ratio = user_config.window.height_ratio
end
end
-- Handle floating config migration
if user_config and user_config.floating then
-- Migrate old floating config to window.floating
if not user_config.window then
user_config.window = {}
end
if not user_config.window.floating then
user_config.window.floating = user_config.floating
end
-- Remove the old floating config to avoid conflicts
user_config.floating = nil
-- Show deprecation warning
if not silent then
vim.notify(
'Claude Code: The floating config has been moved to window.floating. Please update your configuration.',
vim.log.levels.WARN
)
end
end
local config = vim.tbl_deep_extend('force', {}, M.default_config, user_config or {})
local valid, err = validate_config(config)
if not valid then
-- Only notify if not in silent mode
if not silent then
vim.notify('Claude Code: ' .. err, vim.log.levels.ERROR)
end
-- Fall back to default config in case of error
return vim.deepcopy(M.default_config)
end
return config
end
return M