-
Notifications
You must be signed in to change notification settings - Fork 198
Expand file tree
/
Copy pathconfig.lua
More file actions
141 lines (119 loc) · 5.4 KB
/
Copy pathconfig.lua
File metadata and controls
141 lines (119 loc) · 5.4 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
---@brief [[
--- Manages configuration for the Claude Code Neovim integration.
--- Provides default settings, validation, and application of user-defined configurations.
---@brief ]]
---@module 'claudecode.config'
local M = {}
---@type ClaudeCodeConfig
M.defaults = {
port_range = { min = 10000, max = 65535 },
auto_start = true,
terminal_cmd = nil,
env = {}, -- Custom environment variables for Claude terminal
log_level = "info",
track_selection = true,
visual_demotion_delay_ms = 50, -- Milliseconds to wait before demoting a visual selection
connection_wait_delay = 200, -- Milliseconds to wait after connection before sending queued @ mentions
connection_timeout = 10000, -- Maximum time to wait for Claude Code to connect (milliseconds)
queue_timeout = 5000, -- Maximum time to keep @ mentions in queue (milliseconds)
diff_opts = {
auto_close_on_accept = true,
show_diff_stats = true,
vertical_split = true,
open_in_current_tab = true, -- Use current tab instead of creating new tab
keep_terminal_focus = false, -- If true, moves focus back to terminal after diff opens
},
models = {
{ name = "Claude Opus 4 (Latest)", value = "opus" },
{ name = "Claude Sonnet 4 (Latest)", value = "sonnet" },
},
terminal = nil, -- Will be lazy-loaded to avoid circular dependency
}
---Validates the provided configuration table.
---Throws an error if any validation fails.
---@param config table The configuration table to validate.
---@return boolean true if the configuration is valid.
function M.validate(config)
assert(
type(config.port_range) == "table"
and type(config.port_range.min) == "number"
and type(config.port_range.max) == "number"
and config.port_range.min > 0
and config.port_range.max <= 65535
and config.port_range.min <= config.port_range.max,
"Invalid port range"
)
assert(type(config.auto_start) == "boolean", "auto_start must be a boolean")
assert(config.terminal_cmd == nil or type(config.terminal_cmd) == "string", "terminal_cmd must be nil or a string")
local valid_log_levels = { "trace", "debug", "info", "warn", "error" }
local is_valid_log_level = false
for _, level in ipairs(valid_log_levels) do
if config.log_level == level then
is_valid_log_level = true
break
end
end
assert(is_valid_log_level, "log_level must be one of: " .. table.concat(valid_log_levels, ", "))
assert(type(config.track_selection) == "boolean", "track_selection must be a boolean")
assert(
type(config.visual_demotion_delay_ms) == "number" and config.visual_demotion_delay_ms >= 0,
"visual_demotion_delay_ms must be a non-negative number"
)
assert(
type(config.connection_wait_delay) == "number" and config.connection_wait_delay >= 0,
"connection_wait_delay must be a non-negative number"
)
assert(
type(config.connection_timeout) == "number" and config.connection_timeout > 0,
"connection_timeout must be a positive number"
)
assert(type(config.queue_timeout) == "number" and config.queue_timeout > 0, "queue_timeout must be a positive number")
assert(type(config.diff_opts) == "table", "diff_opts must be a table")
assert(type(config.diff_opts.auto_close_on_accept) == "boolean", "diff_opts.auto_close_on_accept must be a boolean")
assert(type(config.diff_opts.show_diff_stats) == "boolean", "diff_opts.show_diff_stats must be a boolean")
assert(type(config.diff_opts.vertical_split) == "boolean", "diff_opts.vertical_split must be a boolean")
assert(type(config.diff_opts.open_in_current_tab) == "boolean", "diff_opts.open_in_current_tab must be a boolean")
assert(type(config.diff_opts.keep_terminal_focus) == "boolean", "diff_opts.keep_terminal_focus must be a boolean")
-- Validate env
assert(type(config.env) == "table", "env must be a table")
for key, value in pairs(config.env) do
assert(type(key) == "string", "env keys must be strings")
assert(type(value) == "string", "env values must be strings")
end
-- Validate models
assert(type(config.models) == "table", "models must be a table")
assert(#config.models > 0, "models must not be empty")
for i, model in ipairs(config.models) do
assert(type(model) == "table", "models[" .. i .. "] must be a table")
assert(type(model.name) == "string" and model.name ~= "", "models[" .. i .. "].name must be a non-empty string")
assert(type(model.value) == "string" and model.value ~= "", "models[" .. i .. "].value must be a non-empty string")
end
return true
end
---Applies user configuration on top of default settings and validates the result.
---@param user_config table|nil The user-provided configuration table.
---@return ClaudeCodeConfig config The final, validated configuration table.
function M.apply(user_config)
local config = vim.deepcopy(M.defaults)
-- Lazy-load terminal defaults to avoid circular dependency
if config.terminal == nil then
local terminal_ok, terminal_module = pcall(require, "claudecode.terminal")
if terminal_ok and terminal_module.defaults then
config.terminal = terminal_module.defaults
end
end
if user_config then
-- Use vim.tbl_deep_extend if available, otherwise simple merge
if vim.tbl_deep_extend then
config = vim.tbl_deep_extend("force", config, user_config)
else
-- Simple fallback for testing environment
for k, v in pairs(user_config) do
config[k] = v
end
end
end
M.validate(config)
return config
end
return M