Files
dotfiles/config/nvim/lua/plugins/ide.lua
T
2026-03-18 01:13:05 -04:00

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' }
},
},
}