feat(ui): modernize nvim with fzf-lua, snacks dashboard, and p10k-style statusline

- Replace Snacks picker with fzf-lua for LSP navigation (gd, gr, gi, gt)
- Add fzf-lua plugin with LSP-optimized settings
- Fix Mason inconsistencies (add eslint, gopls to ensure_installed)
- Replace alpha-nvim with Snacks dashboard (shared config)
- Create dashboard_config.lua for DRY dashboard settings
- Modernize lualine with p10k-rainbow style and solid backgrounds
- Enhance bufferline with LSP diagnostics and modern styling
- Update noice with centered cmdline/search and modern icons
- Add global rounded borders for floating windows
- Improve indent-blankline with scope highlighting
- Add return-to-dashboard on last buffer close
- Create performance_monitor module

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-12 18:59:46 -05:00
parent 2382297a6d
commit 89cba7056e
14 changed files with 998 additions and 224 deletions

4
.gitignore vendored
View File

@@ -24,3 +24,7 @@ session.vim
# Local configuration overrides
local.lua
# Codetyper.nvim - AI coding partner files
*.coder.*
.coder/

View File

@@ -0,0 +1,66 @@
-- Shared dashboard configuration for alpha-nvim and snacks.dashboard
local M = {}
M.header = {
" ██████╗ █████╗ ██████╗ ██████╗ ██████╗ ███████╗██╗ ██╗ ",
" █╔════╝██╔══██╗██╔══██╗██╔════╝ ██╔══██╗██╔════╝██║ ██║ ",
" █║ ███████║██████╔╝██║ ███╗██║ ██║█████╗ ██║ ██║ ",
" █║ ██╔══██║██╔══██╗██║ ██║██║ ██║██╔══╝ ╚██╗ ██╔╝ ",
" ██████╗██║ ██║██║ ██║╚██████╔╝██████╔╝███████╗ ╚████╔╝ ",
" ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═══╝ ",
" ",
" ███╗ ██╗███████╗ ██████╗ ██╗ ██╗██╗███╗ ███╗ ",
" ████╗ ██║██╔════╝██╔═══██╗██║ ██║██║████╗ ████║ ",
" ██╔██╗ ██║█████╗ ██║ ██║██║ ██║██║██╔████╔██║ ",
" ██║╚██╗██║██╔══╝ ██║ ██║╚██╗ ██╔╝██║██║╚██╔╝██║ ",
" ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║ ",
" ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═══╝ ╚═╝╚═╝ ╚═╝ ",
}
-- Menu items (single column)
M.menu_items = {
{ key = "f", icon = " ", desc = "Find File", action = ":FzfLua files" },
{ key = "n", icon = " ", desc = "New File", action = ":ene | startinsert" },
{ key = "g", icon = " ", desc = "Find Text", action = ":FzfLua live_grep" },
{ key = "r", icon = " ", desc = "Recent Files", action = ":FzfLua oldfiles" },
{ key = "t", icon = " ", desc = "File Tree", action = ":NvimTreeToggle" },
{ key = "L", icon = "󰒲 ", desc = "Lazy", action = ":Lazy" },
{ key = "m", icon = " ", desc = "Mason", action = ":Mason" },
{ key = "q", icon = " ", desc = "Quit", action = ":qa" },
}
-- Get header as string (for snacks)
function M.get_header_string()
return table.concat(M.header, "\n")
end
-- Helper to convert menu items to snacks format
local function to_snacks_keys(items)
local keys = {}
for _, item in ipairs(items) do
table.insert(keys, {
icon = item.icon,
key = item.key,
desc = item.desc,
action = item.action,
})
end
return keys
end
-- Get snacks dashboard keys format
function M.get_snacks_keys()
return to_snacks_keys(M.menu_items)
end
-- Get alpha buttons (requires alpha dashboard module)
function M.get_alpha_buttons(dashboard)
local buttons = {}
for _, item in ipairs(M.menu_items) do
local cmd = item.action:gsub("^:", "<cmd>") .. "<CR>"
table.insert(buttons, dashboard.button(item.key, item.icon .. " " .. item.desc, cmd))
end
return buttons
end
return M

View File

