Skip to content

refactor: centralize type definitions in dedicated types.lua module #108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 2 additions & 31 deletions lua/claudecode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,7 @@

local M = {}

-- Types (authoritative for configuration shape):
---@class ClaudeCode.DiffOptions
---@field auto_close_on_accept boolean
---@field show_diff_stats boolean
---@field vertical_split boolean
---@field open_in_current_tab boolean
---@field keep_terminal_focus boolean

---@class ClaudeCode.ModelOption
---@field name string
---@field value string

---@alias ClaudeCode.LogLevel "trace"|"debug"|"info"|"warn"|"error"

---@class ClaudeCode.Config
---@field port_range {min: integer, max: integer}
---@field auto_start boolean
---@field terminal_cmd string|nil
---@field env table<string, string>
---@field log_level ClaudeCode.LogLevel
---@field track_selection boolean
---@field visual_demotion_delay_ms number
---@field connection_wait_delay number
---@field connection_timeout number
---@field queue_timeout number
---@field diff_opts ClaudeCode.DiffOptions
---@field models ClaudeCode.ModelOption[]
---@field disable_broadcast_debouncing? boolean
---@field enable_broadcast_debouncing_in_tests? boolean
---@field terminal TerminalConfig|nil
---@type ClaudeCodeConfig
M.defaults = {
port_range = { min = 10000, max = 65535 },
auto_start = true,
Expand Down Expand Up @@ -138,7 +109,7 @@ end

---Applies user configuration on top of default settings and validates the result.
---@param user_config table|nil The user-provided configuration table.
---@return ClaudeCode.Config config The final, validated configuration table.
---@return ClaudeCodeConfig config The final, validated configuration table.
function M.apply(user_config)
local config = vim.deepcopy(M.defaults)

Expand Down
33 changes: 3 additions & 30 deletions lua/claudecode/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,8 @@ local M = {}

local logger = require("claudecode.logger")

-- Types

---@class ClaudeCode.Version
---@field major integer
---@field minor integer
---@field patch integer
---@field prerelease? string
---@field string fun(self: ClaudeCode.Version):string

-- Narrow facade of the server module used by this file
---@class ClaudeCode.ServerFacade
---@field start fun(config: ClaudeCode.Config, auth_token: string|nil): boolean, number|string
---@field stop fun(): boolean, string|nil
---@field broadcast fun(method: string, params: table|nil): boolean
---@field get_status fun(): { running: boolean, port: integer|nil, client_count: integer, clients?: table }

-- State type for this module
---@class ClaudeCode.State
---@field config ClaudeCode.Config
---@field server ClaudeCode.ServerFacade|nil
---@field port integer|nil
---@field auth_token string|nil
---@field initialized boolean
---@field mention_queue table[]
---@field mention_timer table|nil
---@field connection_timer table|nil

--- Current plugin version
---@type ClaudeCode.Version
---@type ClaudeCodeVersion
M.version = {
major = 0,
minor = 2,
Expand All @@ -53,7 +26,7 @@ M.version = {
}

-- Module state
---@type ClaudeCode.State
---@type ClaudeCodeState
M.state = {
config = require("claudecode.config").defaults,
server = nil,
Expand Down Expand Up @@ -314,7 +287,7 @@ function M.send_at_mention(file_path, start_line, end_line, context)
end

---Set up the plugin with user configuration
---@param opts ClaudeCode.Config|nil Optional configuration table to override defaults.
---@param opts ClaudeCodeConfig|nil Optional configuration table to override defaults.
---@return table module The plugin module
function M.setup(opts)
opts = opts or {}
Expand Down
4 changes: 2 additions & 2 deletions lua/claudecode/logger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ local level_values = {
local current_log_level_value = M.levels.INFO

---Setup the logger module
---@param plugin_config ClaudeCode.Config The configuration table (e.g., from claudecode.init.state.config).
---@param plugin_config ClaudeCodeConfig The configuration table (e.g., from claudecode.init.state.config).
function M.setup(plugin_config)
local conf = plugin_config

Expand Down Expand Up @@ -119,7 +119,7 @@ function M.info(component, ...)
end

---Check if a specific log level is enabled
---@param level_name ClaudeCode.LogLevel The level name ("error", "warn", "info", "debug", "trace")
---@param level_name ClaudeCodeLogLevel The level name ("error", "warn", "info", "debug", "trace")
---@return boolean enabled Whether the level is enabled
function M.is_level_enabled(level_name)
local level_value = level_values[level_name]
Expand Down
36 changes: 7 additions & 29 deletions lua/claudecode/terminal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,11 @@
--- Supports Snacks.nvim or a native Neovim terminal fallback.
--- @module 'claudecode.terminal'

--- @class TerminalProvider
--- @field setup fun(config: TerminalConfig)
--- @field open fun(cmd_string: string, env_table: table, config: TerminalConfig, focus: boolean?)
--- @field close fun()
--- @field toggle fun(cmd_string: string, env_table: table, effective_config: TerminalConfig)
--- @field simple_toggle fun(cmd_string: string, env_table: table, effective_config: TerminalConfig)
--- @field focus_toggle fun(cmd_string: string, env_table: table, effective_config: TerminalConfig)
--- @field get_active_bufnr fun(): number?
--- @field is_available fun(): boolean
--- @field ensure_visible? function
--- @field _get_terminal_for_test fun(): table?

--- @class TerminalConfig
--- @field split_side "left"|"right"
--- @field split_width_percentage number
--- @field provider "auto"|"snacks"|"native"|TerminalProvider
--- @field show_native_term_exit_tip boolean
--- @field terminal_cmd string|nil
--- @field auto_close boolean
--- @field env table<string, string>
--- @field snacks_win_opts table

local M = {}

local claudecode_server_module = require("claudecode.server.init")

--- @type TerminalConfig
---@type ClaudeCodeTerminalConfig
local defaults = {
split_side = "right",
split_width_percentage = 0.30,
Expand All @@ -47,7 +25,7 @@ local providers = {}

---Loads a terminal provider module
---@param provider_name string The name of the provider to load
---@return TerminalProvider? provider The provider module, or nil if loading failed
---@return ClaudeCodeTerminalProvider? provider The provider module, or nil if loading failed
local function load_provider(provider_name)
if not providers[provider_name] then
local ok, provider = pcall(require, "claudecode.terminal." .. provider_name)
Expand All @@ -61,8 +39,8 @@ local function load_provider(provider_name)
end

---Validates and enhances a custom table provider with smart defaults
---@param provider TerminalProvider The custom provider table to validate
---@return TerminalProvider? provider The enhanced provider, or nil if invalid
---@param provider ClaudeCodeTerminalProvider The custom provider table to validate
---@return ClaudeCodeTerminalProvider? provider The enhanced provider, or nil if invalid
---@return string? error Error message if validation failed
local function validate_and_enhance_provider(provider)
if type(provider) ~= "table" then
Expand Down Expand Up @@ -117,13 +95,13 @@ end

---Gets the effective terminal provider, guaranteed to return a valid provider
---Falls back to native provider if configured provider is unavailable
---@return TerminalProvider provider The terminal provider module (never nil)
---@return ClaudeCodeTerminalProvider provider The terminal provider module (never nil)
local function get_provider()
local logger = require("claudecode.logger")

-- Handle custom table provider
if type(defaults.provider) == "table" then
local custom_provider = defaults.provider --[[@as TerminalProvider]]
local custom_provider = defaults.provider --[[@as ClaudeCodeTerminalProvider]]
local enhanced_provider, error_msg = validate_and_enhance_provider(custom_provider)
if enhanced_provider then
-- Check if custom provider is available
Expand Down Expand Up @@ -290,7 +268,7 @@ end

---Configures the terminal module.
---Merges user-provided terminal configuration with defaults and sets the terminal command.
---@param user_term_config TerminalConfig? Configuration options for the terminal.
---@param user_term_config ClaudeCodeTerminalConfig? Configuration options for the terminal.
---@param p_terminal_cmd string? The command to run in the terminal (from main config).
---@param p_env table? Custom environment variables to pass to the terminal (from main config).
function M.setup(user_term_config, p_terminal_cmd, p_env)
Expand Down
12 changes: 6 additions & 6 deletions lua/claudecode/terminal/native.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ local winid = nil
local jobid = nil
local tip_shown = false

---@type TerminalConfig
---@type ClaudeCodeTerminalConfig
local config = require("claudecode.terminal").defaults

local function cleanup_state()
Expand Down Expand Up @@ -269,7 +269,7 @@ local function find_existing_claude_terminal()
end

---Setup the terminal module
---@param term_config TerminalConfig
---@param term_config ClaudeCodeTerminalConfig
function M.setup(term_config)
config = term_config
end
Expand Down Expand Up @@ -320,7 +320,7 @@ end
---Simple toggle: always show/hide terminal regardless of focus
---@param cmd_string string
---@param env_table table
---@param effective_config TerminalConfig
---@param effective_config ClaudeCodeTerminalConfig
function M.simple_toggle(cmd_string, env_table, effective_config)
-- Check if we have a valid terminal buffer (process running)
local has_buffer = bufnr and vim.api.nvim_buf_is_valid(bufnr)
Expand Down Expand Up @@ -360,7 +360,7 @@ end
---Smart focus toggle: switches to terminal if not focused, hides if currently focused
---@param cmd_string string
---@param env_table table
---@param effective_config TerminalConfig
---@param effective_config ClaudeCodeTerminalConfig
function M.focus_toggle(cmd_string, env_table, effective_config)
-- Check if we have a valid terminal buffer (process running)
local has_buffer = bufnr and vim.api.nvim_buf_is_valid(bufnr)
Expand Down Expand Up @@ -416,7 +416,7 @@ end
--- Legacy toggle function for backward compatibility (defaults to simple_toggle)
--- @param cmd_string string
--- @param env_table table
--- @param effective_config TerminalConfig
--- @param effective_config ClaudeCodeTerminalConfig
function M.toggle(cmd_string, env_table, effective_config)
M.simple_toggle(cmd_string, env_table, effective_config)
end
Expand All @@ -434,5 +434,5 @@ function M.is_available()
return true -- Native provider is always available
end

--- @type TerminalProvider
--- @type ClaudeCodeTerminalProvider
return M
6 changes: 3 additions & 3 deletions lua/claudecode/terminal/snacks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ local function setup_terminal_events(term_instance, config)
end

---Builds Snacks terminal options with focus control
---@param config TerminalConfig Terminal configuration
---@param config ClaudeCodeTerminalConfig Terminal configuration
---@param env_table table Environment variables to set for the terminal process
---@param focus boolean|nil Whether to focus the terminal when opened (defaults to true)
---@return table options Snacks terminal options with start_insert/auto_insert controlled by focus parameter
Expand All @@ -69,7 +69,7 @@ end
---Open a terminal using Snacks.nvim
---@param cmd_string string
---@param env_table table
---@param config TerminalConfig
---@param config ClaudeCodeTerminalConfig
---@param focus boolean?
function M.open(cmd_string, env_table, config, focus)
if not is_available() then
Expand Down Expand Up @@ -258,5 +258,5 @@ function M._get_terminal_for_test()
return terminal
end

---@type TerminalProvider
---@type ClaudeCodeTerminalProvider
return M
117 changes: 117 additions & 0 deletions lua/claudecode/types.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---@brief [[
--- Centralized type definitions for ClaudeCode.nvim public API.
--- This module contains all user-facing types and configuration structures.
---@brief ]]
---@module 'claudecode.types'

-- Version information type
---@class ClaudeCodeVersion
---@field major integer
---@field minor integer
---@field patch integer
---@field prerelease? string
---@field string fun(self: ClaudeCodeVersion): string

-- Diff behavior configuration
---@class ClaudeCodeDiffOptions
---@field auto_close_on_accept boolean
---@field show_diff_stats boolean
---@field vertical_split boolean
---@field open_in_current_tab boolean
---@field keep_terminal_focus boolean

-- Model selection option
---@class ClaudeCodeModelOption
---@field name string
---@field value string

-- Log level type alias
---@alias ClaudeCodeLogLevel "trace"|"debug"|"info"|"warn"|"error"

-- Terminal split side positioning
---@alias ClaudeCodeSplitSide "left"|"right"

-- In-tree terminal provider names
---@alias ClaudeCodeTerminalProviderName "auto"|"snacks"|"native"

-- @ mention queued for Claude Code
---@class ClaudeCodeMention
---@field file_path string The absolute file path to mention
---@field start_line number? Optional start line (0-indexed for Claude compatibility)
---@field end_line number? Optional end line (0-indexed for Claude compatibility)
---@field timestamp number Creation timestamp from vim.loop.now() for expiry tracking

-- Terminal provider interface
---@class ClaudeCodeTerminalProvider
---@field setup fun(config: ClaudeCodeTerminalConfig)
---@field open fun(cmd_string: string, env_table: table, config: ClaudeCodeTerminalConfig, focus: boolean?)
---@field close fun()
---@field toggle fun(cmd_string: string, env_table: table, effective_config: ClaudeCodeTerminalConfig)
---@field simple_toggle fun(cmd_string: string, env_table: table, effective_config: ClaudeCodeTerminalConfig)
---@field focus_toggle fun(cmd_string: string, env_table: table, effective_config: ClaudeCodeTerminalConfig)
---@field get_active_bufnr fun(): number?
---@field is_available fun(): boolean
---@field ensure_visible? function
---@field _get_terminal_for_test fun(): table?

-- Terminal configuration
---@class ClaudeCodeTerminalConfig
---@field split_side ClaudeCodeSplitSide
---@field split_width_percentage number
---@field provider ClaudeCodeTerminalProviderName|ClaudeCodeTerminalProvider
---@field show_native_term_exit_tip boolean
---@field terminal_cmd string?
---@field auto_close boolean
---@field env table<string, string>
---@field snacks_win_opts table

-- Port range configuration
---@class ClaudeCodePortRange
---@field min integer
---@field max integer

-- Server status information
---@class ClaudeCodeServerStatus
---@field running boolean
---@field port integer?
---@field client_count integer
---@field clients? table<string, any>

-- Main configuration structure
---@class ClaudeCodeConfig
---@field port_range ClaudeCodePortRange
---@field auto_start boolean
---@field terminal_cmd string|nil
---@field env table<string, string>
---@field log_level ClaudeCodeLogLevel
---@field track_selection boolean
---@field visual_demotion_delay_ms number
---@field connection_wait_delay number
---@field connection_timeout number
---@field queue_timeout number
---@field diff_opts ClaudeCodeDiffOptions
---@field models ClaudeCodeModelOption[]
---@field disable_broadcast_debouncing? boolean
---@field enable_broadcast_debouncing_in_tests? boolean
---@field terminal ClaudeCodeTerminalConfig?

-- Server interface for main module
---@class ClaudeCodeServerFacade
---@field start fun(config: ClaudeCodeConfig, auth_token: string|nil): (success: boolean, port_or_error: number|string)
---@field stop fun(): (success: boolean, error_message: string?)
---@field broadcast fun(method: string, params: table?): boolean
---@field get_status fun(): ClaudeCodeServerStatus

-- Main module state
---@class ClaudeCodeState
---@field config ClaudeCodeConfig
---@field server ClaudeCodeServerFacade|nil
---@field port integer|nil
---@field auth_token string|nil
---@field initialized boolean
---@field mention_queue ClaudeCodeMention[]
---@field mention_timer uv.uv_timer_t? -- (compatible with vim.loop timer)
---@field connection_timer uv.uv_timer_t? -- (compatible with vim.loop timer)

-- This module only defines types, no runtime functionality
return {}