Refactor config: fix conflicts, add features, update docs

- Fix keymap conflicts: session (<leader>sS/sR), substitute (<leader>sl)
- Remove duplicate keymaps (window, resize) and options (synmaxcol, foldmethod)
- Add which-key group names for better keymap organization
- Add auto-format on save with smart filtering (conform.nvim)
- Add diagnostic float on hover (CursorHold)
- Add safe buffer close with unsaved changes confirmation
- Add quickfix/location list navigation keymaps
- Add startup config validation (nvim version, executables)
- Enable plugin update notifications in lazy.nvim
- Clean up: remove temporary files (kkk, cleanup script)
- Clean up: remove commented code and fix double function loading
- Update README.md with comprehensive documentation
- Add CHANGELOG.md tracking all changes
This commit is contained in:
Carlos Gutierrez
2026-01-10 22:13:59 -05:00
parent 0066ac1441
commit cd817820ca
15 changed files with 490 additions and 1093 deletions

View File

@@ -34,31 +34,80 @@ local function load_functions()
end
-- 4. Fix: Force filetype detection on BufRead (fix for nvim-tree/plain text issue)
-- Only run if filetype is not already detected to avoid redundant calls
vim.api.nvim_create_autocmd("BufRead", {
pattern = "*",
callback = function()
vim.cmd("silent filetype detect")
if vim.bo.filetype == "" then
vim.cmd("silent filetype detect")
end
end,
})
-- 5. Load functions immediately
load_functions()
-- 6. Fallback: also try to load on VimEnter if LazyDone doesn't fire
-- 5. Load functions on VimEnter to ensure plugins are loaded first
-- Using a flag to prevent double-loading
local functions_loaded = false
vim.api.nvim_create_autocmd("VimEnter", {
callback = function()
-- Wait a bit for plugins to load
vim.defer_fn(function()
load_functions()
end, 200)
if not functions_loaded then
vim.defer_fn(function()
load_functions()
functions_loaded = true
end, 200)
end
end,
once = true,
})
--[[ vim.api.nvim_create_autocmd("BufReadPost", {
once = true,
-- 6. Diagnostic float on hover (show diagnostics when cursor holds)
vim.api.nvim_create_autocmd("CursorHold", {
callback = function()
require("cargdev.core.project_config").bootstrap_config()
end
local opts = {
focusable = false,
close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" },
border = "rounded",
source = "always",
prefix = " ",
scope = "cursor",
}
vim.diagnostic.open_float(nil, opts)
end,
})
]]
-- 7. Configuration validation on startup
local function validate_config()
local warnings = {}
-- Check Neovim version (require 0.9+)
if vim.fn.has("nvim-0.9") == 0 then
table.insert(warnings, "Neovim 0.9+ is recommended for this configuration")
end
-- Check for required executables
local required_executables = { "git", "rg", "node" }
for _, exe in ipairs(required_executables) do
if vim.fn.executable(exe) == 0 then
table.insert(warnings, string.format("'%s' not found in PATH", exe))
end
end
-- Display warnings if any
if #warnings > 0 then
vim.defer_fn(function()
for _, warning in ipairs(warnings) do
vim.notify("Config Warning: " .. warning, vim.log.levels.WARN)
end
end, 1000)
end
end
-- Run validation on startup
vim.api.nvim_create_autocmd("VimEnter", {
callback = validate_config,
once = true,
})
-- 8. Custom health check command
vim.api.nvim_create_user_command("CheckConfig", function()
vim.cmd("checkhealth")
end, { desc = "Run Neovim health check" })

View File

@@ -11,14 +11,16 @@ local opts = { noremap = true, silent = true }
-- "jj" is much less likely to appear in normal typing and won't interfere
keymap.set("i", "jj", "<ESC>", opts) -- Exit insert mode with jj
keymap.set("n", "<leader>nh", ":nohl<CR>", opts) -- Clear search highlights
-- Removed: keymap.set("n", "x", '"_x', opts) -- Delete character without copying into register
-- This was causing single character deletions to not be copied to the default register
-- Save and quit (additional)
keymap.set("n", "<leader>Q", ":qa!<CR>", { desc = "Quit all" })
-- Put this in your init.lua
-- Obsidian vault path with validation
local vault_path = vim.env.IDEA_DIR
if not vault_path or vault_path == "" then
-- Silently skip Obsidian link setup if IDEA_DIR is not configured
return
end

View File

@@ -25,17 +25,7 @@ keymap.set("n", "<leader>no", ":noh <CR>", { desc = "Reset search a word" })
keymap.set("n", "<leader>+", "<C-a>", { desc = "Increment number" }) -- increment
keymap.set("n", "<leader>-", "<C-x>", { desc = "Decrement number" }) -- decrement
-- window management
keymap.set("n", "<leader>sv", "<C-w>v", { desc = "Split window vertically" }) -- split window vertically
keymap.set("n", "<leader>sh", "<C-w>s", { desc = "Split window horizontally" }) -- split window horizontally
keymap.set("n", "<leader>se", "<C-w>=", { desc = "Make splits equal size" }) -- make split windows equal width & height
keymap.set("n", "<leader>sx", "<cmd>close<CR>", { desc = "Close current split" }) -- close current split window
keymap.set("n", "<leader>to", "<cmd>tabnew<CR>", { desc = "Open new tab" }) -- open new tab
keymap.set("n", "<leader>tx", "<cmd>tabclose<CR>", { desc = "Close current tab" }) -- close current tab
keymap.set("n", "<leader>tn", "<cmd>tabn<CR>", { desc = "Go to next tab" }) -- go to next tab
keymap.set("n", "<leader>tp", "<cmd>tabp<CR>", { desc = "Go to previous tab" }) -- go to previous tab
keymap.set("n", "<leader>tf", "<cmd>tabnew %<CR>", { desc = "Open current buffer in new tab" }) -- move current buffer to new tab
-- Window management keymaps are centralized in lua/cargdev/core/keymaps/window.lua
-- sintax fixer
keymap.set("n", "<leader>sy", "gg=G<CR>", { desc = "Format current file" })
@@ -43,8 +33,26 @@ keymap.set("n", "<leader>sy", "gg=G<CR>", { desc = "Format current file" })
keymap.set("n", "<C-e>", "10<C-e>", { noremap = true, silent = true })
keymap.set("n", "<C-y>", "10<C-y>", { noremap = true, silent = true })
-- close current file on buffer
keymap.set("n", "<leader>bd", ":bd<CR>", { desc = "Close current file on buffer" })
-- Buffer management with safe close (confirms if unsaved changes)
keymap.set("n", "<leader>bd", function()
if vim.bo.modified then
vim.ui.select({ "Save & Close", "Discard & Close", "Cancel" }, {
prompt = "Buffer has unsaved changes:",
}, function(choice)
if choice == "Save & Close" then
vim.cmd("w")
vim.cmd("bd")
elseif choice == "Discard & Close" then
vim.cmd("bd!")
end
end)
else
vim.cmd("bd")
end
end, { desc = "Buffer: Close (safe)" })
-- Force close buffer without confirmation
keymap.set("n", "<leader>bD", ":bd!<CR>", { desc = "Buffer: Force close" })
-- Set buftabline mappings
keymap.set("n", "<C-p>", ":bnext<CR>", { noremap = true, silent = true })
@@ -62,17 +70,7 @@ keymap.set("n", "<leader>;", "$a;<ESC>", { desc = "Adding ';' at the end of the
keymap.set("n", "<leader>con", "oconsole.log()<ESC>0w$h", { desc = "Adding console.log() on the line below" })
keymap.set("n", "<leader>x", ":!node %<CR>", { desc = "Running current project using node" })
-- Move between Tmux and Neovim splits using Alt + Arrow keys
-- keymap.set("n", "<A-h>", ":TmuxNavigateLeft<CR>", { noremap = true, silent = true })
-- keymap.set("n", "<A-j>", ":TmuxNavigateDown<CR>", { noremap = true, silent = true })
-- keymap.set("n", "<A-k>", ":TmuxNavigateUp<CR>", { noremap = true, silent = true })
-- keymap.set("n", "<A-l>", ":TmuxNavigateRight<CR>", { noremap = true, silent = true })
-- Resize splits using Ctrl + Arrow keys
keymap.set("n", "<C-l>", ":vertical resize -5<CR>", { noremap = true, silent = true })
keymap.set("n", "<C-h>", ":vertical resize +5<CR>", { noremap = true, silent = true })
keymap.set("n", "<C-k>", ":resize +5<CR>", { noremap = true, silent = true })
keymap.set("n", "<C-j>", ":resize -5<CR>", { noremap = true, silent = true })
-- Resize splits keymaps are centralized in lua/cargdev/core/keymaps/window.lua
-- Run and Debug Project
keymap.set("n", "<leader>pr", ":RunProject<CR>", { desc = "Run Project" })
@@ -91,3 +89,20 @@ keymap.set("v", "<leader>zd", ":CopilotChatDocs<CR>", { desc = "Generate docs (C
keymap.set("n", "<leader>p", function()
vim.cmd("read !pbpaste -Prefer html | pandoc -f html -t gfm")
end, { desc = "Paste HTML clipboard as Markdown" })
-- =============================================================================
-- QUICKFIX NAVIGATION
-- =============================================================================
keymap.set("n", "<leader>qn", ":cnext<CR>zz", { desc = "Quickfix: Next item" })
keymap.set("n", "<leader>qp", ":cprev<CR>zz", { desc = "Quickfix: Previous item" })
keymap.set("n", "<leader>qo", ":copen<CR>", { desc = "Quickfix: Open list" })
keymap.set("n", "<leader>qq", ":cclose<CR>", { desc = "Quickfix: Close list" })
keymap.set("n", "<leader>qf", ":cfirst<CR>zz", { desc = "Quickfix: First item" })
keymap.set("n", "<leader>ql", ":clast<CR>zz", { desc = "Quickfix: Last item" })
-- Location list navigation
keymap.set("n", "<leader>ln", ":lnext<CR>zz", { desc = "Location: Next item" })
keymap.set("n", "<leader>lp", ":lprev<CR>zz", { desc = "Location: Previous item" })
keymap.set("n", "<leader>lo", ":lopen<CR>", { desc = "Location: Open list" })
keymap.set("n", "<leader>lq", ":lclose<CR>", { desc = "Location: Close list" })

View File

@@ -42,17 +42,17 @@ keymap.set("n", "<leader>tf", "<cmd>ToggleTerm direction=float<cr>", { desc = "T
keymap.set("n", "<leader>th", "<cmd>ToggleTerm size=10 direction=horizontal<cr>", { desc = "ToggleTerm horizontal split" })
keymap.set("n", "<leader>tv", "<cmd>ToggleTerm size=80 direction=vertical<cr>", { desc = "ToggleTerm vertical split" })
-- Session management
keymap.set("n", "<leader>ss", "<cmd>SessionSave<cr>", { desc = "Save session" })
keymap.set("n", "<leader>sr", "<cmd>SessionRestore<cr>", { desc = "Restore session" })
-- Session management (using <leader>sS and <leader>sR to avoid conflicts with substitute)
keymap.set("n", "<leader>sS", "<cmd>SessionSave<cr>", { desc = "Session: Save" })
keymap.set("n", "<leader>sR", "<cmd>SessionRestore<cr>", { desc = "Session: Restore" })
-- Formatting
keymap.set("n", "<leader>f", "<cmd>lua vim.lsp.buf.format()<cr>", { desc = "Format buffer" })
-- Substitute (changed from <leader>s to <leader>sub to avoid conflicts)
keymap.set("n", "<leader>sub", "<cmd>lua require('substitute').operator()<cr>", { desc = "Substitute with motion" })
keymap.set("n", "<leader>ss", "<cmd>lua require('substitute').line()<cr>", { desc = "Substitute line" })
keymap.set("n", "<leader>S", "<cmd>lua require('substitute').eol()<cr>", { desc = "Substitute to end of line" })
-- Substitute
keymap.set("n", "<leader>sub", "<cmd>lua require('substitute').operator()<cr>", { desc = "Substitute: With motion" })
keymap.set("n", "<leader>sl", "<cmd>lua require('substitute').line()<cr>", { desc = "Substitute: Line" })
keymap.set("n", "<leader>S", "<cmd>lua require('substitute').eol()<cr>", { desc = "Substitute: To end of line" })
-- Surround
keymap.set("n", "<leader>sa", "<cmd>lua require('nvim-surround').surround_add()<cr>", { desc = "Add surrounding" })

View File

@@ -40,7 +40,7 @@ opt.smartindent = true -- Smart indent
opt.updatetime = 100 -- Faster completion (reduced from 250)
opt.timeoutlen = 200 -- Faster key sequence completion (reduced from 300)
opt.redrawtime = 1500 -- Allow more time for loading syntax
opt.synmaxcol = 240 -- Only highlight the first 240 columns
opt.synmaxcol = 200 -- Only highlight the first 200 columns (conservative for performance)
opt.maxmempattern = 1000 -- Reduce memory for pattern matching
opt.hidden = true -- Allow switching buffers without saving
opt.scrolljump = 1 -- Minimal number of screen lines to scroll
@@ -49,9 +49,7 @@ opt.sidescrolloff = 3 -- Keep 3 columns left/right of cursor (reduced from 8)
-- Syntax loading optimizations
opt.syntax = "on" -- Enable syntax highlighting
opt.synmaxcol = 200 -- Reduce syntax highlighting column limit
opt.lazyredraw = false -- Don't use lazy redraw (can cause issues)
opt.foldmethod = "syntax" -- Use syntax-based folding for better performance
opt.foldlevel = 99 -- Don't fold by default
-- Filetype plugin optimizations
@@ -101,9 +99,8 @@ opt.formatoptions:append("j") -- Remove comment leader when joining lines
opt.showmatch = true -- Show matching brackets
opt.matchtime = 2 -- How long to show matching brackets
-- Folding
-- Folding (indent-based is generally faster than syntax-based)
opt.foldmethod = "indent" -- Fold based on indentation
opt.foldlevel = 99 -- Don't fold by default
opt.foldnestmax = 10 -- Maximum nesting level
-- Backup and swap

View File

@@ -14,7 +14,8 @@ vim.opt.rtp:prepend(lazypath)
require("lazy").setup({ { import = "cargdev.plugins" }, { import = "cargdev.plugins.lsp" } }, {
checker = {
enabled = true,
notify = false,
notify = true, -- Enable plugin update notifications
frequency = 86400, -- Check once per day (in seconds)
},
change_detection = {
notify = false,

View File

@@ -32,7 +32,22 @@ return {
dbml = { "dbml" }, -- DBML formatting
sql = { "sqlfluff" }, -- SQL formatting
},
format_on_save = false, -- Set to true if you want auto-formatting on save
format_on_save = function(bufnr)
-- Disable autoformat for certain filetypes
local ignore_filetypes = { "sql", "markdown" }
if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then
return
end
-- Disable for files in certain paths
local bufname = vim.api.nvim_buf_get_name(bufnr)
if bufname:match("/node_modules/") then
return
end
return {
timeout_ms = 2000,
lsp_fallback = true,
}
end,
})
vim.keymap.set({ "n", "v" }, "<leader>mm", function()
@@ -41,6 +56,16 @@ return {
async = false,
timeout_ms = 2000,
})
end, { desc = "Format file or range (in visual mode)" })
end, { desc = "Format: File or range (in visual mode)" })
-- Toggle auto-format on save
vim.api.nvim_create_user_command("FormatToggle", function()
vim.g.disable_autoformat = not vim.g.disable_autoformat
if vim.g.disable_autoformat then
vim.notify("Auto-format on save disabled", vim.log.levels.INFO)
else
vim.notify("Auto-format on save enabled", vim.log.levels.INFO)
end
end, { desc = "Toggle auto-format on save" })
end,
}

View File

@@ -49,7 +49,7 @@ return {
},
}
-- Custom word/character counter function
-- 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)
@@ -58,7 +58,6 @@ return {
end
local words = 0
local chars = 0
-- Get all lines at once for better performance
local all_lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
@@ -69,13 +68,11 @@ return {
for _ in line:gmatch("%S+") do
words = words + 1
end
-- Count characters (excluding newline)
chars = chars + #line
end
end
-- Format: show words and characters
return string.format("%d words, %d chars", words, chars)
-- Format: show only word count
return string.format("%d words", words)
end
-- configure lualine with modified theme

View File

@@ -5,9 +5,38 @@ return {
vim.o.timeout = true
vim.o.timeoutlen = 200 -- Reduced from 500 for faster response
end,
opts = {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
},
config = function()
local wk = require("which-key")
wk.setup({
plugins = {
marks = true,
registers = true,
spelling = { enabled = true, suggestions = 20 },
},
win = {
border = "rounded",
padding = { 2, 2, 2, 2 },
},
})
-- Register group names for better organization
wk.add({
{ "<leader>b", group = "Buffer" },
{ "<leader>c", group = "Code/Copilot" },
{ "<leader>d", group = "Debug/DAP" },
{ "<leader>e", group = "Explorer" },
{ "<leader>f", group = "Find/Files" },
{ "<leader>g", group = "Git" },
{ "<leader>l", group = "LSP/LeetCode" },
{ "<leader>m", group = "Format" },
{ "<leader>n", group = "Notifications" },
{ "<leader>p", group = "Project" },
{ "<leader>q", group = "Quickfix" },
{ "<leader>s", group = "Session/Split/Substitute" },
{ "<leader>t", group = "Tab/Terminal/Text" },
{ "<leader>x", group = "Trouble/Diagnostics" },
{ "<leader>z", group = "Copilot Chat" },
})
end,
}