1613 lines
74 KiB
Lua
1613 lines
74 KiB
Lua
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",
|
|
-- { "stevearc/dressing.nvim", opts = {} },
|
|
},
|
|
event = "VeryLazy",
|
|
keys = {
|
|
{ "<leader>rc", "<cmd>CodeCompanionChat Toggle<cr>", mode = {'n', 'v'}, { noremap = true, silent = true }, desc = "CC Toggle" },
|
|
{ "<leader>ra", "<cmd>CodeCompanionActions<cr>", mode = { 'n', 'v' }, { noremap = true, silent = true }, desc = "CC Action" },
|
|
{ "<leader>ri", "<cmd>CodeCompanionChat Add<cr>", mode = { 'v' }, { noremap = true, silent = true }, desc = "CC Add" },
|
|
{ "<leader>re", "<cmd>CodeCompanion Explain<cr>", mode = { 'n' }, desc = "CC Explain" },
|
|
{ "<leader>rf", "<cmd>CodeCompanion Fix code<cr>", mode = { 'n' }, desc = "CC fix" },
|
|
{ '<leader>cr', '<cmd>CodeCompanion Code Review<cr>', mode = { 'v' }, desc = 'Code Review' },
|
|
{ '<leader>co', '<cmd>CodeCompanion Optimize Performance<cr>', mode = { 'v' }, desc = 'Optimize Code' },
|
|
{ '<leader>ce', '<cmd>CodeCompanion Explain Code<cr>', mode = { 'v' }, desc = 'Explain Code' },
|
|
{ '<leader>cg', '<cmd>CodeCompanion Generate Tests<cr>', mode = { 'v' }, desc = 'Generate Tests' },
|
|
{ '<leader>cd', '<cmd>CodeCompanion Debug Analysis<cr>', 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', '<git_files>')
|
|
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', '<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 = "<LocalLeader>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 = "<LocalLeader>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 = "<LocalLeader>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 = "<LocalLeader>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 = {
|
|
{
|
|
"<leader>at",
|
|
function() require("agentic").toggle() end,
|
|
mode = { "n", "v", "i" },
|
|
desc = "Toggle Agentic Chat"
|
|
},
|
|
{
|
|
"<C-'>",
|
|
function() require("agentic").add_selection_or_file_to_context() end,
|
|
mode = { "n", "v" },
|
|
desc = "Add file or selection to Agentic to Context"
|
|
},
|
|
{
|
|
"<C-,>",
|
|
function() require("agentic").new_session() end,
|
|
mode = { "n", "v", "i" },
|
|
desc = "New Agentic Session"
|
|
},
|
|
{
|
|
"<A-i>r", -- ai Restore
|
|
function()
|
|
require("agentic").restore_session()
|
|
end,
|
|
desc = "Agentic Restore session",
|
|
silent = true,
|
|
mode = { "n", "v", "i" },
|
|
},
|
|
{
|
|
"<leader>ad", -- ai Diagnostics
|
|
function()
|
|
require("agentic").add_current_line_diagnostics()
|
|
end,
|
|
desc = "Add current line diagnostic to Agentic",
|
|
mode = { "n" },
|
|
},
|
|
{
|
|
"<leader>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 = true,
|
|
keymap = {
|
|
accept_and_goto = "<leader>p",
|
|
accept = false,
|
|
dismiss = "<Esc>",
|
|
},
|
|
},
|
|
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
|
|
{ "<leader>fa", ":'<,'>Fabric<CR>", mode = "v", desc = "Fabric AI" },
|
|
{ "<leader>fa", ":Fabric<CR>", mode = "n", desc = "Fabric AI" },
|
|
{ "<leader>fu", ":Fabric url<CR>", 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 = {
|
|
{
|
|
'<leader>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', '<leader>vs', function()
|
|
gitsigns.stage_hunk { vim.fn.line '.', vim.fn.line 'v' }
|
|
end, { desc = 'stage git hunk' })
|
|
|
|
map('v', '<leader>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', '<leader>vs', gitsigns.stage_hunk, { desc = 'git stage hunk' })
|
|
map('n', '<leader>vr', gitsigns.reset_hunk, { desc = 'git reset hunk' })
|
|
map('n', '<leader>vS', gitsigns.stage_buffer, { desc = 'git stage buffer' })
|
|
map('n', '<leader>vu', gitsigns.undo_stage_hunk, { desc = 'git undo stage hunk' })
|
|
map('n', '<leader>vR', gitsigns.reset_buffer, { desc = 'git reset buffer' })
|
|
map('n', '<leader>vP', gitsigns.preview_hunk, { desc = 'git preview hunk' })
|
|
map('n', '<leader>vb', gitsigns.blame_line, { desc = 'git blame line' })
|
|
map('n', '<leader>vP', gitsigns.diffthis, { desc = 'git diff against index' })
|
|
map('n', '<leader>vD', function()
|
|
gitsigns.diffthis '@'
|
|
end, { desc = 'git [D]iff against last commit' })
|
|
-- Toggles
|
|
map('n', '<leader>uvb', gitsigns.toggle_current_line_blame, { desc = '[T]oggle git show [b]lame line' })
|
|
map('n', '<leader>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", "<leader>va", annotate.file, { desc = "JJ annotate file" })
|
|
vim.keymap.set("n", "<leader>vA", annotate.line, { desc = "JJ annotate line" })
|
|
vim.keymap.set("n", "<leader>vbc", cmd.bookmark_create, { desc = "JJ bookmark create" })
|
|
vim.keymap.set("n", "<leader>vbd", cmd.bookmark_delete, { desc = "JJ bookmark delete" })
|
|
vim.keymap.set("n", "<leader>vbm", cmd.bookmark_move, { desc = "JJ bookmark move" })
|
|
vim.keymap.set("n", "<leader>vd", cmd.describe, { desc = "JJ describe" })
|
|
vim.keymap.set("n", "<leader>vl", cmd.log, { desc = "JJ log" })
|
|
vim.keymap.set("n", "<leader>ve", cmd.edit, { desc = "JJ edit" })
|
|
vim.keymap.set("n", "<leader>vn", cmd.new, { desc = "JJ new" })
|
|
vim.keymap.set("n", "<leader>vs", cmd.status, { desc = "JJ status" })
|
|
vim.keymap.set("n", "<leader>vS", cmd.squash, { desc = "JJ squash" })
|
|
vim.keymap.set("n", "<leader>vju", cmd.undo, { desc = "JJ undo" })
|
|
vim.keymap.set("n", "<leader>vjr", cmd.redo, { desc = "JJ redo" })
|
|
vim.keymap.set("n", "<leader>vr", cmd.rebase, { desc = "JJ rebase" })
|
|
vim.keymap.set("n", "<leader>vf", cmd.fetch, { desc = "JJ fetch" })
|
|
vim.keymap.set("n", "<leader>vx", cmd.abandon, { desc = "JJ abandon" })
|
|
vim.keymap.set("n", "<leader>vp", cmd.push, { desc = "JJ push" })
|
|
vim.keymap.set("n", "<leader>vpr", cmd.open_pr, { desc = "JJ open PR from bookmark in current revision or parent" })
|
|
vim.keymap.set("n", "<leader>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", "<leader>vjd", function() diff.open_vdiff() end, { desc = "JJ diff current buffer" })
|
|
vim.keymap.set("n", "<leader>vjD", function() diff.open_hsplit() end, { desc = "JJ hdiff current buffer" })
|
|
|
|
-- Pickers
|
|
local picker = require("jj.picker")
|
|
vim.keymap.set("n", "<leader>vjs", function() picker.status() end, { desc = "JJ Picker status" })
|
|
vim.keymap.set("n", "<leader>vjh", function() picker.file_history() end, { desc = "JJ Picker history" })
|
|
|
|
-- Some functions like `log` can take parameters
|
|
vim.keymap.set("n", "<leader>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", "<leader>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", "<leader>cct", crates.toggle, { desc = 'toggle' })
|
|
vim.keymap.set("n", "<leader>ccr", crates.reload, { desc = 'reload' })
|
|
vim.keymap.set("n", "<leader>ccv", crates.show_versions_popup, { desc = 'show versions' })
|
|
vim.keymap.set("n", "<leader>ccf", crates.show_features_popup, { desc = 'show features' })
|
|
vim.keymap.set("n", "<leader>ccd", crates.show_dependencies_popup, { desc = 'show dependencies' })
|
|
vim.keymap.set("n", "<leader>ccu", crates.update_crate, { desc = 'update' })
|
|
vim.keymap.set("v", "<leader>ccu", crates.update_crates, { desc = 'update' })
|
|
vim.keymap.set("n", "<leader>cca", crates.update_all_crates, { desc = 'update all' })
|
|
vim.keymap.set("n", "<leader>ccU", crates.upgrade_crate, { desc = 'upgrade' })
|
|
vim.keymap.set("v", "<leader>ccU", crates.upgrade_crates, { desc = 'upgrade' })
|
|
vim.keymap.set("n", "<leader>ccA", crates.upgrade_all_crates, { desc = 'upgrade all' })
|
|
vim.keymap.set("n", "<leader>ccx", crates.expand_plain_crate_to_inline_table, { desc = 'expand' })
|
|
vim.keymap.set("n", "<leader>ccX", crates.extract_crate_into_table, { desc = 'extract' })
|
|
vim.keymap.set("n", "<leader>ccH", crates.open_homepage, { desc = 'open homepage' })
|
|
vim.keymap.set("n", "<leader>ccR", crates.open_repository, { desc = 'open repository' })
|
|
vim.keymap.set("n", "<leader>ccD", crates.open_documentation, { desc = 'open documents' })
|
|
vim.keymap.set("n", "<leader>ccC", crates.open_crates_io, { desc = 'open crates.io' })
|
|
vim.keymap.set("n", "<leader>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", "<leader>lr", function()
|
|
vim.cmd.RustLsp("codeAction")
|
|
end, { desc = "Code Action", buffer = bufnr })
|
|
vim.keymap.set("n", "<leader>ld", function()
|
|
vim.cmd.RustLsp("debuggables")
|
|
end, { desc = "Rust Debuggables", buffer = bufnr })
|
|
vim.keymap.set("n", "<leader>lD", function()
|
|
vim.cmd.RustLsp("openDocs")
|
|
end, { desc = "Open Documents", buffer = bufnr })
|
|
vim.keymap.set("n", "<leader>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 = {
|
|
{ "<leader>st", function() Snacks.picker.todo_comments() end, desc = "Todo" },
|
|
{ "<leader>sT", function() Snacks.picker.todo_comments({ keywords = { "TODO", "FIX", "FIXME" } }) end, desc = "Todo/Fix/Fixme" },
|
|
},
|
|
opts = {},
|
|
},
|
|
|
|
{
|
|
"mbbill/undotree",
|
|
lazy = true,
|
|
keys = {
|
|
{ '<leader>uu', vim.cmd.UndotreeToggle, desc = 'Format buffer' }
|
|
},
|
|
},
|
|
|
|
}
|
|
|