@@ -0,0 +1,112 @@
local M = {}
-- Check overall Neovim performance
function M.check_performance()
local stats = {}
-- Startup time
stats.startup = vim.fn.reltimefloat(vim.fn.reltime(vim.g.start_time or vim.fn.reltime()))
-- Memory usage
local mem = collectgarbage("count")
stats.memory_kb = math.floor(mem)
stats.memory_mb = string.format("%.2f", mem / 1024)
-- Buffer count
stats.buffers = #vim.fn.getbufinfo({ buflisted = 1 })
-- Loaded plugins (lazy.nvim)
local lazy_ok, lazy = pcall(require, "lazy")
if lazy_ok then
local lazy_stats = lazy.stats()
stats.plugins_loaded = lazy_stats.loaded
stats.plugins_total = lazy_stats.count
stats.startup_ms = string.format("%.2f", lazy_stats.startuptime)
end
-- Active LSP clients
stats.lsp_clients = #vim.lsp.get_clients()
-- Display results
local lines = {
"Performance Stats",
string.rep("-", 40),
string.format("Memory Usage: %s MB (%d KB)", stats.memory_mb, stats.memory_kb),
string.format("Open Buffers: %d", stats.buffers),
string.format("Active LSP Clients: %d", stats.lsp_clients),
}
if stats.plugins_loaded then
table.insert(lines, string.format("Plugins: %d/%d loaded", stats.plugins_loaded, stats.plugins_total))
table.insert(lines, string.format("Startup Time: %s ms", stats.startup_ms))
end
vim.notify(table.concat(lines, "\n"), vim.log.levels.INFO, { title = "Performance" })
end
-- Check LSP health for current buffer
function M.check_lsp_health()
local clients = vim.lsp.get_clients({ bufnr = 0 })
if #clients == 0 then
vim.notify("No LSP clients attached to this buffer", vim.log.levels.WARN, { title = "LSP Health" })
return
end
local lines = {
"LSP Health Report",
string.rep("-", 40),
}
for _, client in ipairs(clients) do
table.insert(lines, "")
table.insert(lines, string.format("Client: %s (id: %d)", client.name, client.id))
table.insert(lines, string.format(" Root: %s", client.config.root_dir or "N/A"))
-- Check capabilities
local caps = {}
if client.server_capabilities.completionProvider then
table.insert(caps, "completion")
end
if client.server_capabilities.hoverProvider then
table.insert(caps, "hover")
end
if client.server_capabilities.definitionProvider then
table.insert(caps, "definition")
end
if client.server_capabilities.referencesProvider then
table.insert(caps, "references")
end
if client.server_capabilities.documentFormattingProvider then
table.insert(caps, "formatting")
end
if client.server_capabilities.codeActionProvider then
table.insert(caps, "code_actions")
end
table.insert(lines, string.format(" Capabilities: %s", table.concat(caps, ", ")))
end
-- Diagnostics summary
local diagnostics = vim.diagnostic.get(0)
local counts = { errors = 0, warnings = 0, hints = 0, info = 0 }
for _, d in ipairs(diagnostics) do
if d.severity == vim.diagnostic.severity.ERROR then
counts.errors = counts.errors + 1
elseif d.severity == vim.diagnostic.severity.WARN then
counts.warnings = counts.warnings + 1
elseif d.severity == vim.diagnostic.severity.HINT then
counts.hints = counts.hints + 1
elseif d.severity == vim.diagnostic.severity.INFO then
counts.info = counts.info + 1
end
end
table.insert(lines, "")
table.insert(lines, string.format("Diagnostics: %d errors, %d warnings, %d hints, %d info",
counts.errors, counts.warnings, counts.hints, counts.info))
vim.notify(table.concat(lines, "\n"), vim.log.levels.INFO, { title = "LSP Health" })
end
return M

View File

@@ -2,26 +2,26 @@
local keymap = vim.keymap
-- =============================================================================
-- LSP NAVIGATION (FUNCTION NAVIGATION)
-- LSP NAVIGATION (FUNCTION NAVIGATION) - Using fzf-lua
-- =============================================================================
-- Primary LSP navigation
keymap.set("n", "gd", "<cmd>lua require('snacks.picker').lsp_definitions()<cr>", { desc = "Go to definition" })
keymap.set("n", "gi", "<cmd>lua require('snacks.picker').lsp_implementations()<cr>", { desc = "Go to implementation" })
keymap.set("n", "gr", "<cmd>lua require('snacks.picker').lsp_references()<cr>", { desc = "Show references" })
keymap.set("n", "gt", "<cmd>lua require('snacks.picker').lsp_type_definitions()<cr>", { desc = "Go to type definition" })
keymap.set("n", "gd", "<cmd>FzfLua lsp_definitions<cr>", { desc = "Go to definition" })
keymap.set("n", "gi", "<cmd>FzfLua lsp_implementations<cr>", { desc = "Go to implementation" })
keymap.set("n", "gr", "<cmd>FzfLua lsp_references<cr>", { desc = "Show references" })
keymap.set("n", "gt", "<cmd>FzfLua lsp_typedefs<cr>", { desc = "Go to type definition" })
-- Symbol search
keymap.set("n", "<leader>ds", "<cmd>lua require('snacks.picker').lsp_document_symbols()<cr>", { desc = "Document symbols" })
keymap.set("n", "<leader>ws", "<cmd>lua require('snacks.picker').lsp_workspace_symbols()<cr>", { desc = "Workspace symbols" })
keymap.set("n", "<leader>ds", "<cmd>FzfLua lsp_document_symbols<cr>", { desc = "Document symbols" })
keymap.set("n", "<leader>ws", "<cmd>FzfLua lsp_workspace_symbols<cr>", { desc = "Workspace symbols" })
-- Code actions and documentation
keymap.set("n", "<leader>ca", "<cmd>lua vim.lsp.buf.code_action()<cr>", { desc = "Code actions" })
keymap.set("n", "<leader>ca", "<cmd>FzfLua lsp_code_actions<cr>", { desc = "Code actions" })
keymap.set("n", "<leader>rn", "<cmd>lua vim.lsp.buf.rename()<cr>", { desc = "Rename" })
keymap.set("n", "K", "<cmd>lua vim.lsp.buf.hover()<cr>", { desc = "Hover documentation" })
-- Diagnostics
keymap.set("n", "<leader>D", "<cmd>lua require('snacks.picker').diagnostics()<cr>", { desc = "Show diagnostics" })
keymap.set("n", "<leader>D", "<cmd>FzfLua diagnostics_workspace<cr>", { desc = "Show diagnostics" })
keymap.set("n", "<leader>dd", "<cmd>lua vim.diagnostic.open_float()<cr>", { desc = "Line diagnostics" })
keymap.set("n", "[d", "<cmd>lua vim.diagnostic.goto_prev()<cr>", { desc = "Previous diagnostic" })
keymap.set("n", "]d", "<cmd>lua vim.diagnostic.goto_next()<cr>", { desc = "Next diagnostic" })

