return { { "Davidyz/VectorCode", version = "*", build = "uv tool upgrade vectorcode", -- This helps keeping the CLI up-to-date -- build = "pipx upgrade vectorcode", -- If you used pipx to install the CLI dependencies = { "nvim-lua/plenary.nvim" }, }, { 'j-hui/fidget.nvim', lazy = true }, { "olimorris/codecompanion.nvim", version = "^18.0.0", opts = {}, dependencies = { "nvim-lua/plenary.nvim", "nvim-treesitter/nvim-treesitter", "franco-ruggeri/codecompanion-spinner.nvim", "ravitemer/codecompanion-history.nvim", "cairijun/codecompanion-agentskills.nvim", "ttgrules/cc-adapter-copilot-cli-acp", }, event = "VeryLazy", keys = { { "rct", "CodeCompanionChat Toggle", mode = {'n', 'v'}, { noremap = true, silent = true }, desc = "CC Toggle" }, { "rca", "CodeCompanionActions", mode = { 'n', 'v' }, { noremap = true, silent = true }, desc = "CC Action" }, { "rce", "CodeCompanion Explain", mode = { 'n' }, desc = "CC Explain" }, { "rcf", "CodeCompanion Fix code", mode = { 'n' }, desc = "CC fix" }, { "rcc", "CodeCompanionChat Add", mode = { 'v' }, { noremap = true, silent = true }, desc = "CC Add" }, { 'rcr', 'CodeCompanion Code Review', mode = { 'v' }, desc = 'Code Review' }, { 'rco', 'CodeCompanion Optimize Performance', mode = { 'v' }, desc = 'Optimize Code' }, { 'rce', 'CodeCompanion Explain Code', mode = { 'v' }, desc = 'Explain Code' }, { 'rcg', 'CodeCompanion Generate Tests', mode = { 'v' }, desc = 'Generate Tests' }, { 'rcd', 'CodeCompanion Debug Analysis', mode = { 'v' }, desc = 'Debug Analysis' }, }, config = function() local function get_abacus_key() local handle = io.popen("pass show abacus.ai-api") if not handle then return "" end local result = handle:read("*a") handle:close() -- Remove trailing newline that 'pass' often adds return result:gsub("%s+", "") end local codecompanion = require("codecompanion") codecompanion.setup({ adapters = { http = { opts = { show_presets = true, show_model_choices = true, }, -- openai = function() -- return require("codecompanion.adapters").extend("openai", { -- env = { api_key = "cmd:pass show api.openai.com" } -- }) -- end, openrouter = function() return require("codecompanion.adapters").extend("openai_compatible", { env = { url = "https://openrouter.ai/api", api_key = "OPENROUTER_API_KEY", chat_url = "/v1/chat/completions", }, schema = { model = { default = "anthropic/claude-3.7-sonnet", }, }, }) end, abacus = function() return require("codecompanion.adapters").extend("openai_compatible", { name = "abacus", formatted_name = "Abacus.AI", env = { url = "https://routellm.abacus.ai/v1", -- IMPORTANT: include /v1 in the base url api_key = get_abacus_key(), chat_url = "/chat/completions" }, headers = { ["Content-Type"] = "application/json", ["Authorization"] = "Bearer ${api_key}", }, schema = { model = { order = 1, mapping = "parameters", type = "enum", desc = "The model to use for chat completions.", default = "route-llm", choices = { -- Routing Model ["route-llm"] = { opts = { desc = "Intelligent routing to best model" } }, -- OpenAI Models ["gpt-5.2"] = { opts = { has_vision = true } }, ["gpt-5.1"] = { opts = { has_vision = true } }, ["gpt-5.1-chat-latest"] = { opts = { has_vision = true } }, ["gpt-5"] = { opts = { has_vision = true } }, ["gpt-5-mini"] = { opts = { has_vision = true } }, ["gpt-5-nano"] = { opts = { has_vision = true } }, ["gpt-4o"] = { opts = { has_vision = true } }, ["gpt-4o-mini"] = { opts = { has_vision = true } }, ["o4-mini"] = { opts = { can_reason = true } }, ["o3"] = { opts = { can_reason = true } }, ["o3-pro"] = { opts = { can_reason = true } }, -- Anthropic Models ["claude-4-5-sonnet"] = { opts = { has_vision = true } }, ["claude-4-5-haiku"] = { opts = { has_vision = true } }, ["claude-4-5-opus"] = { opts = { has_vision = true } }, ["claude-3-opus"] = { opts = { has_vision = true } }, -- Google Models ["gemini-3-pro"] = { opts = { has_vision = true } }, ["gemini-3-flash"] = { opts = { has_vision = true } }, ["gemini-2.5-pro"] = { opts = { has_vision = true } }, ["gemini-2.5-flash"] = { opts = { has_vision = true } }, -- xAI Models ["grok-4-1-fast"] = {}, ["grok-4"] = {}, ["grok-code-fast-1"] = {}, -- Meta Models ["llama-4-Maverick-17B"] = {}, ["llama-3.1-405B"] = {}, ["llama-3.1-70B"] = {}, -- DeepSeek Models ["deepseek-v3.2"] = {}, ["deepseek-v3.1-Terminus"] = {}, ["deepseek-R1"] = { opts = { can_reason = true } }, -- Qwen Models ["qwen-3-Max"] = {}, ["qwen3-coder-480b-a35b-instruct"] = {}, ["qwen-3-32B"] = {}, ["qwq-32B"] = { opts = { can_reason = true } }, }, }, temperature = { order = 2, mapping = "parameters", type = "number", optional = true, default = 1.0, desc = "Controls randomness of output (0-2).", validate = function(n) return n >= 0 and n <= 2, "Must be between 0 and 2" end, }, max_tokens = { order = 3, mapping = "parameters", type = "integer", optional = true, default = nil, desc = "Maximum tokens to generate.", validate = function(n) return n > 0, "Must be greater than 0" end, }, top_p = { order = 4, mapping = "parameters", type = "number", optional = true, default = 1.0, desc = "Nucleus sampling parameter (0-1).", validate = function(n) return n >= 0 and n <= 1, "Must be between 0 and 1" end, }, }, }) end, ollama = function() return require("codecompanion.adapters").extend("ollama", { env = { url = "http://129.100.33.66:11434", }, schema = { model = { default = "qwen3.5", -- change to whatever you pulled }, }, }) end, copilot = function() return require("codecompanion.adapters").extend("copilot", { schema = { model = { default = "gpt-5-mini", -- Consistent model choice }, max_tokens = { default = 16284, } } }) end, }, acp = { opts = { show_presets = true, }, copilot_cli = function() return require("codecompanion.adapters").extend("copilot_cli", {}) end, codex = function() return require("codecompanion.adapters").extend("codex", { commands = { default = { "codex-acp" }, }, schema = { model = { default = "github-copilot/gpt-5.2-codex", }, }, defaults = { timeout = 20000, auth_method = "chatgpt", -- "openai-api-key"|"codex-api-key"|"chatgpt" }, }) end, opencode = function() return require("codecompanion.adapters").extend("codex", { commands = { default = { "opencode", "acp" }, }, schema = { model = { default = "github-copilot/gpt-5.2-codex", }, }, defaults = { timeout = 20000, auth_method = "chatgpt", -- "openai-api-key"|"codex-api-key"|"chatgpt" }, }) end, }, }, rules = { opts = { chat = { enabled = true, autoload = { "default" } }, }, }, opts = { send_code = true, log_level = "WARN", -- Change to DEBUG for troubleshooting language = "English", -- NEW: Performance improvements job_start_delay = 500, -- Reduced from default 1500ms submit_delay = 1000, -- Reduced from default 2000ms }, extensions = { spinner = {}, -- ddgr_search = { -- opts = { -- require_approval_before = false, -- }, -- }, agentskills = { opts = { { "~/Documents/ai-skills", recursive = true }, }, }, -- vectorcode = { lazy = true }, history = { lazy = true, enabled = true, opts = { keymap = "ghf", save_chat_keymap = "ghs", picker = "snacks", dir_to_save = vim.env.HOME .. "/Documents/ai-history", title_generation_opts = { adapter = "copilot", model = "gpt-5-mini", }, summary = { create_summary_keymap = "ghc", browse_summaries_keymap = "ghb", }, }, }, -- mcphub = { -- callback = "mcphub.extensions.codecompanion", -- opts = { -- make_vars = true, -- make_slash_commands = true, -- show_result_in_chat = true, -- }, -- }, }, interactions = { chat = { variables = { project = { callback = function() -- Get project files structure local files = vim.fn.systemlist("fd . -type f") return table.concat(files, "\n") end, description = "Share project structure" } }, tools = { opts = { auto_submit_errors = true, -- Send any errors to the LLM automatically? auto_submit_success = true, -- Send any successful output to the LLM automatically? system_prompt = { enabled = true, replace_main_system_prompt = false, }, default_tools = { "file_search", "read_file", "cmd_runner", -- "ddgr_search", }, }, ["fetch_enhanced"] = { callback = function(url, options) options = options or {} local max_length = options.max_length or 200000 -- 200KB default local timeout = options.timeout or 60 -- Use curl for better control local cmd = string.format( 'curl -L -s --max-time %d --user-agent "CodeCompanion-Neovim" "%s"', timeout, url ) local handle = io.popen(cmd) if not handle then return nil, "Failed to execute curl" end local result = handle:read("*a") local success = handle:close() if not success then return nil, "Curl command failed" end -- Truncate if too long if #result > max_length then result = result:sub(1, max_length) .. "\n[... truncated at " .. max_length .. " characters ...]" end return result end, opts = { requires_approval = false, } }, ["fetch_unlimited"] = { description = "Fetch a data from the web", callback = function(url, options) options = options or {} -- Use a local proxy service or direct system calls local temp_file = vim.fn.tempname() local cmd = string.format( 'wget --timeout=60 --tries=3 --output-document="%s" "%s" 2>/dev/null && cat "%s" && rm "%s"', temp_file, url, temp_file, temp_file ) local handle = io.popen(cmd) if not handle then return nil, "Failed to fetch URL" end local result = handle:read("*a") handle:close() -- Optional: Process and clean the content -- Remove excessive whitespace, clean HTML if needed -- result = result:gsub("%s+", " "):gsub("^\s+", ""):gsub("%s+$", "") return result end, opts = { requires_approval = false, description = "Fetch web content with unlimited size" } }, ["fetch"] = { description = "Fetch a webpage in a markdown format", callback = function(url, options) local cmd = string.format( 'reader -o -i none %s 2>/dev/null', url ) local handle = io.popen(cmd) if not handle then return nil, "Failed to fetch URL" end local result = handle:read("*a") handle:close() return result end, }, -- ["mcp"] = { -- Name this tool whatever you like -- -- Callback provides the necessary functions to CodeCompanion -- callback = function() -- return require("mcphub.extensions.codecompanion") -- end, -- opts = { -- -- If true, CodeCompanion will ask for approval before executing the MCP tool call -- requires_approval = true, -- -- Optional: Pass parameters like temperature to the underlying LLM if the chat strategy supports it -- temperature = 0.7 -- } -- }, groups = { ['plan'] = { description = "Planning my project and codes with enhanced web access", prompt = "Using all the ${tools} at your disposal including enhanced web fetching. Analyze the codes and use it to help me with my query. You have access to unlimited web content fetching.", tools = { "fetch", -- Backup unlimited fetch "file_search", "grep_search", "list_code_usages", "next_edit_suggestion", "read_file", "cmd_runner", }, opts = { collapse_tools = true, -- Override default fetch behavior for this group tool_config = { fetch_enhanced = { max_length = 500000, -- 500KB for planning tasks chunk_processing = true, }, }, }, }, ['research'] = { description = "Deep research with unlimited web access", prompt = "You are a research assistant with unlimited web access. Using the ${tools} fetch and analyze large documents, research papers, and comprehensive web content.", tools = { "fetch", "fetch_enhanced", "file_search", "read_file", }, opts = { collapse_tools = false, }, }, -- NEW: Add development group for coding tasks ['dev'] = { description = "Full-stack development with all necessary tools", prompt = "You are an expert full-stack developer. Use ${tools} to understand, modify, and test code. Always gather context before making changes.", tools = { "file_search", "grep_search", "fetch", "list_code_usages", "read_file", "insert_edit_into_file", "cmd_runner", "next_edit_suggestion", }, opts = { collapse_tools = true, }, }, }, }, slash_commands = { ["buffer"] = { opts = { provider = "snacks" } }, -- snacks ["file"] = { opts = { provider = "snacks" } }, -- snackes ['git_files'] = { description = 'List git files', ---@param chat CodeCompanion.Chat callback = function(chat) local handle = io.popen 'git ls-files' if handle ~= nil then local result = handle:read '*a' handle:close() chat:add_reference({ content = result }, 'git', '') return vim.notify('Git files added to the chat.') else return vim.notify('No git files available', vim.log.levels.INFO, { title = 'CodeCompanion' }) end end, opts = { contains_code = false, }, }, -- NEW: Add helpful workspace command ["workspace"] = { description = "Add workspace context", callback = function(chat) local cwd = vim.fn.getcwd() local workspace_info = string.format("Working directory: %s", cwd) -- Get project type local files = vim.fn.glob(cwd .. "/*", false, true) for _, file in ipairs(files) do local basename = vim.fn.fnamemodify(file, ":t") if basename == "package.json" then workspace_info = workspace_info .. "\nProject type: Node.js/JavaScript" break elseif basename == "Cargo.toml" then workspace_info = workspace_info .. "\nProject type: Rust" break elseif basename == "go.mod" then workspace_info = workspace_info .. "\nProject type: Go" break end end chat:add_reference({ content = workspace_info }, 'workspace', '') return vim.notify('Workspace context added.') end, opts = { contains_code = false, }, }, }, -- adapter = { name = "abacus", model = "route-llm" }, -- adapter = { name = "opencode", model = "github-copilot/gpt-5.2-codex" }, adapter = { name = "copilot", model = "gpt-5-mini" }, }, inline = { -- adapter = { name = "abacus", model = "route-llm" }, adapter = { name = "copilot", model = "gpt-5.1-codex-mini" }, }, cmd = { adapter = { name = "copilot", model = "gpt-5-mini" }, }, background = { adapter = { name = "copilot", model = "gpt-5-mini" }, }, }, prompt_library = { markdown = { dirs = { vim.fn.getcwd() .. "/.prompts", "~/.agents/prompts", }, }, ["Code Review"] = { interaction = "chat", description = "Review the selected code for improvements", opts = { mapping = "rpc", modes = { "v" }, adapter = { name = "copilot", model = "chatgpt-5.1-codex", }, }, prompts = { { role = "system", content = "You are an expert code reviewer. Analyze the code for: 1) Logic errors 2) Performance issues 3) Security vulnerabilities 4) Best practices 5) Code clarity and maintainability. Provide specific, actionable feedback.", }, { role = "user", content = function(context) local code = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line) return "Please review this code:\n\n```" .. context.filetype .. "\n" .. code .. "\n```" end, }, }, cc_keywords = { "review", "critique", "smell", "security", "vulnerability", "best practice", "maintainab" }, cc_threshold = 2, }, ["Optimize Performance"] = { interaction = "chat", description = "Get performance optimization suggestions", opts = { mapping = "rpo", modes = { "v" }, adapter = { name = "copilot", model = "chatgpt-5.2-codex", }, }, prompts = { { role = "system", content = "You are a performance optimization expert. Focus on: 1) Time complexity improvements 2) Space efficiency 3) Algorithm optimization 4) Framework-specific optimizations 5) Caching strategies.", }, { role = "user", content = function(context) local code = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line) return "How can I optimize the performance of this code?\n\n```" .. context.filetype .. "\n" .. code .. "\n```" end, }, }, cc_keywords = { "optimize", "performance", "slow", "latency", "throughput", "memory", "alloc" }, }, ["Debug Analysis"] = { interaction = "chat", description = "Analyze and debug problematic code", opts = { mapping = "rpd", modes = { "v" }, adapter = { name = "copilot", model = "chatgpt-5.2-codex", }, }, prompts = { { role = "system", content = [[You are a debugging expert. Analyze code for: 1. Potential bugs and issues 2. Logic errors 3. Runtime errors 4. Common pitfalls 5. Debugging strategies. 6. Provide specific solutions.]], }, { role = "user", content = function(context) local code = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line) return fmt( [[Help me debug this code from buffer %d and identify potential issues: ```%s %s ```]], context.bufnr, context.filetype, code ) end, opts = { contains_code = true, } }, }, cc_keyword = { "bug", "debug", "error", "exception", "crash", "stacktrace", "broken", "issue" }, }, ["Architecture Review"] = { interaction = "chat", description = "Review architectural patterns and design", opts = { mapping = "rpa", modes = { "v" }, adapter = { name = "copilot", model = "chatgpt-5.2-codex", }, }, prompts = { { role = "system", content = "You are a software architect. Review code for: 1) Design patterns usage 2) SOLID principles 3) Separation of concerns 4) Scalability considerations 5) Maintainability. Suggest architectural improvements.", }, { role = "user", content = function(context) local code = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line) return fmt( [[Please review the architecture and design of this code from buffer %d: ```%s %s ```]], context.bufnr, context.filetype, code ) end, opts = { contains_code = true, } }, }, cc_keywords = { "architecture", "design", "pattern", "solid", "scalab", "maintainab", "refactor" }, }, }, display = { action_palette = { provider = "snacks", opts = { show_default_actions = true, show_default_prompt_library = true, } }, chat = { show_settings = false, render_headers = false, icons = { chat_context = "📎️", }, fold_context = true, -- NEW: Better chat window configuration window = { layout = "vertical", width = 0.45, height = 0.8, border = "rounded", -- Better visual }, auto_scroll = false, start_in_insert_mode = false, -- More convenient } } }) end }, { "carlos-algms/agentic.nvim", opts = { -- Available by default: "claude-agent-acp" | "gemini-acp" | "codex-acp" | "opencode-acp" | "cursor-acp" | "auggie-acp" | "mistral-vibe-acp" provider = "opencode-acp", -- setting the name here is all you need to get started }, -- these are just suggested keymaps; customize as desired keys = { { "at", function() require("agentic").toggle() end, mode = { "n", "v", "i" }, desc = "Toggle Agentic Chat" }, { "", function() require("agentic").add_selection_or_file_to_context() end, mode = { "n", "v" }, desc = "Add file or selection to Agentic to Context" }, { "", function() require("agentic").new_session() end, mode = { "n", "v", "i" }, desc = "New Agentic Session" }, { "r", -- ai Restore function() require("agentic").restore_session() end, desc = "Agentic Restore session", silent = true, mode = { "n", "v", "i" }, }, { "ad", -- ai Diagnostics function() require("agentic").add_current_line_diagnostics() end, desc = "Add current line diagnostic to Agentic", mode = { "n" }, }, { "aD", -- ai all Diagnostics function() require("agentic").add_buffer_diagnostics() end, desc = "Add all buffer diagnostics to Agentic", mode = { "n" }, }, }, }, { "zbirenbaum/copilot.lua", dependencies = { "copilotlsp-nvim/copilot-lsp", config = function() vim.g.copilot_nes_debounce = 500 end, }, cmd = "Copilot", event = "InsertEnter", config = function() require('copilot').setup({ nes = { enabled = false, keymap = { accept_and_goto = "", accept = false, dismiss = "", }, }, panel = { enabled = false, }, -- suggestion = { -- enabled = false, -- }, -- filetypes = { -- -- yaml = false, -- -- markdown = false, -- help = false, -- gitcommit = false, -- gitrebase = false, -- hgcommit = false, -- svn = false, -- cvs = false, -- ["."] = false, -- }, -- copilot_node_command = 'node', -- Node.js version must be > 18.x -- copilot_model = "o4-mini-2025-04-16", -- copilot_model = "gpt-5.1-codex-mini", -- server_opts_overrides = { -- settings = { -- advanced = { -- listCount = 10, -- inlineSuggestCount = 3, -- -- model = "claude-3.5-sonnet-20241022", -- model = "o3-mini-2025-01-31", -- --model = "GPT-4o-copilot" -- } -- } -- }, }) end, }, { "PhantomYdn/fabric-ai.nvim", cmd = { "Fabric" }, opts = { -- Default configuration (all optional) fabric_path = "fabric-ai", -- Path to Fabric CLI patterns_path = nil, -- Custom patterns dir (auto-detect if nil) timeout = 300000, -- Command timeout in ms (5 minutes) window = { width = 0.8, -- 80% of editor width height = 0.8, -- 80% of editor height border = "rounded", }, }, keys = { -- fabric-ai.nvim doesn't have default keymappings { "fa", ":'<,'>Fabric", mode = "v", desc = "Fabric AI" }, { "fa", ":Fabric", mode = "n", desc = "Fabric AI" }, { "fu", ":Fabric url", mode = "n", desc = "Fabric URL" }, }, }, { 'L3MON4D3/LuaSnip', dependencies = { 'rafamadriz/friendly-snippets', }, version = "v2.*", build = "make install_jsregexp", config = function() require('luasnip.loaders.from_vscode').lazy_load() require('luasnip.loaders.from_vscode').lazy_load({ paths = "./json_snippets" }) local luasnip = require("luasnip") luasnip.add_snippets("zig", require("snippets.zig")) end, }, { 'saghen/blink.cmp', lazy = false, -- lazy loading handled internally -- optional: provides snippets for the snippet source dependencies = { 'L3MON4D3/LuaSnip', 'moyiz/blink-emoji.nvim', 'MeanderingProgrammer/render-markdown.nvim', 'fang2hou/blink-copilot', --'giuxtaposition/blink-cmp-copilot', }, version = '1.*', config = function() -- NOTE: Specify the trigger character(s) used for luasnip -- local trigger_text = ";" require('blink.cmp').setup({ enabled = function() local filetype = vim.bo[0].filetype if filetype == "TelescopePrompt" or filetype == "minifiles" or filetype == "snacks_picker_input" then return false end return true end, snippets = { preset = 'luasnip' }, completion = { -- keyword = { -- -- 'prefix' will fuzzy match on the text before the cursor -- -- 'full' will fuzzy match on the text before *and* after the cursor -- -- example: 'foo_|_bar' will match 'foo_' for 'prefix' and 'foo__bar' for 'full' -- range = "full", -- }, menu = { draw = { treesitter = { 'lsp' } } -- border = "single", }, list = { selection = { preselect = false, auto_insert = false, } }, documentation = { auto_show = true, auto_show_delay_ms = 500, -- window = { -- border = "single", -- }, }, ghost_text = { enabled = false }, }, cmdline = { enabled = true, }, signature = { enabled = true }, sources = { per_filetype = { org = {'orgmode'} }, default = { 'orgmode', 'lsp', 'copilot', 'snippets', 'path', 'omni', 'buffer', 'codecompanion', 'markdown' }, providers = { codecompanion = { name = "CodeCompanion" , module = "codecompanion.providers.completion.blink", enabled = true, }, orgmode = { name = 'Orgmode', module = 'orgmode.org.autocompletion.blink', fallbacks = { 'buffer' }, }, copilot = { name = 'copilot', module = 'blink-copilot', score_offset = 100, async = true, }, markdown = { name = 'RenderMarkdown', module = 'render-markdown.integ.blink', score_offset = 80, }, lsp = { name = 'lsp', -- IMPORTANT: use the same name as you would for nvim-cmp enabled = true, module = 'blink.cmp.sources.lsp', -- fallbacks = { 'snippets', 'buffer', 'path' }, score_offset = 100, }, path = { name = 'path', -- IMPORTANT: use the same name as you would for nvim-cmp module = 'blink.cmp.sources.path', score_offset = 50, fallbacks = { 'snippets', 'buffer' }, opts = { trailing_slash = false, label_trailing_slash = true, get_cwd = function(context) return vim.fn.expand(("#%d:p:h"):format(context.bufnr)) end, show_hidden_files_by_default = true, }, }, buffer = { name = "Buffer", enabled = true, max_items = 3, module = "blink.cmp.sources.buffer", min_keyword_length = 4, score_offset = 15, -- the higher the number, the higher the priority }, snippets = { name = "snippets", enabled = true, max_items = 15, min_keyword_length = 2, module = "blink.cmp.sources.snippets", score_offset = 90, -- the higher the number, the higher the priority }, emoji = { module = "blink-emoji", name = "Emoji", score_offset = 0, -- the higher the number, the higher the priority opts = { insert = true }, -- Insert emoji (default) or complete its name }, }, }, appearance = { -- Blink does not expose its default kind icons so you must copy them all (or set your custom ones) and add Copilot kind_icons = { Copilot = "", Text = '󰉿', Method = '󰊕', Function = '󰊕', Constructor = '󰒓', Field = '󰜢', Variable = '󰆦', Property = '󰖷', Class = '󱡠', Interface = '󱡠', Struct = '󱡠', Module = '󰅩', Unit = '󰪚', Value = '󰦨', Enum = '󰦨', EnumMember = '󰦨', Keyword = '󰻾', Constant = '󰏿', Snippet = '󱄽', Color = '󰏘', File = '󰈔', Reference = '󰬲', Folder = '󰉋', Event = '󱐋', Operator = '󰪚', TypeParameter = '󰬛', }, }, }) end }, { 'stevearc/conform.nvim', event = { 'BufWritePre' }, cmd = { 'ConformInfo' }, keys = { { 'bf', function() require('conform').format { async = true, lsp_format = 'fallback' } end, mode = { 'n', 'v' }, desc = 'Format buffer', }, }, opts = { notify_on_error = false, -- format_on_save = function(bufnr) -- -- Disable "format_on_save lsp_fallback" for languages that don't -- -- have a well standardized coding style. You can add additional -- -- languages here or re-enable it for the disabled ones. -- local disable_filetypes = { c = true, cpp = true } -- local lsp_format_opt -- if disable_filetypes[vim.bo[bufnr].filetype] then -- lsp_format_opt = 'never' -- else -- lsp_format_opt = 'fallback' -- end -- return { -- timeout_ms = 500, -- lsp_format = lsp_format_opt, -- } -- end, formatters = { shfmt = { prepend_args = { "-i", "2", "-ci" }, }, dprint = { condition = function(ctx) return vim.fs.find({ "dprint.json" }, { path = ctx.filename, upward = true })[1] end, }, }, formatters_by_ft = { lua = { 'stylua' }, go = { "goimports", "gofmt" }, rust = { "dprint", "rustfmt", lsp_format = "fallback" }, python = { "isort", "black", stop_after_first = true }, javascript = { "dprint", "prettier", stop_after_first = true }, markdown = { "dprint", "prettier", stop_after_first = true }, javascriptreact = { "dprint", "prettier", stop_after_first = true }, typescript = { "dprint", "prettier", stop_after_first = true }, typescriptreact = { "dprint", "prettier", stop_after_first = true }, svelte = { "dprint", "prettier", stop_after_first = true }, html = { "dprint", "prettier", stop_after_first = true }, }, }, }, { 'lewis6991/gitsigns.nvim', event = "VimEnter", opts = { auto_attach = false, signs_staged_enable = true, signcolumn = true, current_line_blame_opts = { delay = 50 }, on_attach = function(bufnr) local gitsigns = require('gitsigns') local function map(mode, l, r, opts) opts = opts or {} opts.buffer = bufnr vim.keymap.set(mode, l, r, opts) end -- Actions -- visual mode map('v', 'vs', function() gitsigns.stage_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'stage git hunk' }) map('v', 'vr', function() gitsigns.reset_hunk { vim.fn.line '.', vim.fn.line 'v' } end, { desc = 'reset git hunk' }) -- normal mode map('n', '[v', function() gitsigns.nav_hunk 'prev' end, { desc = 'git previous hunk' }) map('n', ']v', function() gitsigns.nav_hunk 'next' end, { desc = 'git next hunk' }) map('n', 'vs', gitsigns.stage_hunk, { desc = 'git stage hunk' }) map('n', 'vr', gitsigns.reset_hunk, { desc = 'git reset hunk' }) map('n', 'vS', gitsigns.stage_buffer, { desc = 'git stage buffer' }) map('n', 'vu', gitsigns.undo_stage_hunk, { desc = 'git undo stage hunk' }) map('n', 'vR', gitsigns.reset_buffer, { desc = 'git reset buffer' }) map('n', 'vP', gitsigns.preview_hunk, { desc = 'git preview hunk' }) map('n', 'vb', gitsigns.blame_line, { desc = 'git blame line' }) map('n', 'vP', gitsigns.diffthis, { desc = 'git diff against index' }) map('n', 'vD', function() gitsigns.diffthis '@' end, { desc = 'git [D]iff against last commit' }) -- Toggles map('n', 'uvb', gitsigns.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' }) map('n', 'uvd', gitsigns.toggle_deleted, { desc = '[T]oggle git show [D]eleted' }) end, } }, { "sindrets/diffview.nvim", }, { "NicolasGB/jj.nvim", version = "*", -- Use latest stable release -- Or from the main branch (uncomment the branch line and comment the version line) -- branch = "main", keys = function() local cmd = require("jj.cmd") local annotate = require("jj.annotate") vim.keymap.set("n", "va", annotate.file, { desc = "JJ annotate file" }) vim.keymap.set("n", "vA", annotate.line, { desc = "JJ annotate line" }) vim.keymap.set("n", "vbc", cmd.bookmark_create, { desc = "JJ bookmark create" }) vim.keymap.set("n", "vbd", cmd.bookmark_delete, { desc = "JJ bookmark delete" }) vim.keymap.set("n", "vbm", cmd.bookmark_move, { desc = "JJ bookmark move" }) vim.keymap.set("n", "vd", cmd.describe, { desc = "JJ describe" }) vim.keymap.set("n", "vl", cmd.log, { desc = "JJ log" }) vim.keymap.set("n", "ve", cmd.edit, { desc = "JJ edit" }) vim.keymap.set("n", "vn", cmd.new, { desc = "JJ new" }) vim.keymap.set("n", "vs", cmd.status, { desc = "JJ status" }) vim.keymap.set("n", "vS", cmd.squash, { desc = "JJ squash" }) vim.keymap.set("n", "vju", cmd.undo, { desc = "JJ undo" }) vim.keymap.set("n", "vjr", cmd.redo, { desc = "JJ redo" }) vim.keymap.set("n", "vr", cmd.rebase, { desc = "JJ rebase" }) vim.keymap.set("n", "vf", cmd.fetch, { desc = "JJ fetch" }) vim.keymap.set("n", "vx", cmd.abandon, { desc = "JJ abandon" }) vim.keymap.set("n", "vp", cmd.push, { desc = "JJ push" }) vim.keymap.set("n", "vpr", cmd.open_pr, { desc = "JJ open PR from bookmark in current revision or parent" }) vim.keymap.set("n", "vpl", function() cmd.open_pr { list_bookmarks = true } end, { desc = "JJ open PR listing available bookmarks" }) -- Diff commands local diff = require("jj.diff") vim.keymap.set("n", "vjd", function() diff.open_vdiff() end, { desc = "JJ diff current buffer" }) vim.keymap.set("n", "vjD", function() diff.open_hsplit() end, { desc = "JJ hdiff current buffer" }) -- Pickers local picker = require("jj.picker") vim.keymap.set("n", "vjs", function() picker.status() end, { desc = "JJ Picker status" }) vim.keymap.set("n", "vjh", function() picker.file_history() end, { desc = "JJ Picker history" }) -- Some functions like `log` can take parameters vim.keymap.set("n", "vL", function() cmd.log { revisions = "all()", -- equivalent to jj log -r :: } end, { desc = "JJ log all" }) -- This is an alias i use for moving bookmarks its so good vim.keymap.set("n", "vt", function() cmd.j "tug" cmd.log {} end, { desc = "JJ tug" }) end, config = function() require("jj").setup({ diff = { backend = "native", }, cmd = { describe = { editor = { type = "buffer", } } }, describe = { editor = { type = "buffer", } } }) end, }, { "julienvincent/hunk.nvim", cmd = { "DiffEditor" }, config = function() require("hunk").setup() end, }, { -- "PrayagS/jj-diffconflicts", -- branch = 'fix-for-jj-v0_37_0', "rafikdraoui/jj-diffconflicts" }, { 'Glhou/jjsigns.nvim', branch = 'fix/skip-extra-lines', config = function() require('jjsigns').setup({ enabled = true, attach = { auto = false, } }) end, }, { 'williamboman/mason.nvim', lazy = true, opts = {} }, { 'williamboman/mason-lspconfig.nvim', lazy = true }, { 'WhoIsSethDaniel/mason-tool-installer.nvim', lazy = true }, { 'neovim/nvim-lspconfig', dependencies = { { 'SmiteshP/nvim-navic', lazy = true }, }, config = function() vim.api.nvim_create_autocmd('LspAttach', { group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), callback = function(event) local function client_supports_method(client, method, bufnr) if vim.fn.has 'nvim-0.11' == 1 then return client:supports_method(method, bufnr) else return client.supports_method(method, { bufnr = bufnr }) end end local client = vim.lsp.get_client_by_id(event.data.client_id) if client and client:supports_method(vim.lsp.protocol.Methods.textDocument_completion, event.buf) then vim.lsp.completion.enable(true, client.id, event.buf, { autotrigger = true }) end end, }) -- Diagnostic Config -- See :help vim.diagnostic.Opts vim.diagnostic.config({ severity_sort = true, float = { border = 'rounded', source = 'if_many' }, underline = { severity = vim.diagnostic.severity.ERROR }, signs = vim.g.have_nerd_font and { text = { [vim.diagnostic.severity.ERROR] = '󰅚 ', [vim.diagnostic.severity.WARN] = '󰀪 ', [vim.diagnostic.severity.INFO] = '󰋽 ', [vim.diagnostic.severity.HINT] = '󰌶 ', }, } or {}, virtual_text = { source = 'if_many', spacing = 2, format = function(diagnostic) local diagnostic_message = { [vim.diagnostic.severity.ERROR] = diagnostic.message, [vim.diagnostic.severity.WARN] = diagnostic.message, [vim.diagnostic.severity.INFO] = diagnostic.message, [vim.diagnostic.severity.HINT] = diagnostic.message, } return diagnostic_message[diagnostic.severity] end, }, }) local servers = { lua_ls = { settings = { Lua = { runtime = { version = 'LuaJIT', }, workspace = { library = vim.api.nvim_get_runtime_file("", true), checkThirdParty = false, }, completion = { callSnippet = "Replace", }, diagnostics = { disable = { 'missing-fields' }, globals = { 'vim', 'require' }, }, }, } }, gopls = { settings = { gopls = { experimentalPostfixCompletions = true, analyses = { unusedparams = true, shadow = true, }, staticcheck = true, hints = { enabled = true, rangeVariableTypes = true, prameterNames = true, functionTypeParameters = true, constantValues = true, compositeLiteralTypes = true, compositeLiteralFields = true, assignVariableTypes = true, }, }, }, }, harper_ls = { settings = { ["harper-ls"] = { linters = { SentenceCapitalization = true, SpellCheck = true }, dialect = "Canadian" } } }, -- csharp_ls = {}, zls= {}, clangd= { settings = { ["clang"] = { cmd = { "clangd", "--background-index", "--compile-commands-dir=" .. vim.loop.cwd() .. "/build" }, } } }, ts_ls= {}, html= {}, eslint= {}, jsonls= {}, jdtls= {}, } local ensure_installed = vim.tbl_keys(servers or {}) require('mason-tool-installer').setup ({ ensure_installed = ensure_installed }) local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = vim.tbl_deep_extend('force', capabilities, require('blink.cmp').get_lsp_capabilities({}, false)) capabilities = vim.tbl_deep_extend('force', capabilities, { general = { -- dynamicRegistration = false, positionEncodings = { "utf-16" }, }, textDocument = { foldingRange = { dynamicRegistration = false, lineFoldingOnly = true } } }) for server, cfg in pairs(servers) do cfg.capabilities = vim.tbl_deep_extend('force', {}, capabilities, cfg.capabilities or {}) vim.lsp.config(server, cfg) vim.lsp.enable(server) end vim.lsp.enable("rust-analyzer", false) end }, { "rcarriga/nvim-dap-ui", dependencies = { "mfussenegger/nvim-dap", "nvim-neotest/nvim-nio" }, config = function() local dapui = require("dapui") local dap = require("dap") dapui.setup() vim.fn.sign_define("DapBreakpoint", { text = "🐞" }) dap.listeners.before.attach.dapui_config = function() dapui.open() end dap.listeners.before.launch.dapui_config = function() dapui.open() end dap.listeners.before.event_terminated.dapui_config = function() dapui.close() end dap.listeners.before.event_exited.dapui_config = function() dapui.close() end end }, { "jay-babu/mason-nvim-dap.nvim", config = function() require ('mason-nvim-dap').setup({ handlers = { function(config) -- all sources with no handler get passed here -- Keep original functionality require('mason-nvim-dap').default_setup(config) end, }, }) end, }, { "Saecki/crates.nvim", lazy = true, keys = function() local crates = require("crates") local opts = { silent = true } vim.keymap.set("n", "cct", crates.toggle, { desc = 'toggle' }) vim.keymap.set("n", "ccr", crates.reload, { desc = 'reload' }) vim.keymap.set("n", "ccv", crates.show_versions_popup, { desc = 'show versions' }) vim.keymap.set("n", "ccf", crates.show_features_popup, { desc = 'show features' }) vim.keymap.set("n", "ccd", crates.show_dependencies_popup, { desc = 'show dependencies' }) vim.keymap.set("n", "ccu", crates.update_crate, { desc = 'update' }) vim.keymap.set("v", "ccu", crates.update_crates, { desc = 'update' }) vim.keymap.set("n", "cca", crates.update_all_crates, { desc = 'update all' }) vim.keymap.set("n", "ccU", crates.upgrade_crate, { desc = 'upgrade' }) vim.keymap.set("v", "ccU", crates.upgrade_crates, { desc = 'upgrade' }) vim.keymap.set("n", "ccA", crates.upgrade_all_crates, { desc = 'upgrade all' }) vim.keymap.set("n", "ccx", crates.expand_plain_crate_to_inline_table, { desc = 'expand' }) vim.keymap.set("n", "ccX", crates.extract_crate_into_table, { desc = 'extract' }) vim.keymap.set("n", "ccH", crates.open_homepage, { desc = 'open homepage' }) vim.keymap.set("n", "ccR", crates.open_repository, { desc = 'open repository' }) vim.keymap.set("n", "ccD", crates.open_documentation, { desc = 'open documents' }) vim.keymap.set("n", "ccC", crates.open_crates_io, { desc = 'open crates.io' }) vim.keymap.set("n", "ccL", crates.open_lib_rs, { desc = 'open lib.rs' }) end, opts = { completion = { crates = { enabled = true, }, }, lsp = { enabled = true, actions = true, completion = true, hover = true, }, }, }, { 'mrcjkb/rustaceanvim', version = '^6', -- Recommended lazy = true, ft = {'rust'}, opts = { server = { default_settings = { cargo = { allFeatures = false, loadOutDirsFromCheck = true, buildScripts = { enable = true }, }, }, on_attach = function(_, bufnr) vim.keymap.set("n", "lr", function() vim.cmd.RustLsp("codeAction") end, { desc = "Code Action", buffer = bufnr }) vim.keymap.set("n", "ld", function() vim.cmd.RustLsp("debuggables") end, { desc = "Rust Debuggables", buffer = bufnr }) vim.keymap.set("n", "lD", function() vim.cmd.RustLsp("openDocs") end, { desc = "Open Documents", buffer = bufnr }) vim.keymap.set("n", "lc", function() vim.cmd.RustLsp("openCargo") end, { desc = "Open Documents", buffer = bufnr }) end, }, }, config = function(_, opts) vim.g.rustaceanvim = vim.tbl_deep_extend("keep", vim.g.rustaceanvim or {}, opts or {}) end, }, { -- Highlight, edit, and navigate code 'nvim-treesitter/nvim-treesitter', build = ':TSUpdate', dependencies = { 'nvim-treesitter/nvim-treesitter-textobjects', -- 'p00f/nvim-ts-rainbow', }, config = function() require('nvim-treesitter.configs').setup({ -- Add languages to be installed here that you want installed for treesitter ensure_installed = { 'c', "lua", "markdown", "markdown_inline", "vim", "vimdoc", "query", "html", "go", "bash", "zig", "typescript", "javascript", "dockerfile", "xml", "regex", "rust" }, ignore_install = { 'org' }, auto_install = true, -- disable = function(lang, buf) -- local max_filesize = 100 * 1024 -- local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buff_get_name(buf)) -- if ok and stats and stats.size > max_filesize then -- return true -- end -- end, highlight = { enable = true, }, indent = { enable = true }, }) end, }, { 'JoosepAlviste/nvim-ts-context-commentstring', lazy = true, opts = { enable_autocmd = false, } }, { 'nvim-treesitter/nvim-treesitter-context', enabled = true, opts = { mode = "cursor", max_lines = 3 }, }, { "folke/todo-comments.nvim", lazy = true, keys = { { "st", function() Snacks.picker.todo_comments() end, desc = "Todo" }, { "sT", function() Snacks.picker.todo_comments({ keywords = { "TODO", "FIX", "FIXME" } }) end, desc = "Todo/Fix/Fixme" }, }, opts = {}, }, { "mbbill/undotree", lazy = true, keys = { { 'uu', vim.cmd.UndotreeToggle, desc = 'Format buffer' } }, }, }