diff --git a/README.md b/README.md index 39e11c8..42072a5 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ ### lazy.nvim ```lua +---@module "lazy" +---@type LazySpec { "afewyards/codereview.nvim", dependencies = { "nvim-lua/plenary.nvim" }, @@ -62,6 +64,8 @@ "CodeReviewToggleScroll", "CodeReviewCommits", }, + ---@module "codereview" + ---@type codereview.Config opts = {}, } ``` diff --git a/lua/codereview/config.lua b/lua/codereview/config.lua index 36e5ac7..242d2b9 100644 --- a/lua/codereview/config.lua +++ b/lua/codereview/config.lua @@ -1,6 +1,65 @@ -- lua/codereview/config.lua + +---@class codereview.Config +---@field base_url? string API base URL override (auto-detected) +---@field project? string "owner/repo" override (auto-detected) +---@field platform? "github"|"gitlab" platform override (auto-detected) +---@field github_token? string GitHub personal access token +---@field gitlab_token? string GitLab personal access token +---@field picker? "telescope"|"fzf"|"snacks" picker override (auto-detected) +---@field debug? boolean debug logging to `.codereview.log` (default: `false`) +---@field open_in_tab? boolean open review in a new tab (set `false` to use current window) (default: `true`) +---@field diff? codereview.config.Diff diff viewer +---@field pipeline? codereview.config.Pipeline pipeline viewer +---@field ai? codereview.config.AI AI review +---@field keymaps? codereview.config.Keymap override or disable keybindings + +---@class codereview.config.Diff +---@field context? integer lines of context (0-20) (default: 8) +---@field scroll_threshold? integer use scroll mode when file count <= threshold (default: 50) +---@field comment_width? integer comment float width (default: 80) +---@field separator_char? string hunk separator character +---@field separator_lines? integer lines in hunk separator (default: 3) + +---@class codereview.config.Pipeline +---@field poll_interval? integer status poll interval (ms) (default: 10000) +---@field log_max_lines? integer max lines in job log viewer (default: 5000) + +---@class codereview.config.AI +---@field enabled? boolean enable AI Review (default: `true`) +---@field provider? "claude_cli"|"anthropic"|"openai"|"ollama"|"custom_cmd" AI Provider to use +---@field review_level? "info"|"suggestion"|"warning"|"error" controls the verbosity of AI code reviews (default: `info`) +---@field max_file_size? integer skip files larger than N lines (0 = unlimited) (default: 500) +---@field claude_cli? codereview.config.ai.ClaudeCli Claude CLI options +---@field anthropic? codereview.config.ai.Anthropic Anthropic API options +---@field openai? codereview.config.ai.OpenAI OpenAI API options +---@field ollama? codereview.config.ai.Ollama Ollama options +---@field custom_cmd? codereview.config.ai.CustomCmd Custom command options + +---@class codereview.config.ai.ClaudeCli +---@field cmd? string Claude CLI command (default: `claude_cli`) +---@field agent? string Claude Agent (default: `code-review`) + +---@class codereview.config.ai.Anthropic +---@field api_key? string Anthropic API key +---@field model? string Anthropic model name + +---@class codereview.config.ai.OpenAI +---@field api_key? string OpenAI API key +---@field model? string OpenAI model name +---@field base_url? string OpenAI API base URL + +---@class codereview.config.ai.Ollama +---@field model? string Ollama model name +---@field base_url? string Ollama API base URL + +---@class codereview.config.ai.CustomCmd +---@field cmd? string shell command +---@field args? string[] command-line arguments + local M = {} +---@type codereview.Config local defaults = { base_url = nil, -- API base URL override (auto-detected). Alias: gitlab_url project = nil, @@ -26,8 +85,12 @@ local defaults = { keymaps = {}, } +---@type codereview.Config? local current = nil +---@param base table +---@param override table +---@return table local function deep_merge(base, override) local result = vim.deepcopy(base) for k, v in pairs(override) do @@ -40,6 +103,8 @@ local function deep_merge(base, override) return result end +---@param c codereview.Config +---@return codereview.Config local function validate(c) c.diff.context = math.max(0, math.min(20, c.diff.context)) local valid_levels = { info = true, suggestion = true, warning = true, error = true } @@ -54,6 +119,7 @@ local function validate(c) return c end +---@param opts? codereview.Config function M.setup(opts) opts = opts or {} current = validate(deep_merge(defaults, opts)) @@ -61,16 +127,23 @@ function M.setup(opts) -- Only applies when user passed old keys without the new claude_cli sub-table local user_ai = opts.ai or {} local user_claude_cli = user_ai.claude_cli or {} + ---@diagnostic disable-next-line: undefined-field if user_ai.claude_cmd and not user_claude_cli.cmd then + ---@diagnostic disable-next-line: undefined-field current.ai.claude_cli.cmd = user_ai.claude_cmd end + ---@diagnostic disable-next-line: undefined-field if user_ai.agent and not user_claude_cli.agent then + ---@diagnostic disable-next-line: undefined-field current.ai.claude_cli.agent = user_ai.agent end -- Backward compat: gitlab_url → base_url + ---@diagnostic disable-next-line: undefined-field if current.gitlab_url and not current.base_url then + ---@diagnostic disable-next-line: undefined-field current.base_url = current.gitlab_url end + ---@diagnostic disable-next-line: undefined-field if current.token then vim.notify( "[codereview] `token` is deprecated and will NOT be used. Set `github_token` or `gitlab_token` instead.", @@ -80,6 +153,7 @@ function M.setup(opts) require("codereview.keymaps").setup(current.keymaps) end +---@return codereview.Config function M.get() return current or vim.deepcopy(defaults) end diff --git a/lua/codereview/keymaps.lua b/lua/codereview/keymaps.lua index 3aa94fb..514f759 100644 --- a/lua/codereview/keymaps.lua +++ b/lua/codereview/keymaps.lua @@ -1,5 +1,41 @@ local M = {} +---@alias codereview.keymap.Key string|false + +---@class codereview.config.Keymap +---@field next_file? codereview.keymap.Key +---@field prev_file? codereview.keymap.Key +---@field next_commit? codereview.keymap.Key +---@field prev_commit? codereview.keymap.Key +---@field move_down? codereview.keymap.Key +---@field move_up? codereview.keymap.Key +---@field select_next_note? codereview.keymap.Key +---@field select_prev_note? codereview.keymap.Key +---@field create_comment? codereview.keymap.Key +---@field create_range_comment? codereview.keymap.Key +---@field accept_suggestion? codereview.keymap.Key +---@field dismiss_suggestion? codereview.keymap.Key +---@field edit_suggestion? codereview.keymap.Key +---@field reply? codereview.keymap.Key +---@field edit_note? codereview.keymap.Key +---@field delete_note? codereview.keymap.Key +---@field react? codereview.keymap.Key +---@field toggle_resolve? codereview.keymap.Key +---@field toggle_full_file? codereview.keymap.Key +---@field dismiss_all_suggestions? codereview.keymap.Key +---@field submit? codereview.keymap.Key +---@field approve? codereview.keymap.Key +---@field refresh? codereview.keymap.Key +---@field quit? codereview.keymap.Key +---@field open_in_browser? codereview.keymap.Key +---@field merge? codereview.keymap.Key +---@field show_pipeline? codereview.keymap.Key +---@field ai_review? codereview.keymap.Key +---@field ai_review_file? codereview.keymap.Key +---@field pick_comments? codereview.keymap.Key +---@field pick_files? codereview.keymap.Key +---@field pick_commits? codereview.keymap.Key + local defaults = { next_file = { key = "]f", mode = "n", desc = "Next file" }, prev_file = { key = "[f", mode = "n", desc = "Previous file" }, @@ -49,6 +85,7 @@ end local resolved = nil +---@param user_opts? codereview.config.Keymap function M.setup(user_opts) resolved = deep_copy(defaults) if not user_opts then