View File

@@ -242,3 +242,57 @@ vim.api.nvim_create_autocmd("FileType", {
end
end,
})
-- =============================================================================
-- RETURN TO DASHBOARD ON LAST BUFFER CLOSE
-- =============================================================================
-- When closing the last buffer, return to dashboard instead of quitting
vim.api.nvim_create_autocmd("BufDelete", {
callback = function()
local bufs = vim.tbl_filter(function(b)
return vim.api.nvim_buf_is_valid(b)
and vim.bo[b].buflisted
and vim.api.nvim_buf_get_name(b) ~= ""
end, vim.api.nvim_list_bufs())
-- If this is the last listed buffer, open dashboard
if #bufs <= 1 then
vim.schedule(function()
local ok, snacks = pcall(require, "snacks")
if ok and snacks.dashboard then
snacks.dashboard()
end
end)
end
end,
})
-- =============================================================================
-- MODERN UI: GLOBAL ROUNDED BORDERS
-- =============================================================================
-- Rounded border style for all floating windows
local border = "rounded"
-- Override default floating window border
vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { border = border })
vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, { border = border })
-- Diagnostic floating window border
vim.diagnostic.config({
float = {
border = border,
source = "always",
header = "",
prefix = "",
},
})
-- Set global float border highlight
vim.api.nvim_set_hl(0, "FloatBorder", { fg = "#7aa2f7", bg = "NONE" })
vim.api.nvim_set_hl(0, "NormalFloat", { bg = "#1a1b26" })
-- Modern cursor line (subtle highlight)
vim.api.nvim_set_hl(0, "CursorLine", { bg = "#292e42" })
vim.api.nvim_set_hl(0, "CursorLineNr", { fg = "#7aa2f7", bold = true })

View File

@@ -1,56 +1,24 @@
return {
"goolord/alpha-nvim",
event = "VimEnter",
enabled = true,
enabled = false, -- Replaced by Snacks dashboard
config = function()
local alpha = require("alpha")
local dashboard = require("alpha.themes.dashboard")
local config = require("cargdev.core.dashboard_config")
-- 🚀 Set header
dashboard.section.header.val = {
" ██████╗ █████╗ ██████╗ ██████╗ ██████╗ ███████╗██╗ ██╗ ",
" █╔════╝██╔══██╗██╔══██╗██╔════╝ ██╔══██╗██╔════╝██║ ██║ ",
" █║ ███████║██████╔╝██║ ███╗██║ ██║█████╗ ██║ ██║ ",
" █║ ██╔══██║██╔══██╗██║ ██║██║ ██║██╔══╝ ╚██╗ ██╔╝ ",
" ██████╗██║ ██║██║ ██║╚██████╔╝██████╔╝███████╗ ╚████╔╝ ",
" ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═══╝ ",
" ",
" ",
" ███╗ ██╗███████╗ ██████╗ ██╗ ██╗██╗███╗ ███╗ ",
" ████╗ ██║██╔════╝██╔═══██╗██║ ██║██║████╗ ████║ ",
" ██╔██╗ ██║█████╗ ██║ ██║██║ ██║██║██╔████╔██╗ ",
" ██║╚██╗██║██╔══╝ ██║ ██║╚██╗ ██╔╝██║██║╚██╔╝██║ ",
" ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║ ",
" ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═══╝ ╚═╝╚═╝ ╚═╝ ",
" ",
" ",
" 🚀 Welcome to CarGDev Neovim - Customize Your Flow! 🚀 ",
}
-- Set header from shared config
dashboard.section.header.val = config.header
-- 📂 Set menu with improved icons and performance tools
dashboard.section.buttons.val = {
dashboard.button("f", "🔎 Find File (Safe)", "<cmd>Telescope find_files<CR>"),
dashboard.button("n", "📄 New File", "<cmd>ene<CR>"),
dashboard.button("g", "📝 Find Text", "<cmd>Telescope live_grep<CR>"),
dashboard.button("r", "📚 Recent Files", "<cmd>Telescope oldfiles<CR>"),
dashboard.button("t", "🌳 File Tree", "<cmd>NvimTreeToggle<CR>"),
dashboard.button("c", "⚙️ Config", "<cmd>e ~/.config/nvim/init.lua<CR>"),
dashboard.button("L", "🦥 Lazy", "<cmd>Lazy<CR>"),
dashboard.button("p", "📊 Performance", "<cmd>lua require('cargdev.core.function.performance_monitor').check_performance()<CR>"),
dashboard.button("l", "🔧 LSP Health", "<cmd>lua require('cargdev.core.function.performance_monitor').check_lsp_health()<CR>"),
dashboard.button("s", "🧩 Sudoku", "<cmd>Sudoku<CR>"),
dashboard.button("e", "💻 LeetCode", "<cmd>Leet<CR>"),
dashboard.button("m", "🔨 Mason", "<cmd>Mason<CR>"),
dashboard.button("q", "🚪 Quit", "<cmd>qa<CR>"),
}
-- Set menu from shared config
dashboard.section.buttons.val = config.get_alpha_buttons(dashboard)
-- 🎯 Function to center text within a width
-- Footer with fortune
local function center_text(text, width)
local padding = math.floor((width - #text) / 2)
return padding > 0 and string.rep(" ", padding) .. text or text
end
-- 📌 Function to wrap text at a specific width
local function wrap_text(text, width)
local wrapped_lines = {}
for line in text:gmatch("[^\n]+") do
@@ -64,48 +32,19 @@ return {
return wrapped_lines
end
-- 🖥 Set viewport width (adjust if necessary)
local viewport_width = 50
-- 📝 Get a fortune quote and wrap it
local handle = io.popen("fortune")
local quote = handle and handle:read("*a") or "💻 Code, Create, Conquer with CarGDev 🚀"
if handle then
handle:close()
end
local quote = handle and handle:read("*a") or "Code, Create, Conquer with CarGDev"
if handle then handle:close() end
local wrapped_quote = wrap_text(quote:gsub("\n", " "), viewport_width)
-- 📝 Set the footer content with added spacing
dashboard.section.footer.val = {
"",
center_text("🔧 CarGDev - Innovating with Neovim! 🔧", viewport_width),
"",
}
-- Add wrapped quote below separator
dashboard.section.footer.val = { "", center_text("CarGDev - Innovating with Neovim!", viewport_width), "" }
for _, line in ipairs(wrapped_quote) do
table.insert(dashboard.section.footer.val, line)
end
-- Add branding line at the bottom
table.insert(dashboard.section.footer.val, "")
table.insert(
dashboard.section.footer.val,
center_text("🎯 Stay productive & code with passion! 🚀", viewport_width)
)
table.insert(dashboard.section.footer.val, "")
-- 🌈 Apply modern styling
dashboard.opts.opts = {
position = "center",
hl = "Statement",
spacing = 2,
}
-- 🚀 Load dashboard config
dashboard.opts.opts = { position = "center", hl = "Statement", spacing = 2 }
alpha.setup(dashboard.opts)
-- 🔥 Disable folding on alpha buffer
vim.cmd([[autocmd FileType alpha setlocal nofoldenable]])
end,
}

View File

@@ -54,21 +54,31 @@ return {
"stevearc/dressing.nvim", -- Load after dressing to override it
},
config = function()
local dashboard_config = require("cargdev.core.dashboard_config")
require("snacks").setup({
-- Enable all snacks modules
bigfile = { enabled = true },
dashboard = {
enabled = false, -- Disabled: using alpha-nvim for CARGDEV branding
enabled = true,
width = 60,
row = nil,
col = nil,
pane_gap = 4,
autokeys = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
preset = {
keys = dashboard_config.get_snacks_keys(),
header = dashboard_config.get_header_string(),
},
sections = {
{ section = "header" },
{ padding = 1 },
{ section = "keys", gap = 1, padding = 1 },
{ section = "startup" },
},
},
explorer = { enabled = true },
image = {
enabled = true,
-- Auto-detect terminal (will try: kitty, wezterm, ghostty in order)
-- If none found, image rendering will be disabled with warnings
-- Note: LaTeX and Mermaid features require external tools:
-- - LaTeX: tectonic or pdflatex
-- - Mermaid: mmdc (Mermaid CLI)
-- These warnings are informational and won't prevent basic image rendering
terminal = nil, -- nil = auto-detect
},
input = { enabled = true },
@@ -83,7 +93,7 @@ return {
toggle = { enabled = true },
words = {
enabled = true,
lsp = { enabled = false }, -- Disable LSP to prevent crashes
lsp = { enabled = false },
hl = { enabled = true },
},
})

View File

@@ -1,11 +1,313 @@
return {
"akinsho/bufferline.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
version = "*",
opts = {
event = "VeryLazy",
config = function()
local bufferline = require("bufferline")
bufferline.setup({
options = {
mode = "tabs",
mode = "buffers",
style_preset = bufferline.style_preset.minimal,
themable = true,
numbers = "none",
close_command = "bdelete! %d",
right_mouse_command = "bdelete! %d",
left_mouse_command = "buffer %d",
middle_mouse_command = nil,
indicator = {
icon = "",
style = "icon",
},
buffer_close_icon = "󰅖",
modified_icon = "",
close_icon = "",
left_trunc_marker = "",
right_trunc_marker = "",
max_name_length = 30,
max_prefix_length = 30,
truncate_names = true,
tab_size = 21,
diagnostics = "nvim_lsp",
diagnostics_update_in_insert = false,
diagnostics_indicator = function(count, level, _, _)
local icon = level:match("error") and " " or " "
return " " .. icon .. count
end,
color_icons = true,
show_buffer_icons = true,
show_buffer_close_icons = true,
show_close_icon = true,
show_tab_indicators = true,
show_duplicate_prefix = true,
persist_buffer_sort = true,
separator_style = "thin",
enforce_regular_tabs = false,
always_show_bufferline = true,
hover = {
enabled = true,
delay = 200,
reveal = { "close" },
},
offsets = {
{
filetype = "NvimTree",
text = " File Explorer",
text_align = "center",
separator = true,
highlight = "Directory",
},
},
},
highlights = {
fill = {
bg = "#16161e",
},
background = {
fg = "#565f89",
bg = "#16161e",
},
tab = {
fg = "#565f89",
bg = "#16161e",
},
tab_selected = {
fg = "#c0caf5",
bg = "#1a1b26",
},
tab_separator = {
fg = "#16161e",
bg = "#16161e",
},
tab_separator_selected = {
fg = "#1a1b26",
bg = "#1a1b26",
},
buffer_visible = {
fg = "#565f89",
bg = "#16161e",
},
buffer_selected = {
fg = "#c0caf5",
bg = "#1a1b26",
bold = true,
italic = false,
},
numbers = {
fg = "#565f89",
bg = "#16161e",
},
numbers_visible = {
fg = "#565f89",
bg = "#16161e",
},
numbers_selected = {
fg = "#c0caf5",
bg = "#1a1b26",
bold = true,
italic = false,
},
diagnostic = {
fg = "#565f89",
bg = "#16161e",
},
diagnostic_visible = {
fg = "#565f89",
bg = "#16161e",
},
diagnostic_selected = {
fg = "#c0caf5",
bg = "#1a1b26",
bold = true,
italic = false,
},
hint = {
fg = "#1abc9c",
bg = "#16161e",
},
hint_visible = {
fg = "#1abc9c",
bg = "#16161e",
},
hint_selected = {
fg = "#1abc9c",
bg = "#1a1b26",
bold = true,
italic = false,
},
hint_diagnostic = {
fg = "#1abc9c",
bg = "#16161e",
},
hint_diagnostic_visible = {
fg = "#1abc9c",
bg = "#16161e",
},
hint_diagnostic_selected = {
fg = "#1abc9c",
bg = "#1a1b26",
bold = true,
italic = false,
},
info = {
fg = "#0db9d7",
bg = "#16161e",
},
info_visible = {
fg = "#0db9d7",
bg = "#16161e",
},
info_selected = {
fg = "#0db9d7",
bg = "#1a1b26",
bold = true,
italic = false,
},
info_diagnostic = {
fg = "#0db9d7",
bg = "#16161e",
},
info_diagnostic_visible = {
fg = "#0db9d7",
bg = "#16161e",
},
info_diagnostic_selected = {
fg = "#0db9d7",
bg = "#1a1b26",
bold = true,
italic = false,
},
warning = {
fg = "#e0af68",
bg = "#16161e",
},
warning_visible = {
fg = "#e0af68",
bg = "#16161e",
},
warning_selected = {
fg = "#e0af68",
bg = "#1a1b26",
bold = true,
italic = false,
},
warning_diagnostic = {
fg = "#e0af68",
bg = "#16161e",
},
warning_diagnostic_visible = {
fg = "#e0af68",
bg = "#16161e",
},
warning_diagnostic_selected = {
fg = "#e0af68",
bg = "#1a1b26",
bold = true,
italic = false,
},
error = {
fg = "#f7768e",
bg = "#16161e",
},
error_visible = {
fg = "#f7768e",
bg = "#16161e",
},
error_selected = {
fg = "#f7768e",
bg = "#1a1b26",
bold = true,
italic = false,
},
error_diagnostic = {
fg = "#f7768e",
bg = "#16161e",
},
error_diagnostic_visible = {
fg = "#f7768e",
bg = "#16161e",
},
error_diagnostic_selected = {
fg = "#f7768e",
bg = "#1a1b26",
bold = true,
italic = false,
},
modified = {
fg = "#e0af68",
bg = "#16161e",
},
modified_visible = {
fg = "#e0af68",
bg = "#16161e",
},
modified_selected = {
fg = "#e0af68",
bg = "#1a1b26",
},
duplicate_selected = {
fg = "#c0caf5",
bg = "#1a1b26",
italic = true,
},
duplicate_visible = {
fg = "#565f89",
bg = "#16161e",
italic = true,
},
duplicate = {
fg = "#565f89",
bg = "#16161e",
italic = true,
},
separator_selected = {
fg = "#16161e",
bg = "#1a1b26",
},
separator_visible = {
fg = "#16161e",
bg = "#16161e",
},
separator = {
fg = "#16161e",
bg = "#16161e",
},
indicator_selected = {
fg = "#7aa2f7",
bg = "#1a1b26",
},
indicator_visible = {
fg = "#16161e",
bg = "#16161e",
},
pick_selected = {
fg = "#f7768e",
bg = "#1a1b26",
bold = true,
italic = false,
},
pick_visible = {
fg = "#f7768e",
bg = "#16161e",
bold = true,
italic = false,
},
pick = {
fg = "#f7768e",
bg = "#16161e",
bold = true,
italic = false,
},
offset_separator = {
fg = "#16161e",
bg = "#16161e",
},
trunc_marker = {
fg = "#565f89",
bg = "#16161e",
},
},
})
end,
}

View File

@@ -1,5 +1,7 @@
return {
"CarGDev/codetyper.nvim",
-- Codetyper.nvim - AI-powered coding partner
-- Local development version
dir = "/Volumes/Carlos_SSD/Documents/projects/nvim.plugins/codetyper.nvim",
name = "codetyper.nvim",
lazy = false, -- Load on startup to create .coder folder
priority = 100, -- Load early
@@ -44,7 +46,7 @@ return {
provider = "ollama",
ollama = {
host = "http://localhost:11434",
model = "qwen3-coder:30b",
model = "deepseek-coder:6.7b",
},
},
window = {
@@ -59,6 +61,7 @@ return {
},
auto_gitignore = true,
auto_open_ask = false, -- Always open Ask panel on startup
agent_mode = false,
})
end,
}

View File

@@ -0,0 +1,39 @@
return {
"ibhagwan/fzf-lua",
dependencies = { "nvim-tree/nvim-web-devicons" },
config = function()
local fzf = require("fzf-lua")
fzf.setup({
"default",
winopts = {
height = 0.85,
width = 0.80,
row = 0.35,
col = 0.50,
border = "rounded",
preview = {
layout = "flex",
flip_columns = 120,
scrollbar = "float",
},
},
keymap = {
builtin = {
["<C-d>"] = "preview-page-down",
["<C-u>"] = "preview-page-up",
},
fzf = {
["ctrl-q"] = "select-all+accept",
},
},
lsp = {
async_or_timeout = 5000,
jump_to_single_result = true,
ignore_current_line = true,
},
diagnostics = {
severity_limit = vim.diagnostic.severity.HINT,
},
})
end,
}

View File

@@ -2,17 +2,61 @@ return {
"lukas-reineke/indent-blankline.nvim",
event = { "BufReadPre", "BufNewFile" },
main = "ibl",
opts = {
config = function()
local hooks = require("ibl.hooks")
-- Rainbow indent colors (subtle)
hooks.register(hooks.type.HIGHLIGHT_SETUP, function()
vim.api.nvim_set_hl(0, "IblIndent", { fg = "#292e42" })
vim.api.nvim_set_hl(0, "IblScope", { fg = "#7aa2f7" })
vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#3b3052" })
vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#3b3939" })
vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#2a3a52" })
vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#3b3339" })
vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#2a3b39" })
vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#3a2a52" })
vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#2a3b4a" })
end)
require("ibl").setup({
indent = {
char = "",
},
exclude = {
filetypes = { "help", "alpha", "dashboard", "neo-tree", "Trouble", "lazy", "mason" },
buftypes = { "terminal", "nofile", "quickfix", "prompt" },
char = "",
tab_char = "",
highlight = "IblIndent",
},
scope = {
enabled = false
enabled = true,
show_start = false,
show_end = false,
highlight = "IblScope",
include = {
node_type = {
["*"] = { "return_statement", "table_constructor" },
lua = { "return_statement", "table_constructor", "function", "if_statement" },
python = { "function_definition", "class_definition", "if_statement", "for_statement" },
javascript = { "function_declaration", "arrow_function", "if_statement", "for_statement" },
typescript = { "function_declaration", "arrow_function", "if_statement", "for_statement" },
},
},
},
exclude = {
filetypes = {
"help",
"alpha",
"dashboard",
"snacks_dashboard",
"neo-tree",
"NvimTree",
"Trouble",
"trouble",
"lazy",
"mason",
"notify",
"toggleterm",
"lazyterm",
},
buftypes = { "terminal", "nofile", "quickfix", "prompt" },
},
})
end,
}

View File

@@ -27,17 +27,19 @@ return {
mason_lspconfig.setup({
-- list of servers for mason to install
ensure_installed = {
"ts_ls",
"html",
"cssls",
"tailwindcss",
"svelte",
"lua_ls",
"graphql",
"emmet_ls",
"eslint",
"gopls",
"graphql",
"html",
"jdtls",
"lua_ls",
"prismals",
"pyright",
"jdtls",
"svelte",
"tailwindcss",
"ts_ls",
},
})

View File

@@ -3,114 +3,150 @@ return {
dependencies = { "nvim-tree/nvim-web-devicons" },
config = function()
local lualine = require("lualine")
local lazy_status = require("lazy.status") -- to configure lazy pending updates count
local lazy_status = require("lazy.status")
-- Rainbow colors similar to p10k-rainbow
local colors = {
blue = "#65D1FF",
green = "#3EFFDC",
violet = "#FF61EF",
yellow = "#FFDA7B",
red = "#FF4A4A",
fg = "#c3ccdc",
bg = "#112638",
inactive_bg = "#2c3043",
blue = "#61afef",
cyan = "#56b6c2",
green = "#98c379",
magenta = "#c678dd",
orange = "#d19a66",
red = "#e06c75",
yellow = "#e5c07b",
fg = "#abb2bf",
bg = "#282c34",
bg_dark = "#21252b",
white = "#ffffff",
black = "#000000",
}
local my_lualine_theme = {
-- P10k rainbow style theme with solid backgrounds
local theme = {
normal = {
a = { bg = colors.blue, fg = colors.bg, gui = "bold" },
b = { bg = colors.bg, fg = colors.fg },
c = { bg = colors.bg, fg = colors.fg },
a = { bg = colors.blue, fg = colors.black, gui = "bold" },
b = { bg = colors.bg, fg = colors.blue },
c = { bg = colors.bg_dark, fg = colors.fg },
z = { bg = colors.blue, fg = colors.black, gui = "bold" },
},
insert = {
a = { bg = colors.green, fg = colors.bg, gui = "bold" },
b = { bg = colors.bg, fg = colors.fg },
c = { bg = colors.bg, fg = colors.fg },
a = { bg = colors.green, fg = colors.black, gui = "bold" },
b = { bg = colors.bg, fg = colors.green },
c = { bg = colors.bg_dark, fg = colors.fg },
z = { bg = colors.green, fg = colors.black, gui = "bold" },
},
visual = {
a = { bg = colors.violet, fg = colors.bg, gui = "bold" },
b = { bg = colors.bg, fg = colors.fg },
c = { bg = colors.bg, fg = colors.fg },
a = { bg = colors.magenta, fg = colors.black, gui = "bold" },
b = { bg = colors.bg, fg = colors.magenta },
c = { bg = colors.bg_dark, fg = colors.fg },
z = { bg = colors.magenta, fg = colors.black, gui = "bold" },
},
command = {
a = { bg = colors.yellow, fg = colors.bg, gui = "bold" },
b = { bg = colors.bg, fg = colors.fg },
c = { bg = colors.bg, fg = colors.fg },
a = { bg = colors.yellow, fg = colors.black, gui = "bold" },
b = { bg = colors.bg, fg = colors.yellow },
c = { bg = colors.bg_dark, fg = colors.fg },
z = { bg = colors.yellow, fg = colors.black, gui = "bold" },
},
replace = {
a = { bg = colors.red, fg = colors.bg, gui = "bold" },
b = { bg = colors.bg, fg = colors.fg },
c = { bg = colors.bg, fg = colors.fg },
a = { bg = colors.red, fg = colors.black, gui = "bold" },
b = { bg = colors.bg, fg = colors.red },
c = { bg = colors.bg_dark, fg = colors.fg },
z = { bg = colors.red, fg = colors.black, gui = "bold" },
},
inactive = {
a = { bg = colors.inactive_bg, fg = colors.semilightgray, gui = "bold" },
b = { bg = colors.inactive_bg, fg = colors.semilightgray },
c = { bg = colors.inactive_bg, fg = colors.semilightgray },
a = { bg = colors.bg_dark, fg = colors.fg },
b = { bg = colors.bg_dark, fg = colors.fg },
c = { bg = colors.bg_dark, fg = colors.fg },
},
}
-- Custom word counter function
local function word_count()
-- Skip for very large files to avoid performance issues
local line_count = vim.api.nvim_buf_line_count(0)
if line_count > 10000 then
-- LSP client name
local function lsp_client()
local clients = vim.lsp.get_clients({ bufnr = 0 })
if #clients == 0 then
return ""
end
local words = 0
-- Get all lines at once for better performance
local all_lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
for _, line in ipairs(all_lines) do
if line and #line > 0 then
-- Count words (non-whitespace sequences)
for _ in line:gmatch("%S+") do
words = words + 1
end
local names = {}
for _, client in ipairs(clients) do
table.insert(names, client.name)
end
return " " .. table.concat(names, ", ")
end
-- Format: show only word count
return string.format("%d words", words)
end
-- configure lualine with modified theme
lualine.setup({
options = {
theme = my_lualine_theme,
theme = theme,
globalstatus = true,
-- Powerline angled separators like p10k
component_separators = { left = "", right = "" },
section_separators = { left = "", right = "" },
disabled_filetypes = {
statusline = { "dashboard", "alpha", "snacks_dashboard" },
},
},
sections = {
lualine_a = { "mode" },
lualine_b = { "branch", "diff", "diagnostics" },
lualine_c = { "filename" },
lualine_a = {
{ "mode", icon = "" },
},
lualine_b = {
{ "branch", icon = "" },
{
"diff",
symbols = { added = " ", modified = " ", removed = " " },
colored = true,
diff_color = {
added = { fg = colors.green },
modified = { fg = colors.yellow },
removed = { fg = colors.red },
},
},
},
lualine_c = {
{
"diagnostics",
symbols = { error = " ", warn = " ", info = " ", hint = "󰌵 " },
diagnostics_color = {
error = { fg = colors.red },
warn = { fg = colors.yellow },
info = { fg = colors.cyan },
hint = { fg = colors.green },
},
},
{ "filetype", icon_only = true, separator = "", padding = { left = 1, right = 0 } },
{ "filename", path = 1, symbols = { modified = "", readonly = " ", unnamed = "󰜥 " } },
},
lualine_x = {
{
lazy_status.updates,
cond = lazy_status.has_updates,
color = { fg = "#ff9e64" },
color = { fg = colors.orange, bg = colors.bg_dark },
},
{ "encoding" },
{ "fileformat" },
{ "filetype" },
{ lsp_client, color = { fg = colors.cyan, bg = colors.bg_dark } },
},
lualine_y = {
{ "encoding", icon = "" },
{ "fileformat", icons_enabled = true },
{ "filetype", colored = true, icon_only = false },
},
lualine_y = { "progress" },
lualine_z = {
{
word_count,
color = { fg = colors.fg },
},
{ "location" },
{ "progress", icon = "󰦨" },
{ "location", icon = "" },
},
},
inactive_sections = {
lualine_a = { "filename" },
lualine_a = {},
lualine_b = {},
lualine_c = {},
lualine_x = {},
lualine_c = { { "filename", path = 1 } },
lualine_x = { "location" },
lualine_y = {},
lualine_z = { "location" },
lualine_z = {},
},
extensions = { "nvim-tree", "lazy", "fzf", "trouble", "quickfix" },
})
-- Ensure statusline has solid background
vim.opt.laststatus = 3
vim.api.nvim_set_hl(0, "StatusLine", { bg = colors.bg_dark })
vim.api.nvim_set_hl(0, "StatusLineNC", { bg = colors.bg_dark })
end,
}

View File

@@ -6,71 +6,234 @@ return {
"rcarriga/nvim-notify",
},
config = function()
require("notify").setup({
background_colour = "#1a1b26",
fps = 60,
icons = {
DEBUG = "",
ERROR = "",
INFO = "",
TRACE = "",
WARN = "",
},
level = 2,
minimum_width = 50,
render = "wrapped-compact",
stages = "fade_in_slide_out",
timeout = 3000,
top_down = true,
})
require("noice").setup({
cmdline = {
enabled = true,
view = "cmdline_popup",
opts = {},
format = {
cmdline = { icon = ">" },
search_down = { icon = "🔍 " },
search_up = { icon = "🔍 " },
filter = { icon = "$" },
lua = { icon = "" },
help = { icon = "?" },
cmdline = { pattern = "^:", icon = "", lang = "vim" },
search_down = { kind = "search", pattern = "^/", icon = " ", lang = "regex" },
search_up = { kind = "search", pattern = "^%?", icon = " ", lang = "regex" },
filter = { pattern = "^:%s*!", icon = "$", lang = "bash" },
lua = { pattern = { "^:%s*lua%s+", "^:%s*lua%s*=%s*", "^:%s*=%s*" }, icon = "", lang = "lua" },
help = { pattern = "^:%s*he?l?p?%s+", icon = "󰋖" },
input = { view = "cmdline_input", icon = "󰥻 " },
},
},
messages = {
enabled = true,
view = "mini", -- Mini popup for messages
view_error = "mini", -- Ensure errors also use mini
view_warn = "mini",
view = "notify",
view_error = "notify",
view_warn = "notify",
view_history = "messages",
view_search = "virtualtext",
},
popupmenu = {
enabled = true,
backend = "nui",
kind_icons = {},
},
redirect = {
view = "popup",
filter = { event = "msg_show" },
},
commands = {
history = {
view = "split",
opts = { enter = true, format = "details" },
filter = {
any = {
{ event = "notify" },
{ error = true },
{ warning = true },
{ event = "msg_show", kind = { "" } },
{ event = "lsp", kind = "message" },
},
},
},
last = {
view = "popup",
opts = { enter = true, format = "details" },
filter = {
any = {
{ event = "notify" },
{ error = true },
{ warning = true },
{ event = "msg_show", kind = { "" } },
{ event = "lsp", kind = "message" },
},
},
filter_opts = { count = 1 },
},
errors = {
view = "popup",
opts = { enter = true, format = "details" },
filter = { error = true },
filter_opts = { reverse = true },
},
},
notify = {
enabled = true,
view = "notify",
},
lsp = {
progress = {
enabled = false,
enabled = true,
format = "lsp_progress",
format_done = "lsp_progress_done",
throttle = 1000 / 30,
view = "mini",
},
override = {
["vim.lsp.util.convert_input_to_markdown_lines"] = true,
["vim.lsp.util.stylize_markdown"] = true,
["cmp.entry.get_documentation"] = true,
},
hover = {
enabled = true,
silent = false,
view = nil,
opts = {},
},
signature = {
enabled = true,
auto_open = {
enabled = true,
trigger = true,
luasnip = true,
throttle = 50,
},
view = nil,
opts = {},
},
message = {
enabled = true,
view = "mini", -- Show LSP messages in mini popup
view = "notify",
opts = {},
},
documentation = {
view = "hover",
opts = {
lang = "markdown",
replace = true,
render = "plain",
format = { "{message}" },
win_options = { concealcursor = "n", conceallevel = 3 },
},
},
views = {
mini = {
position = {
row = "100%", -- Place it at the bottom of the screen
col = "50%", -- Center it horizontally
},
border = {
style = "rounded",
markdown = {
hover = {
["|(%S-)|"] = vim.cmd.help,
["%[.-%]%((%S-)%)"] = require("noice.util").open,
},
win_options = {
winblend = 10, -- Slight transparency
highlights = {
["|%S-|"] = "@text.reference",
["@%S+"] = "@parameter",
["^%s*(Parameters:)"] = "@text.title",
["^%s*(Return:)"] = "@text.title",
["^%s*(See also:)"] = "@text.title",
["{%S-}"] = "@parameter",
},
max_height = 2, -- Small window size
max_width = 60,
},
notify = {
position = {
row = "100%", -- Bottom of the screen
col = "50%",
},
win_options = {
winblend = 10,
},
max_height = 2,
max_width = 60,
health = {
checker = true,
},
smart_move = {
enabled = true,
excluded_filetypes = { "cmp_menu", "cmp_docs", "notify" },
},
presets = {
bottom_search = false,
command_palette = true,
long_message_to_split = false,
long_message_to_split = true,
inc_rename = false,
lsp_doc_border = true,
},
throttle = 1000 / 30,
views = {
cmdline_popup = {
position = {
row = "50%",
col = "50%",
},
size = {
width = 60,
height = "auto",
},
border = {
style = "rounded",
padding = { 0, 1 },
},
win_options = {
winhighlight = {
Normal = "NormalFloat",
FloatBorder = "FloatBorder",
},
},
},
popupmenu = {
relative = "editor",
position = {
row = "55%",
col = "50%",
},
size = {
width = 60,
height = 10,
},
border = {
style = "rounded",
padding = { 0, 1 },
},
win_options = {
winhighlight = {
Normal = "NormalFloat",
FloatBorder = "FloatBorder",
},
},
},
mini = {
win_options = {
winblend = 0,
},
},
},
routes = {
{
filter = {
event = "msg_show",
kind = "",
find = "written",
},
opts = { skip = true },
},
{
filter = {
event = "msg_show",
kind = "search_count",
},
opts = { skip = true },
},
},
})
end,