chore: remove local/unused plugins and refactor core configs
- Remove locally-developed or rarely-used plugin packages (codetyper, curls, edgy, flash) to reduce maintenance surface, external deps, and startup cost; these were local/optional and caused complexity. - Clean up stale/keymap docs and small duplicate or experimental files (keymaps/README.md, sudoku keymaps). - Apply targeted refactors to core modules for readability, robustness, and to align Java/DAP/Copilot integrations with local environment. - Removed plugin modules: - lua/cargdev/plugins/codetyper.lua (deleted) - lua/cargdev/plugins/curls.lua (deleted) - lua/cargdev/plugins/edgy.lua (deleted) - lua/cargdev/plugins/flash.lua (deleted) - Added .codetyper to .gitignore - Java / JDTLS: - ftplugin/java.lua: pin jdtls java executable to JDK 25, switch to mac_arm config, enable LSP formatter and declare multiple runtimes (JavaSE-17, JavaSE-25). - Notifications & startup UX: - lua/cargdev/core/function/notification_manager.lua: large refactor — use local aliases (api, cmd, loop, opt), improved docs, dashboard-aware handling, nvim-notify fallback, safer tracking and cleanup of notifications. - Utilities & monitors: - lua/cargdev/core/function/performance_monitor.lua: use local references, better notify usage and docs. - lua/cargdev/core/function/project_commands.lua: add docs, use local api/fn/notify, clearer RunProject/DebugProject commands. - Terminal helper: - lua/cargdev/core/function/openTerminal.lua: add module docs and small refactor to use local cmd/api aliases and expose keymap. - Keymaps & docs: - Removed stale keymaps README (lua/cargdev/core/keymaps/README.md). - Reworked many keymap files: docstrings, renamed/moved mappings to avoid conflicts, moved DAP mappings into dap plugin config, removed/disabled experimental mappings (see files under lua/cargdev/core/keymaps/*). - Adjusted quick keybindings and prefixes to reduce overlaps. - Plugins & integrations: - lua/cargdev/plugins/formatting.lua: disabled google-java-format fallback for java (prefer JDTLS). - lua/cargdev/plugins/dap.lua: added additional DAP configs (Bun launch, attach helper), moved/registered dap keymaps here. - lua/cargdev/plugins/copilot.lua: reorganized Copilot/Copilot-cmp/CopilotChat config and added copilot source to nvim-cmp. - lua/cargdev/plugins/nvim-cmp.lua: added copilot source and small formatting tweak.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -28,3 +28,4 @@ local.lua
|
||||
*.coder.*
|
||||
.coder/
|
||||
.vscode/
|
||||
.codetyper/
|
||||
|
||||
3
.luarc.json
Normal file
3
.luarc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"Lua": { "diagnostics": { "globals": ["vim"] } }
|
||||
}
|
||||
@@ -4,6 +4,9 @@ local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:t")
|
||||
local workspace_dir = workspace_path .. project_name
|
||||
local keymap = vim.keymap.set
|
||||
|
||||
-- JDTLS requires JDK 21+ to run; use JDK 25 for the server process
|
||||
local jdtls_java = "/opt/homebrew/Cellar/openjdk/25.0.2/libexec/openjdk.jdk/Contents/Home/bin/java"
|
||||
|
||||
local status, jdtls = pcall(require, "jdtls")
|
||||
|
||||
if not status then
|
||||
@@ -44,7 +47,7 @@ end
|
||||
|
||||
local config = {
|
||||
cmd = {
|
||||
"java",
|
||||
jdtls_java,
|
||||
"-Declipse.application=org.eclipse.jdt.ls.core.id1",
|
||||
"-Dosgi.bundles.defaultStartLevel=4",
|
||||
"-Declipse.product=org.eclipse.jdt.ls.core.product",
|
||||
@@ -60,7 +63,7 @@ local config = {
|
||||
"-jar",
|
||||
vim.fn.glob(home .. "/.local/share/nvim/mason/packages/jdtls/plugins/org.eclipse.equinox.launcher_*.jar"),
|
||||
"-configuration",
|
||||
home .. "/.local/share/nvim/mason/packages/jdtls/config_mac",
|
||||
home .. "/.local/share/nvim/mason/packages/jdtls/config_mac_arm",
|
||||
"-data",
|
||||
workspace_dir,
|
||||
},
|
||||
@@ -85,7 +88,20 @@ local config = {
|
||||
},
|
||||
},
|
||||
format = {
|
||||
enabled = false,
|
||||
enabled = true,
|
||||
},
|
||||
configuration = {
|
||||
runtimes = {
|
||||
{
|
||||
name = "JavaSE-17",
|
||||
path = "/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home",
|
||||
},
|
||||
{
|
||||
name = "JavaSE-25",
|
||||
path = "/opt/homebrew/Cellar/openjdk/25.0.2/libexec/openjdk.jdk/Contents/Home",
|
||||
default = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
-- Highlight .njk files as htmldjango for better templating syntax
|
||||
vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
|
||||
--- Custom filetype detection for unsupported or ambiguous file extensions.
|
||||
--- Registers autocmds that assign the correct filetype when buffers are
|
||||
--- opened, enabling proper syntax highlighting and LSP support.
|
||||
--- @module highlights
|
||||
|
||||
--- Set .njk (Nunjucks) files to use the htmldjango filetype,
|
||||
--- which provides the closest built-in syntax support for
|
||||
--- Nunjucks/Jinja-style template syntax (blocks, extends, includes).
|
||||
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
|
||||
pattern = "*.njk",
|
||||
callback = function()
|
||||
vim.cmd("set filetype=htmldjango")
|
||||
|
||||
@@ -1,13 +1,31 @@
|
||||
-- Custom notification manager to handle overlapping and improve UX
|
||||
--- Custom notification manager to handle overlapping and improve UX.
|
||||
--- Provides a centralized notification system that prevents overlapping,
|
||||
--- supports dashboard-aware notifications, and integrates with nvim-notify
|
||||
--- when available, falling back to cmd echo otherwise.
|
||||
--- @module notification_manager
|
||||
local M = {}
|
||||
local log = vim.log
|
||||
local api = vim.api
|
||||
local cmd = vim.cmd
|
||||
local o = vim.o
|
||||
local loop = vim.loop
|
||||
local opt = vim.opt
|
||||
local deferFn = vim.defer_fn
|
||||
|
||||
-- Track active notifications to prevent overlapping
|
||||
--- List of currently displayed notifications (each entry has win, message, timestamp).
|
||||
--- @type table[]
|
||||
local active_notifications = {}
|
||||
local notification_queue = {}
|
||||
|
||||
-- Function to show a notification without overlapping
|
||||
--- Show a notification without overlapping existing ones.
|
||||
--- Uses nvim-notify if available; otherwise falls back to echo.
|
||||
--- Automatically detects the alpha dashboard and delegates to
|
||||
--- `show_dashboard_notification` when appropriate.
|
||||
--- @param message string The notification message to display.
|
||||
--- @param level number|nil Log level from log.levels (default: INFO).
|
||||
--- @param opts table|nil Optional overrides (timeout, title, render, position, etc.).
|
||||
--- @return number|nil notification_id The nvim-notify notification id, or nil on fallback.
|
||||
function M.show_notification(message, level, opts)
|
||||
level = level or vim.log.levels.INFO
|
||||
level = level or log.levels.INFO
|
||||
opts = opts or {}
|
||||
|
||||
-- Default options
|
||||
@@ -31,8 +49,8 @@ function M.show_notification(message, level, opts)
|
||||
end
|
||||
|
||||
-- Check if we're in alpha dashboard
|
||||
local current_buf = vim.api.nvim_get_current_buf()
|
||||
local current_ft = vim.api.nvim_buf_get_option(current_buf, "filetype")
|
||||
local current_buf = api.nvim_get_current_buf()
|
||||
local current_ft = api.nvim_buf_get_option(current_buf, "filetype")
|
||||
|
||||
if current_ft == "alpha" then
|
||||
-- If in dashboard, use a different approach
|
||||
@@ -49,22 +67,22 @@ function M.show_notification(message, level, opts)
|
||||
opts.on_open = function(win)
|
||||
-- Calculate position to avoid overlapping with other notifications
|
||||
local row = 2
|
||||
local col = vim.o.columns - 60
|
||||
local col = o.columns - 60
|
||||
|
||||
-- Adjust position if there are other notifications
|
||||
for _, notif in ipairs(active_notifications) do
|
||||
if notif.win and vim.api.nvim_win_is_valid(notif.win) then
|
||||
if notif.win and api.nvim_win_is_valid(notif.win) then
|
||||
row = row + 10 -- Stack notifications vertically
|
||||
end
|
||||
end
|
||||
|
||||
-- Ensure notification doesn't go off-screen
|
||||
if row > vim.o.lines - 15 then
|
||||
if row > o.lines - 15 then
|
||||
row = 2
|
||||
col = col - 20
|
||||
end
|
||||
|
||||
vim.api.nvim_win_set_config(win, {
|
||||
api.nvim_win_set_config(win, {
|
||||
row = row,
|
||||
col = col,
|
||||
relative = "editor",
|
||||
@@ -76,7 +94,7 @@ function M.show_notification(message, level, opts)
|
||||
table.insert(active_notifications, {
|
||||
win = win,
|
||||
message = message,
|
||||
timestamp = vim.loop.now(),
|
||||
timestamp = loop.now(),
|
||||
})
|
||||
end
|
||||
|
||||
@@ -96,33 +114,38 @@ function M.show_notification(message, level, opts)
|
||||
else
|
||||
-- Fallback to echo instead of vim.notify to avoid circular dependency
|
||||
local icon = "💬"
|
||||
if level == vim.log.levels.ERROR then
|
||||
if level == log.levels.ERROR then
|
||||
icon = "❌"
|
||||
elseif level == vim.log.levels.WARN then
|
||||
elseif level == log.levels.WARN then
|
||||
icon = "⚠️"
|
||||
elseif level == vim.log.levels.INFO then
|
||||
elseif level == log.levels.INFO then
|
||||
icon = "ℹ️"
|
||||
end
|
||||
|
||||
-- Use echo for fallback notifications
|
||||
vim.cmd("echo '" .. icon .. " " .. message .. "'")
|
||||
cmd("echo '" .. icon .. " " .. message .. "'")
|
||||
|
||||
-- Clear message after a delay
|
||||
vim.defer_fn(function()
|
||||
vim.cmd("echo ''")
|
||||
deferFn(function()
|
||||
cmd("echo ''")
|
||||
end, opts.timeout or 3000)
|
||||
end
|
||||
end
|
||||
|
||||
-- Function to show notifications specifically for dashboard
|
||||
--- Show a minimal notification tailored for the alpha dashboard.
|
||||
--- Truncates messages longer than 50 characters and uses echo
|
||||
--- to avoid interfering with the dashboard layout.
|
||||
--- @param message string The notification message to display.
|
||||
--- @param level number|nil Log level from log.levels.
|
||||
--- @param opts table|nil Optional overrides (timeout, etc.).
|
||||
function M.show_dashboard_notification(message, level, opts)
|
||||
-- In dashboard, show minimal notifications
|
||||
local icon = "💬"
|
||||
if level == vim.log.levels.ERROR then
|
||||
if level == log.levels.ERROR then
|
||||
icon = "❌"
|
||||
elseif level == vim.log.levels.WARN then
|
||||
elseif level == log.levels.WARN then
|
||||
icon = "⚠️"
|
||||
elseif level == vim.log.levels.INFO then
|
||||
elseif level == log.levels.INFO then
|
||||
icon = "ℹ️"
|
||||
end
|
||||
|
||||
@@ -133,25 +156,29 @@ function M.show_dashboard_notification(message, level, opts)
|
||||
end
|
||||
|
||||
-- Use echo for dashboard notifications to avoid overlapping
|
||||
vim.cmd("echo '" .. icon .. " " .. short_message .. "'")
|
||||
cmd("echo '" .. icon .. " " .. short_message .. "'")
|
||||
|
||||
-- Clear message after a delay
|
||||
vim.defer_fn(function()
|
||||
vim.cmd("echo ''")
|
||||
deferFn(function()
|
||||
cmd("echo ''")
|
||||
end, opts.timeout or 3000)
|
||||
end
|
||||
|
||||
-- Function to clear all notifications
|
||||
--- Close and clear all active notifications.
|
||||
--- Iterates through `active_notifications`, closes any valid windows,
|
||||
--- and resets the tracking list.
|
||||
function M.clear_all_notifications()
|
||||
for _, notif in ipairs(active_notifications) do
|
||||
if notif.win and vim.api.nvim_win_is_valid(notif.win) then
|
||||
vim.api.nvim_win_close(notif.win, true)
|
||||
if notif.win and api.nvim_win_is_valid(notif.win) then
|
||||
api.nvim_win_close(notif.win, true)
|
||||
end
|
||||
end
|
||||
active_notifications = {}
|
||||
end
|
||||
|
||||
-- Function to show performance notification
|
||||
--- Show a performance-related notification with a chart icon prefix.
|
||||
--- @param message string The performance message to display.
|
||||
--- @param level number|nil Log level from log.levels.
|
||||
function M.show_performance_notification(message, level)
|
||||
M.show_notification("📊 " .. message, level, {
|
||||
title = "Performance Monitor",
|
||||
@@ -160,7 +187,9 @@ function M.show_performance_notification(message, level)
|
||||
})
|
||||
end
|
||||
|
||||
-- Function to show LSP notification
|
||||
--- Show an LSP status notification with a wrench icon prefix.
|
||||
--- @param message string The LSP status message to display.
|
||||
--- @param level number|nil Log level from log.levels.
|
||||
function M.show_lsp_notification(message, level)
|
||||
M.show_notification("🔧 " .. message, level, {
|
||||
title = "LSP Status",
|
||||
@@ -169,7 +198,9 @@ function M.show_lsp_notification(message, level)
|
||||
})
|
||||
end
|
||||
|
||||
-- Function to show file operation notification
|
||||
--- Show a file operation notification with a folder icon prefix.
|
||||
--- @param message string The file operation message to display.
|
||||
--- @param level number|nil Log level from log.levels.
|
||||
function M.show_file_notification(message, level)
|
||||
M.show_notification("📁 " .. message, level, {
|
||||
title = "File Operation",
|
||||
@@ -178,7 +209,9 @@ function M.show_file_notification(message, level)
|
||||
})
|
||||
end
|
||||
|
||||
-- Function to show plugin notification
|
||||
--- Show a plugin manager notification with a sloth icon prefix.
|
||||
--- @param message string The plugin-related message to display.
|
||||
--- @param level number|nil Log level from log.levels.
|
||||
function M.show_plugin_notification(message, level)
|
||||
M.show_notification("🦥 " .. message, level, {
|
||||
title = "Plugin Manager",
|
||||
@@ -187,7 +220,9 @@ function M.show_plugin_notification(message, level)
|
||||
})
|
||||
end
|
||||
|
||||
-- Function to show startup notification
|
||||
--- Show a startup notification with a rocket icon prefix and a short timeout.
|
||||
--- @param message string The startup message to display.
|
||||
--- @param level number|nil Log level from log.levels.
|
||||
function M.show_startup_notification(message, level)
|
||||
M.show_notification("🚀 " .. message, level, {
|
||||
title = "Startup",
|
||||
@@ -196,57 +231,64 @@ function M.show_startup_notification(message, level)
|
||||
})
|
||||
end
|
||||
|
||||
-- Function to handle startup messages aggressively
|
||||
--- Aggressively suppress startup messages and "Press ENTER" prompts.
|
||||
--- Configures `shortmess` with all relevant flags, sets `cmdheight` to 0,
|
||||
--- disables `showmode`, and schedules deferred redraws to clear any
|
||||
--- lingering messages.
|
||||
function M.handle_startup_messages()
|
||||
-- Clear any existing messages immediately
|
||||
vim.cmd("redraw!")
|
||||
vim.cmd("echo ''")
|
||||
cmd("redraw!")
|
||||
cmd("echo ''")
|
||||
|
||||
-- Suppress all startup messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "I" -- No intro message
|
||||
vim.opt.shortmess = vim.opt.shortmess + "c" -- No completion messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "F" -- No file info message
|
||||
vim.opt.shortmess = vim.opt.shortmess + "W" -- No "written" message
|
||||
vim.opt.shortmess = vim.opt.shortmess + "A" -- No attention message
|
||||
vim.opt.shortmess = vim.opt.shortmess + "o" -- No overwrite messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "t" -- No truncation messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "T" -- No truncation messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "f" -- No file info messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "i" -- No intro messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "l" -- No line number messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "m" -- No modification messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "n" -- No line number messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "r" -- No read messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "s" -- No search messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "x" -- No truncation messages
|
||||
vim.opt.shortmess = vim.opt.shortmess + "O" -- No overwrite messages
|
||||
opt.shortmess = opt.shortmess + "I" -- No intro message
|
||||
opt.shortmess = opt.shortmess + "c" -- No completion messages
|
||||
opt.shortmess = opt.shortmess + "F" -- No file info message
|
||||
opt.shortmess = opt.shortmess + "W" -- No "written" message
|
||||
opt.shortmess = opt.shortmess + "A" -- No attention message
|
||||
opt.shortmess = opt.shortmess + "o" -- No overwrite messages
|
||||
opt.shortmess = opt.shortmess + "t" -- No truncation messages
|
||||
opt.shortmess = opt.shortmess + "T" -- No truncation messages
|
||||
opt.shortmess = opt.shortmess + "f" -- No file info messages
|
||||
opt.shortmess = opt.shortmess + "i" -- No intro messages
|
||||
opt.shortmess = opt.shortmess + "l" -- No line number messages
|
||||
opt.shortmess = opt.shortmess + "m" -- No modification messages
|
||||
opt.shortmess = opt.shortmess + "n" -- No line number messages
|
||||
opt.shortmess = opt.shortmess + "r" -- No read messages
|
||||
opt.shortmess = opt.shortmess + "s" -- No search messages
|
||||
opt.shortmess = opt.shortmess + "x" -- No truncation messages
|
||||
opt.shortmess = opt.shortmess + "O" -- No overwrite messages
|
||||
|
||||
-- Disable command line messages
|
||||
vim.opt.cmdheight = 0
|
||||
vim.opt.showmode = false
|
||||
opt.cmdheight = 0
|
||||
opt.showmode = false
|
||||
|
||||
-- Clear any existing messages
|
||||
vim.cmd("echo ''")
|
||||
cmd("echo ''")
|
||||
|
||||
-- Force clear any pending messages
|
||||
vim.defer_fn(function()
|
||||
vim.cmd("redraw!")
|
||||
vim.cmd("echo ''")
|
||||
deferFn(function()
|
||||
cmd("redraw!")
|
||||
cmd("echo ''")
|
||||
end, 100)
|
||||
end
|
||||
|
||||
-- Function to eliminate "Press ENTER" prompts completely
|
||||
--- Eliminate "Press ENTER" prompts by overriding `cmd.echo` and
|
||||
--- installing autocmds that forcibly clear messages on VimEnter and
|
||||
--- BufReadPost events.
|
||||
function M.eliminate_enter_prompts()
|
||||
-- Override the message display to prevent "Press ENTER" prompts
|
||||
local original_echo = vim.cmd.echo
|
||||
vim.cmd.echo = function(msg)
|
||||
local original_echo = cmd.echo
|
||||
cmd.echo = function(msg)
|
||||
local msg_str = tostring(msg)
|
||||
-- Block any messages that might cause "Press ENTER" prompts
|
||||
if msg_str:match("Press ENTER") or
|
||||
msg_str:match("lazyredraw") or
|
||||
msg_str:match("You have enabled") or
|
||||
msg_str:match("This is only meant") or
|
||||
msg_str:match("You'll experience issues") then
|
||||
if
|
||||
msg_str:match("Press ENTER")
|
||||
or msg_str:match("lazyredraw")
|
||||
or msg_str:match("You have enabled")
|
||||
or msg_str:match("This is only meant")
|
||||
or msg_str:match("You'll experience issues")
|
||||
then
|
||||
return -- Don't show these messages
|
||||
end
|
||||
-- Allow other messages
|
||||
@@ -254,17 +296,17 @@ function M.eliminate_enter_prompts()
|
||||
end
|
||||
|
||||
-- Create autocmd to handle any remaining prompts
|
||||
vim.api.nvim_create_autocmd("VimEnter", {
|
||||
api.nvim_create_autocmd("VimEnter", {
|
||||
callback = function()
|
||||
-- Clear any startup messages immediately
|
||||
vim.cmd("redraw!")
|
||||
vim.cmd("echo ''")
|
||||
cmd("redraw!")
|
||||
cmd("echo ''")
|
||||
|
||||
-- Force clear any pending messages multiple times
|
||||
for i = 1, 5 do
|
||||
vim.defer_fn(function()
|
||||
vim.cmd("redraw!")
|
||||
vim.cmd("echo ''")
|
||||
deferFn(function()
|
||||
cmd("redraw!")
|
||||
cmd("echo ''")
|
||||
end, i * 50)
|
||||
end
|
||||
end,
|
||||
@@ -272,18 +314,21 @@ function M.eliminate_enter_prompts()
|
||||
})
|
||||
|
||||
-- Create autocmd to handle message events - use valid events
|
||||
vim.api.nvim_create_autocmd("BufReadPost", {
|
||||
api.nvim_create_autocmd("BufReadPost", {
|
||||
callback = function()
|
||||
-- Clear messages that might cause prompts
|
||||
vim.cmd("redraw!")
|
||||
cmd("redraw!")
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- Function to setup notification system
|
||||
--- Initialize the notification system.
|
||||
--- Registers VimEnter and FileType autocmds to handle startup messages
|
||||
--- and dashboard transitions, and calls `eliminate_enter_prompts`.
|
||||
--- Called automatically when the module is first required.
|
||||
function M.setup()
|
||||
-- Create autocmd to handle startup messages
|
||||
vim.api.nvim_create_autocmd("VimEnter", {
|
||||
api.nvim_create_autocmd("VimEnter", {
|
||||
callback = function()
|
||||
M.handle_startup_messages()
|
||||
end,
|
||||
@@ -291,7 +336,7 @@ function M.setup()
|
||||
})
|
||||
|
||||
-- Create autocmd to handle alpha dashboard
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
api.nvim_create_autocmd("FileType", {
|
||||
pattern = "alpha",
|
||||
callback = function()
|
||||
M.handle_startup_messages()
|
||||
@@ -305,7 +350,7 @@ function M.setup()
|
||||
-- Let the system handle notifications naturally
|
||||
end
|
||||
|
||||
-- Initialize notification manager
|
||||
--- Initialize notification manager on require.
|
||||
M.setup()
|
||||
|
||||
return M
|
||||
|
||||
@@ -1,48 +1,54 @@
|
||||
--- Terminal toggle utility.
|
||||
--- Provides a function and keybinding (`<Leader>ter`) to open or close a
|
||||
--- vertical-split zsh terminal on the right side of the editor. The terminal
|
||||
--- automatically enters insert mode on focus and exits insert mode on blur.
|
||||
--- @module openTerminal
|
||||
|
||||
vim.g.mapleader = " "
|
||||
|
||||
local keymap = vim.keymap
|
||||
local cmd = vim.cmd
|
||||
local api = vim.api
|
||||
|
||||
-- Function to open terminal
|
||||
--- Toggle a terminal split on the rightmost side of the editor.
|
||||
--- If the rightmost buffer is already a terminal, it closes it.
|
||||
--- Otherwise, opens a new vertical split running zsh with line numbers
|
||||
--- disabled and auto insert-mode behavior on focus/blur.
|
||||
local function open_terminal()
|
||||
-- Move to the rightmost buffer (equivalent to `<C-l>` multiple times)
|
||||
vim.cmd("wincmd l")
|
||||
vim.cmd("wincmd l")
|
||||
vim.cmd("wincmd l")
|
||||
vim.cmd("wincmd l")
|
||||
cmd("wincmd l")
|
||||
cmd("wincmd l")
|
||||
cmd("wincmd l")
|
||||
cmd("wincmd l")
|
||||
|
||||
-- Get current buffer number and type
|
||||
local buf_num = vim.api.nvim_get_current_buf()
|
||||
local buf_type = vim.api.nvim_buf_get_option(buf_num, "buftype")
|
||||
local buf_num = apinvim_get_current_buf()
|
||||
local buf_type = apinvim_buf_get_option(buf_num, "buftype")
|
||||
|
||||
if buf_type == "terminal" then
|
||||
-- If already in a terminal, close it
|
||||
vim.cmd("q")
|
||||
cmd("q")
|
||||
else
|
||||
-- Open terminal in a vertical split
|
||||
vim.cmd("vsp | term zsh")
|
||||
cmd("vsp | term zsh")
|
||||
|
||||
-- Disable line numbers in terminal
|
||||
vim.cmd("setlocal nonumber norelativenumber")
|
||||
cmd("setlocal nonumber norelativenumber")
|
||||
|
||||
-- Auto-start insert mode in terminal
|
||||
vim.api.nvim_create_autocmd({ "BufWinEnter", "WinEnter" }, {
|
||||
apinvim_create_autocmd({ "BufWinEnter", "WinEnter" }, {
|
||||
buffer = 0,
|
||||
command = "startinsert!",
|
||||
})
|
||||
vim.api.nvim_create_autocmd("BufLeave", {
|
||||
apinvim_create_autocmd("BufLeave", {
|
||||
buffer = 0,
|
||||
command = "stopinsert!",
|
||||
})
|
||||
|
||||
-- Terminal key mappings
|
||||
vim.keymap.set("t", "<C-h>", "<C-\\><C-n><C-w>h", { buffer = true })
|
||||
vim.keymap.set("t", "<C-t>", "<C-\\><C-n>:q<CR>", { buffer = true })
|
||||
vim.keymap.set("t", "<C-\\><C-\\>", "<C-\\><C-n>", { buffer = true })
|
||||
|
||||
-- Start terminal in insert mode
|
||||
vim.cmd("startinsert!")
|
||||
cmd("startinsert!")
|
||||
end
|
||||
end
|
||||
|
||||
-- Keybinding to open terminal
|
||||
--- Map `<Leader>ter` in normal mode to toggle the terminal split.
|
||||
keymap.set("n", "<Leader>ter", open_terminal, { noremap = true, silent = true })
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
--- Performance and LSP health monitoring utilities.
|
||||
--- Provides functions to inspect memory usage, startup time, loaded plugins,
|
||||
--- active LSP clients, and per-buffer diagnostic summaries.
|
||||
--- @module performance_monitor
|
||||
local M = {}
|
||||
|
||||
-- Check overall Neovim performance
|
||||
local fn = vim.fn
|
||||
local notify = vim.notify
|
||||
local lsp = vim.lsp
|
||||
|
||||
--- Collect and display overall Neovim performance statistics.
|
||||
--- Reports memory usage, open buffer count, active LSP clients, and
|
||||
--- (when lazy.nvim is available) loaded plugin count and startup time.
|
||||
--- Results are shown via `vim.notify` at INFO level.
|
||||
function M.check_performance()
|
||||
local stats = {}
|
||||
|
||||
-- Startup time
|
||||
stats.startup = vim.fn.reltimefloat(vim.fn.reltime(vim.g.start_time or vim.fn.reltime()))
|
||||
stats.startup = fn.reltimefloat(fn.reltime(vim.g.start_time or fn.reltime()))
|
||||
|
||||
-- Memory usage
|
||||
local mem = collectgarbage("count")
|
||||
@@ -13,7 +24,7 @@ function M.check_performance()
|
||||
stats.memory_mb = string.format("%.2f", mem / 1024)
|
||||
|
||||
-- Buffer count
|
||||
stats.buffers = #vim.fn.getbufinfo({ buflisted = 1 })
|
||||
stats.buffers = #fn.getbufinfo({ buflisted = 1 })
|
||||
|
||||
-- Loaded plugins (lazy.nvim)
|
||||
local lazy_ok, lazy = pcall(require, "lazy")
|
||||
@@ -25,7 +36,7 @@ function M.check_performance()
|
||||
end
|
||||
|
||||
-- Active LSP clients
|
||||
stats.lsp_clients = #vim.lsp.get_clients()
|
||||
stats.lsp_clients = #lsp.get_clients()
|
||||
|
||||
-- Display results
|
||||
local lines = {
|
||||
@@ -41,15 +52,19 @@ function M.check_performance()
|
||||
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" })
|
||||
notify(table.concat(lines, "\n"), vim.log.levels.INFO, { title = "Performance" })
|
||||
end
|
||||
|
||||
-- Check LSP health for current buffer
|
||||
--- Check LSP health for the current buffer.
|
||||
--- Lists all attached LSP clients with their root directory and
|
||||
--- server capabilities (completion, hover, definition, references,
|
||||
--- formatting, code_actions), followed by a diagnostic severity summary.
|
||||
--- Warns if no LSP clients are attached.
|
||||
function M.check_lsp_health()
|
||||
local clients = vim.lsp.get_clients({ bufnr = 0 })
|
||||
local clients = 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" })
|
||||
notify("No LSP clients attached to this buffer", vim.log.levels.WARN, { title = "LSP Health" })
|
||||
return
|
||||
end
|
||||
|
||||
@@ -103,10 +118,18 @@ function M.check_lsp_health()
|
||||
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))
|
||||
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" })
|
||||
notify(table.concat(lines, "\n"), vim.log.levels.INFO, { title = "LSP Health" })
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -1,27 +1,43 @@
|
||||
vim.api.nvim_create_user_command("RunProject", function()
|
||||
--- Project-level user commands for running and debugging.
|
||||
--- Reads a per-project configuration file at `.nvim/project.lua` that should
|
||||
--- return a table with `run` and/or `debug` keys containing shell commands.
|
||||
--- Registers the `:RunProject` and `:DebugProject` user commands.
|
||||
--- @module project_commands
|
||||
|
||||
local api = vim.api
|
||||
local fn = vim.fn
|
||||
local notify = vim.notify
|
||||
|
||||
--- Run the project using the `run` command from `.nvim/project.lua`.
|
||||
--- Opens a vertical split terminal with the configured run command.
|
||||
--- Notifies the user if the config file or run command is missing.
|
||||
api.nvim_create_user_command("RunProject", function()
|
||||
local config_path = ".nvim/project.lua"
|
||||
if vim.fn.filereadable(config_path) == 0 then
|
||||
vim.notify("No project config found. Run `:e` on any file to generate it.", vim.log.levels.WARN)
|
||||
if fn.filereadable(config_path) == 0 then
|
||||
notify("No project config found. Run `:e` on any file to generate it.", vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
local config = loadfile(config_path)()
|
||||
if config and config.run then
|
||||
vim.cmd("vsplit | terminal " .. config.run)
|
||||
else
|
||||
vim.notify("Run command not found in project config.", vim.log.levels.ERROR)
|
||||
notify("Run command not found in project config.", vim.log.levels.ERROR)
|
||||
end
|
||||
end, {})
|
||||
|
||||
vim.api.nvim_create_user_command("DebugProject", function()
|
||||
--- Debug the project using the `debug` command from `.nvim/project.lua`.
|
||||
--- Opens a vertical split terminal with the configured debug command.
|
||||
--- Notifies the user if the config file or debug command is missing.
|
||||
api.nvim_create_user_command("DebugProject", function()
|
||||
local config_path = ".nvim/project.lua"
|
||||
if vim.fn.filereadable(config_path) == 0 then
|
||||
vim.notify("No project config found. Run `:e` on any file to generate it.", vim.log.levels.WARN)
|
||||
if fn.filereadable(config_path) == 0 then
|
||||
notify("No project config found. Run `:e` on any file to generate it.", vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
local config = loadfile(config_path)()
|
||||
if config and config.debug then
|
||||
vim.cmd("vsplit | terminal " .. config.debug)
|
||||
else
|
||||
vim.notify("Debug command not found in project config.", vim.log.levels.ERROR)
|
||||
notify("Debug command not found in project config.", vim.log.levels.ERROR)
|
||||
end
|
||||
end, {})
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
# Keymaps Structure
|
||||
|
||||
This folder contains all the keymaps organized by category for better maintainability.
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
keymaps/
|
||||
├── README.md # This file
|
||||
├── general.lua # General keymaps (leader, basic navigation, obsidian)
|
||||
├── personal.lua # Personal workflow keymaps
|
||||
├── lsp.lua # LSP and function navigation keymaps
|
||||
├── dap.lua # DAP debugging keymaps
|
||||
├── snacks.lua # Snacks search and navigation keymaps
|
||||
├── window.lua # Window management keymaps
|
||||
├── copilot.lua # Copilot AI keymaps
|
||||
├── plugins.lua # Plugin-specific keymaps (Telescope, trouble, etc.)
|
||||
├── project.lua # Project-specific keymaps
|
||||
├── ufo.lua # Folding keymaps
|
||||
├── leet.lua # LeetCode keymaps
|
||||
├── sudoku.lua # Sudoku game keymaps
|
||||
└── database.lua # Database keymaps
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
The main `keymaps.lua` file automatically loads all `.lua` files from this folder:
|
||||
|
||||
```lua
|
||||
local function load_keymaps()
|
||||
local keymaps_path = vim.fn.stdpath("config") .. "/lua/cargdev/core/keymaps"
|
||||
local scan = vim.fn.globpath(keymaps_path, "*.lua", false, true)
|
||||
|
||||
for _, file in ipairs(scan) do
|
||||
local module_name = "cargdev.core.keymaps." .. file:match("([^/]+)%.lua$")
|
||||
pcall(require, module_name)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Keymap Categories
|
||||
|
||||
| Category | File | Description |
|
||||
|----------|------|-------------|
|
||||
| General | `general.lua` | Basic setup, escape, obsidian links |
|
||||
| Personal | `personal.lua` | Your workflow shortcuts |
|
||||
| LSP | `lsp.lua` | Function navigation and LSP features |
|
||||
| Debugging | `dap.lua` | DAP debugging (Java, Node.js, Python) |
|
||||
| Search | `snacks.lua` | File and text search (Snacks) |
|
||||
| Window | `window.lua` | Window/split management |
|
||||
| Copilot | `copilot.lua` | AI assistant keymaps |
|
||||
| Plugins | `plugins.lua` | Plugin-specific (Telescope, trouble, etc.) |
|
||||
| Project | `project.lua` | Project commands |
|
||||
| Folding | `ufo.lua` | Code folding |
|
||||
| LeetCode | `leet.lua` | LeetCode integration |
|
||||
| Database | `database.lua` | Database operations |
|
||||
|
||||
## Adding New Keymaps
|
||||
|
||||
1. **Choose the appropriate file** based on the category
|
||||
2. **Add your keymaps** using the standard format:
|
||||
```lua
|
||||
local keymap = vim.keymap
|
||||
keymap.set("n", "<leader>key", "<cmd>command<cr>", { desc = "Description" })
|
||||
```
|
||||
3. **The keymaps will be automatically loaded** when Neovim starts
|
||||
|
||||
## Leader Key Prefixes
|
||||
|
||||
| Prefix | Category |
|
||||
|--------|----------|
|
||||
| `<leader>f` | Find/Files (Telescope) |
|
||||
| `<leader>g` | Git |
|
||||
| `<leader>d` | Debug |
|
||||
| `<leader>l` | LSP/LeetCode |
|
||||
| `<leader>x` | Trouble/Diagnostics |
|
||||
| `<leader>s` | Search/Session |
|
||||
| `<leader>t` | Toggle/Text/Treesj |
|
||||
| `<leader>h` | Harpoon |
|
||||
| `<leader>k` | Kulala (HTTP) |
|
||||
| `<leader>o` | Overseer/Octo |
|
||||
| `<leader>n` | NPM/Navbuddy |
|
||||
| `<leader>c` | Code/Crates |
|
||||
| `<leader>v` | Vim learning |
|
||||
| `<leader>z` | Zen mode |
|
||||
| `<leader>q` | Session (persistence) |
|
||||
| `<leader>r` | Rename/Regex |
|
||||
| `<leader>p` | Portal/Projects |
|
||||
|
||||
## Full Reference
|
||||
|
||||
See [KEYMAPS.md](../../../../KEYMAPS.md) in the root directory for complete keybinding reference.
|
||||
|
||||
## Notes
|
||||
|
||||
- All files are automatically loaded by `keymaps.lua`
|
||||
- Each file should have its own `local keymap = vim.keymap` declaration
|
||||
- Use descriptive `desc` for all keymaps (shows in which-key)
|
||||
- Follow the existing naming conventions for consistency
|
||||
@@ -1,24 +1,32 @@
|
||||
-- Copilot keymaps
|
||||
--- Copilot keymaps.
|
||||
--- Bindings for GitHub Copilot panel navigation (normal mode) and inline
|
||||
--- suggestion cycling (insert mode). All Copilot modules are loaded via
|
||||
--- pcall to avoid errors when Copilot is not installed or authenticated.
|
||||
--- @module keymaps.copilot
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
-- Helper function to safely get Copilot modules
|
||||
--- Safely require the copilot.panel module.
|
||||
--- @return table|nil panel The panel module, or nil if unavailable.
|
||||
local function get_copilot_panel()
|
||||
local ok, panel = pcall(require, "copilot.panel")
|
||||
return ok and panel or nil
|
||||
end
|
||||
|
||||
--- Safely require the copilot.suggestion module.
|
||||
--- @return table|nil suggestion The suggestion module, or nil if unavailable.
|
||||
local function get_copilot_suggestion()
|
||||
local ok, suggestion = pcall(require, "copilot.suggestion")
|
||||
return ok and suggestion or nil
|
||||
end
|
||||
|
||||
-- Copilot panel and status
|
||||
--- Copilot commands — open panel, disable, enable, and check status.
|
||||
keymap.set("n", "<leader>cp", ":Copilot panel<CR>", { desc = "Copilot: Open copilot panel" })
|
||||
keymap.set("n", "<leader>cd", ":Copilot disable<CR>", { desc = "Copilot: Disable" })
|
||||
keymap.set("n", "<leader>ce", ":Copilot enable<CR>", { desc = "Copilot: Enable" })
|
||||
keymap.set("n", "<leader>cD", ":Copilot disable<CR>", { desc = "Copilot: Disable" })
|
||||
keymap.set("n", "<leader>cE", ":Copilot enable<CR>", { desc = "Copilot: Enable" })
|
||||
keymap.set("n", "<leader>cs", ":Copilot status<CR>", { desc = "Copilot: Status" })
|
||||
|
||||
-- Copilot panel keymaps
|
||||
--- Panel navigation — jump previous/next, accept, refresh, and open.
|
||||
keymap.set("n", "[[", function()
|
||||
local panel = get_copilot_panel()
|
||||
if panel and panel.is_open() then
|
||||
@@ -40,7 +48,7 @@ keymap.set("n", "<CR>", function()
|
||||
end
|
||||
end, { desc = "Copilot: Accept suggestion in panel" })
|
||||
|
||||
keymap.set("n", "gr", function()
|
||||
keymap.set("n", "rp", function()
|
||||
local panel = get_copilot_panel()
|
||||
if panel and panel.is_open() then
|
||||
panel.refresh()
|
||||
@@ -49,10 +57,7 @@ end, { desc = "Copilot: Refresh panel" })
|
||||
|
||||
keymap.set("n", "<M-CR>", ":Copilot panel<CR>", { desc = "Copilot: Open panel" })
|
||||
|
||||
-- Copilot suggestion keymaps (insert mode)
|
||||
-- Note: Tab mapping is handled in nvim-cmp.lua to avoid conflicts
|
||||
-- Tab is reserved exclusively for Copilot inline suggestions
|
||||
|
||||
--- Inline suggestion cycling (insert mode) — next, previous, dismiss.
|
||||
keymap.set("i", "<leader>]", function()
|
||||
local suggestion = get_copilot_suggestion()
|
||||
if suggestion and suggestion.is_visible() then
|
||||
@@ -73,6 +78,3 @@ keymap.set("i", "<C-]>", function()
|
||||
suggestion.dismiss()
|
||||
end
|
||||
end, { desc = "Copilot: Dismiss suggestion" })
|
||||
|
||||
-- CodeCompanion keymaps
|
||||
keymap.set("n", "<leader>cc", ":CodeCompanion<CR>", { desc = "CodeCompanion: Open CodeCompanion" })
|
||||
|
||||
@@ -1,35 +1,6 @@
|
||||
-- DAP (Debug Adapter Protocol) keymaps
|
||||
|
||||
local ok_dap, dap = pcall(require, "dap")
|
||||
local ok_dapui, dapui = pcall(require, "dapui")
|
||||
local fn = vim.fn
|
||||
local keymap = vim.keymap.set
|
||||
|
||||
if ok_dap and ok_dapui then
|
||||
keymap("n", "<leader>dcr", dap.continue, { desc = "▶ Start Debugging" })
|
||||
keymap("n", "<leader>do", dap.step_over, { desc = "⏭ Step Over" })
|
||||
keymap("n", "<leader>di", dap.step_into, { desc = "⤵ Step Into" })
|
||||
keymap("n", "<leader>dot", dap.step_out, { desc = "⤴ Step Out" })
|
||||
keymap("n", "<leader>db", dap.toggle_breakpoint, { desc = "🔴 Toggle Breakpoint" })
|
||||
keymap("n", "<leader>dB", function()
|
||||
dap.set_breakpoint(fn.input("Breakpoint condition: "))
|
||||
end, { desc = "⚠ Conditional Breakpoint" })
|
||||
keymap("n", "<leader>dr", dap.repl.open, { desc = "💬 Open REPL" })
|
||||
keymap("n", "<leader>dl", dap.run_last, { desc = "🔁 Run Last Debug" })
|
||||
keymap("n", "<leader>du", dapui.toggle, { desc = "🧩 Toggle DAP UI" })
|
||||
keymap("n", "<leader>dq", dap.terminate, { desc = "⛔ Stop Debugging" })
|
||||
|
||||
-- 🧼 Reset UI
|
||||
keymap("n", "<leader>drt", function()
|
||||
dap.terminate()
|
||||
dapui.close()
|
||||
vim.defer_fn(function()
|
||||
dapui.open()
|
||||
end, 200)
|
||||
end, { desc = "🧼 Reset DAP UI Layout" })
|
||||
|
||||
-- 🔭 Snacks Integration (replacing Telescope)
|
||||
keymap("n", "<leader>dcf", "<cmd>lua require('snacks.picker').dap_configurations()<cr>", { desc = "🔭 DAP Configs" })
|
||||
keymap("n", "<leader>dcb", "<cmd>lua require('snacks.picker').dap_list_breakpoints()<cr>", { desc = "🧷 List Breakpoints" })
|
||||
keymap("n", "<leader>dco", "<cmd>lua require('snacks.picker').dap_commands()<cr>", { desc = "⚙️ DAP Commands" })
|
||||
end
|
||||
--- DAP (Debug Adapter Protocol) keymaps.
|
||||
--- All DAP keymaps are registered in `plugins/dap.lua` inside the plugin's
|
||||
--- config function to ensure nvim-dap and nvim-dap-ui are fully loaded
|
||||
--- before any keybindings reference them. This file is intentionally empty.
|
||||
--- @module keymaps.dap
|
||||
--- @see plugins.dap
|
||||
|
||||
@@ -1,53 +1,57 @@
|
||||
-- Database keymaps
|
||||
-- Using <leader>D prefix to avoid conflicts with DAP keymaps (<leader>d)
|
||||
--- Database keymaps (vim-dadbod, MongoDB, Redis).
|
||||
--- Uses `<leader>D` prefix to avoid conflicts with DAP keymaps (`<leader>d`).
|
||||
--- Covers DBUI toggle, connections, query execution/saving, buffer management,
|
||||
--- and quick-connect shortcuts for PostgreSQL Docker, MongoDB, and Redis.
|
||||
--- @module keymaps.database
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
-- =============================================================================
|
||||
-- DATABASE KEYMAPS (vim-dadbod)
|
||||
-- =============================================================================
|
||||
|
||||
-- Toggle database UI
|
||||
--- Toggle the vim-dadbod Database UI panel.
|
||||
keymap.set("n", "<leader>Du", "<cmd>DBUIToggle<CR>", { desc = "Toggle Database UI" })
|
||||
|
||||
-- Add a new database connection
|
||||
--- Add a new database connection interactively.
|
||||
keymap.set("n", "<leader>Da", "<cmd>DBUIAddConnection<CR>", { desc = "Add DB Connection" })
|
||||
|
||||
-- Find buffer (useful when you have multiple query buffers)
|
||||
--- Find a DBUI query buffer (useful when multiple query buffers are open).
|
||||
keymap.set("n", "<leader>Df", "<cmd>DBUIFindBuffer<CR>", { desc = "Find DB Buffer" })
|
||||
|
||||
-- Execute query (works in sql buffers)
|
||||
--- Execute a SQL query (full buffer in normal mode, selection in visual mode).
|
||||
keymap.set("n", "<leader>De", "<Plug>(DBUI_ExecuteQuery)", { desc = "Execute Query" })
|
||||
keymap.set("v", "<leader>De", "<Plug>(DBUI_ExecuteQuery)", { desc = "Execute Selected Query" })
|
||||
|
||||
-- Save query
|
||||
--- Save the current query buffer to disk.
|
||||
keymap.set("n", "<leader>Dw", "<Plug>(DBUI_SaveQuery)", { desc = "Save Query" })
|
||||
|
||||
-- Rename buffer
|
||||
--- Rename the current DBUI query buffer.
|
||||
keymap.set("n", "<leader>Dr", "<Plug>(DBUI_RenameBuf)", { desc = "Rename DB Buffer" })
|
||||
|
||||
-- =============================================================================
|
||||
-- QUICK CONNECTIONS
|
||||
-- =============================================================================
|
||||
|
||||
-- PostgreSQL Docker (default: 5432 postgres postgres postgres)
|
||||
--- Connect to a PostgreSQL instance running in Docker (default port 5432).
|
||||
keymap.set("n", "<leader>Dp", "<cmd>DBPostgresDocker<CR>", { desc = "Connect PostgreSQL Docker" })
|
||||
|
||||
-- =============================================================================
|
||||
-- MONGODB
|
||||
-- =============================================================================
|
||||
|
||||
-- Open MongoDB shell (local)
|
||||
--- Open a local MongoDB shell.
|
||||
keymap.set("n", "<leader>Dm", "<cmd>MongoDB<CR>", { desc = "Open MongoDB Shell" })
|
||||
|
||||
-- Open MongoDB in Docker container
|
||||
--- Open a MongoDB shell inside a Docker container.
|
||||
keymap.set("n", "<leader>DM", "<cmd>MongoDBDocker<CR>", { desc = "MongoDB Docker Shell" })
|
||||
|
||||
-- =============================================================================
|
||||
-- REDIS
|
||||
-- =============================================================================
|
||||
|
||||
-- Open Redis CLI (local)
|
||||
--- Open a local Redis CLI session.
|
||||
keymap.set("n", "<leader>Di", "<cmd>Redis<CR>", { desc = "Open Redis CLI" })
|
||||
|
||||
-- Open Redis in Docker container
|
||||
--- Open a Redis CLI session inside a Docker container.
|
||||
keymap.set("n", "<leader>DI", "<cmd>RedisDocker<CR>", { desc = "Redis Docker CLI" })
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
-- General keymaps
|
||||
--- General-purpose keymaps.
|
||||
--- Provides essential editor-wide shortcuts: insert-mode escape (`jj`),
|
||||
--- search highlight clearing, and quit-all.
|
||||
--- @module keymaps.general
|
||||
|
||||
local keymap = vim.keymap
|
||||
local opts = { noremap = true, silent = true }
|
||||
|
||||
@@ -6,116 +10,12 @@ local opts = { noremap = true, silent = true }
|
||||
-- GENERAL KEYMAPS
|
||||
-- =============================================================================
|
||||
|
||||
-- General keymaps
|
||||
-- Changed from "jk" to "jj" to avoid conflicts when typing words containing 'j' followed by other letters
|
||||
-- "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
|
||||
--- Exit insert mode by pressing `jj` (chosen over `jk` to avoid
|
||||
--- conflicts when typing words containing "j" followed by other letters).
|
||||
keymap.set("i", "jj", "<ESC>", opts)
|
||||
|
||||
-- Save and quit (additional)
|
||||
--- Clear search highlights.
|
||||
keymap.set("n", "<leader>nh", ":nohl<CR>", opts)
|
||||
|
||||
--- Quit all open buffers and windows without saving.
|
||||
keymap.set("n", "<leader>Q", ":qa!<CR>", { desc = "Quit all" })
|
||||
|
||||
-- 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
|
||||
|
||||
|
||||
|
||||
local function follow_obsidian_link()
|
||||
-- Extract the full [[...]] link from the current line under/around the cursor
|
||||
local line = vim.api.nvim_get_current_line()
|
||||
local col = vim.fn.col('.')
|
||||
local start_idx, end_idx, raw
|
||||
-- Search for all [[...]] in the line, pick the one under/around the cursor
|
||||
local i = 1
|
||||
while true do
|
||||
local s, e = line:find('%[%[.-%]%]', i)
|
||||
if not s then break end
|
||||
if col >= s and col <= e + 1 then
|
||||
start_idx, end_idx = s, e
|
||||
break
|
||||
end
|
||||
i = e + 1
|
||||
end
|
||||
if not start_idx then
|
||||
vim.notify('No [[link]] under cursor', vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
raw = line:sub(start_idx, end_idx)
|
||||
raw = raw:gsub('^!%[%[', '[[') -- strip leading ! from embeds
|
||||
local link = raw:gsub('%[%[', ''):gsub('%]%]', '')
|
||||
|
||||
-- split off alias (|) and heading (#) only after extracting the full link
|
||||
local alias
|
||||
local heading
|
||||
-- first, split off alias if present
|
||||
local pipe_idx = link:find("|", 1, true)
|
||||
if pipe_idx then
|
||||
alias = link:sub(pipe_idx + 1)
|
||||
link = link:sub(1, pipe_idx - 1)
|
||||
end
|
||||
-- then, split off heading if present
|
||||
local hash_idx = link:find("#", 1, true)
|
||||
if hash_idx then
|
||||
heading = link:sub(hash_idx + 1)
|
||||
link = link:sub(1, hash_idx - 1)
|
||||
end
|
||||
|
||||
-- normalize spaces
|
||||
link = link:gsub("\\ ", " "):gsub("^%s+", ""):gsub("%s+$", "")
|
||||
|
||||
local function goto_heading(h)
|
||||
if not h or h == "" then
|
||||
return
|
||||
end
|
||||
-- crude jump: search for markdown heading or block that contains it
|
||||
vim.cmd("keepjumps normal! gg")
|
||||
local pat = "^%s*#+%s*" .. vim.pesc(h)
|
||||
if vim.fn.search(pat) == 0 then
|
||||
-- fallback: plain search
|
||||
vim.fn.search(vim.pesc(h))
|
||||
end
|
||||
end
|
||||
|
||||
-- if link contains a '/', treat it as a relative path inside the vault
|
||||
if link:find("/") then
|
||||
local target = vault_path .. "/" .. link .. ".md"
|
||||
vim.cmd.edit(target)
|
||||
goto_heading(heading)
|
||||
return
|
||||
end
|
||||
|
||||
-- otherwise search recursively for basename match anywhere in the vault
|
||||
local pattern = "**/" .. link .. ".md"
|
||||
local matches = vim.fn.globpath(vault_path, pattern, false, true) -- list
|
||||
|
||||
if #matches == 1 then
|
||||
vim.cmd.edit(matches[1])
|
||||
goto_heading(heading)
|
||||
elseif #matches > 1 then
|
||||
vim.ui.select(matches, { prompt = "Multiple matches for " .. link .. ":" }, function(choice)
|
||||
if choice then
|
||||
vim.cmd.edit(choice)
|
||||
goto_heading(heading)
|
||||
end
|
||||
end)
|
||||
else
|
||||
-- not found: offer to create at vault root
|
||||
local target = vault_path .. "/" .. link .. ".md"
|
||||
vim.ui.input({ prompt = "Create " .. target .. " ? (y/N) " }, function(ans)
|
||||
if ans and ans:lower():sub(1, 1) == "y" then
|
||||
vim.cmd.edit(target)
|
||||
-- optional: insert a title
|
||||
if vim.fn.line("$") == 1 and vim.fn.getline(1) == "" then
|
||||
vim.api.nvim_buf_set_lines(0, 0, 0, false, { "# " .. (alias or link), "" })
|
||||
end
|
||||
goto_heading(heading)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
vim.keymap.set("n", "<leader>o", follow_obsidian_link, { noremap = true, silent = true })
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
-- Leet keymaps
|
||||
--- LeetCode keymaps.
|
||||
--- Bindings for testing, submitting, and retrieving solutions via the
|
||||
--- leetcode.nvim plugin. All mappings use the `<leader>l` prefix.
|
||||
--- @module keymaps.leet
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
keymap.set("n", "<leader>lr", ":Leet test<CR>", { desc = "Test the leet current problem code" })
|
||||
keymap.set("n", "<leader>ls", ":Leet submit<CR>", { desc = "Submit the leet solution" })
|
||||
keymap.set("n", "<leader>lls", ":Leet last_submit<CR>", { desc = "Brings the latest submition from leetcode" })
|
||||
--- LeetCode — run, submit, daily challenge, list, console, cookie, hints.
|
||||
keymap.set("n", "<leader>lr", "<cmd>Leet run<CR>", { desc = "LeetCode: Run Code" })
|
||||
keymap.set("n", "<leader>ls", "<cmd>Leet submit<CR>", { desc = "LeetCode: Submit Code" })
|
||||
keymap.set("n", "<leader>ld", "<cmd>Leet daily<CR>", { desc = "LeetCode: Daily Challenge" })
|
||||
keymap.set("n", "<leader>ll", "<cmd>Leet list<CR>", { desc = "LeetCode: List Problems" })
|
||||
keymap.set("n", "<leader>lc", "<cmd>Leet console<CR>", { desc = "LeetCode: Open Console" })
|
||||
keymap.set("n", "<leader>lu", "<cmd>Leet cookie update<CR>", { desc = "LeetCode: Update Cookie" })
|
||||
keymap.set("n", "<leader>lh", "<cmd>Leet hints<cr>", { desc = "LeetCode: Open hints" })
|
||||
keymap.set("n", "<leader>lls", "<cmd>Leet last<cr>", { desc = "LeetCode: Get latest submission" })
|
||||
|
||||
@@ -1,27 +1,33 @@
|
||||
-- LSP and function navigation keymaps
|
||||
--- LSP and function navigation keymaps.
|
||||
--- Uses fzf-lua pickers for go-to-definition, implementation, references,
|
||||
--- type definitions, symbol search, code actions, rename, hover docs,
|
||||
--- and diagnostic navigation.
|
||||
--- @module keymaps.lsp
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
-- =============================================================================
|
||||
-- LSP NAVIGATION (FUNCTION NAVIGATION) - Using fzf-lua
|
||||
-- =============================================================================
|
||||
|
||||
-- Primary LSP navigation
|
||||
--- Primary LSP navigation — definition, implementation, references, type def.
|
||||
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
|
||||
--- Symbol search — document and workspace symbols via fzf-lua.
|
||||
keymap.set("n", "<leader>ds", "<cmd>FzfLua lsp_document_symbols<cr>", { desc = "Document symbols" })
|
||||
keymap.set("n", "<leader>lw", "<cmd>FzfLua lsp_workspace_symbols<cr>", { desc = "LSP: Workspace symbols" })
|
||||
|
||||
-- Code actions and documentation
|
||||
--- Code actions, rename, and hover documentation.
|
||||
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" })
|
||||
keymap.set("n", "H", "<cmd>lua vim.lsp.buf.hover()<cr>", { desc = "Hover documentation" })
|
||||
|
||||
-- Diagnostics
|
||||
--- Diagnostics — workspace list, line float, and prev/next navigation.
|
||||
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" })
|
||||
|
||||
|
||||
17
lua/cargdev/core/keymaps/openterminal.lua
Normal file
17
lua/cargdev/core/keymaps/openterminal.lua
Normal file
@@ -0,0 +1,17 @@
|
||||
--- Terminal-mode keymaps.
|
||||
--- Provides shortcuts for navigating out of terminal buffers and closing them.
|
||||
--- - `Ctrl+H` — switch to the left window from terminal mode.
|
||||
--- - `Ctrl+T` — close the terminal window.
|
||||
--- - `Ctrl+\ Ctrl+\` — escape to normal mode from terminal mode.
|
||||
--- @module keymaps.openterminal
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
--- Switch to the left window from terminal mode.
|
||||
keymap.set("t", "<C-h>", "<C-\\><C-n><C-w>h", { buffer = true })
|
||||
|
||||
--- Close the terminal window.
|
||||
keymap.set("t", "<C-t>", "<C-\\><C-n>:q<CR>", { buffer = true })
|
||||
|
||||
--- Escape terminal mode to normal mode.
|
||||
keymap.set("t", "<C-\\><C-\\>", "<C-\\><C-n>", { buffer = true })
|
||||
@@ -1,66 +1,50 @@
|
||||
-- Personal keymaps (original workflow)
|
||||
--- Personal keymaps — custom workflow shortcuts.
|
||||
--- Includes text selection helpers, file management (save, quit, source),
|
||||
--- number increment/decrement, buffer management with smart close via
|
||||
--- snacks.bufdelete, coding shortcuts (React import, semicolons, commas,
|
||||
--- console.log), Copilot Chat commands, clipboard HTML-to-Markdown paste,
|
||||
--- and quickfix/location list navigation.
|
||||
--- @module keymaps.personal
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
-- =============================================================================
|
||||
-- PERSONAL KEYMAPS (ORIGINAL WORKFLOW)
|
||||
-- =============================================================================
|
||||
|
||||
--- Select the entire file contents (visual mode).
|
||||
keymap.set("n", "<leader>u", function()
|
||||
vim.cmd("normal! ggVG$")
|
||||
end, { desc = "Select the whole file" })
|
||||
|
||||
--- Duplicate the current line below.
|
||||
keymap.set("n", "<leader>4", function()
|
||||
-- Copy current line and paste below
|
||||
vim.cmd("normal! yy")
|
||||
vim.cmd("normal! p")
|
||||
end, { desc = "Copy the entire line and paste just below" })
|
||||
|
||||
-- file management
|
||||
--- File management — save, quit, force quit, source, and clear search.
|
||||
keymap.set("n", "<leader>w", ":w<CR>", { desc = "Save the current file" })
|
||||
keymap.set("n", "<leader>xa", ":xa<CR>", { desc = "Save and close all the files" })
|
||||
keymap.set("n", "<leader>q", ":q<CR>", { desc = "Quit" })
|
||||
keymap.set("n", "<leader>Q", ":q!<CR>", { desc = "Force quit" })
|
||||
keymap.set("n", "<leader>so", ":source %<CR>", { desc = "Reload nvim" })
|
||||
keymap.set("n", "<leader>no", ":noh <CR>", { desc = "Reset search a word" })
|
||||
|
||||
-- increment/decrement numbers
|
||||
keymap.set("n", "<leader>+", "<C-a>", { desc = "Increment number" }) -- increment
|
||||
keymap.set("n", "<leader>-", "<C-x>", { desc = "Decrement number" }) -- decrement
|
||||
--- Increment/decrement the number under the cursor.
|
||||
keymap.set("n", "<leader>+", "<C-a>", { desc = "Increment number" })
|
||||
keymap.set("n", "<leader>-", "<C-x>", { desc = "Decrement number" })
|
||||
|
||||
-- Window management keymaps are centralized in lua/cargdev/core/keymaps/window.lua
|
||||
|
||||
-- sintax fixer
|
||||
--- Re-indent the entire file using Neovim's built-in `=` operator.
|
||||
keymap.set("n", "<leader>sy", "gg=G<CR>", { desc = "Format current file" })
|
||||
|
||||
--- Fast scroll — 10 lines at a time with Ctrl+E / Ctrl+Y.
|
||||
keymap.set("n", "<C-e>", "10<C-e>", { noremap = true, silent = true })
|
||||
keymap.set("n", "<C-y>", "10<C-y>", { noremap = true, silent = true })
|
||||
|
||||
-- Buffer management with safe close (confirms if unsaved changes)
|
||||
-- Uses snacks.bufdelete for smart buffer deletion, shows dashboard on last buffer
|
||||
local function close_buffer(force)
|
||||
local ok, snacks = pcall(require, "snacks")
|
||||
if ok and snacks.bufdelete then
|
||||
-- snacks.bufdelete handles everything smartly
|
||||
snacks.bufdelete({ force = force })
|
||||
else
|
||||
-- Fallback to manual handling
|
||||
local current_buf = vim.api.nvim_get_current_buf()
|
||||
local buffers = vim.tbl_filter(function(buf)
|
||||
return vim.api.nvim_buf_is_valid(buf) and vim.bo[buf].buflisted
|
||||
end, vim.api.nvim_list_bufs())
|
||||
|
||||
if #buffers > 1 then
|
||||
vim.cmd("bprevious")
|
||||
vim.cmd((force and "bdelete! " or "bdelete ") .. current_buf)
|
||||
else
|
||||
-- Last buffer: show dashboard instead of quitting
|
||||
vim.cmd("enew")
|
||||
if ok and snacks.dashboard then
|
||||
snacks.dashboard()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Close the current buffer with a confirmation prompt if modified.
|
||||
keymap.set("n", "<leader>bd", function()
|
||||
if vim.bo.modified then
|
||||
vim.ui.select({ "Save & Close", "Discard & Close", "Cancel" }, {
|
||||
@@ -68,26 +52,24 @@ keymap.set("n", "<leader>bd", function()
|
||||
}, function(choice)
|
||||
if choice == "Save & Close" then
|
||||
vim.cmd("w")
|
||||
close_buffer(false)
|
||||
vim.cmd("bd")
|
||||
elseif choice == "Discard & Close" then
|
||||
close_buffer(true)
|
||||
vim.cmd("bd!")
|
||||
end
|
||||
end)
|
||||
else
|
||||
close_buffer(false)
|
||||
vim.cmd("bd")
|
||||
end
|
||||
end, { desc = "Buffer: Close (safe)" })
|
||||
|
||||
-- Force close buffer without confirmation
|
||||
keymap.set("n", "<leader>bD", function()
|
||||
close_buffer(true)
|
||||
end, { desc = "Buffer: Force close" })
|
||||
--- Force close the current buffer, discarding unsaved changes.
|
||||
keymap.set("n", "<leader>bD", ":db!<CR>", { desc = "Buffer: Force close" })
|
||||
|
||||
-- Set buftabline mappings
|
||||
--- Buftabline navigation — Ctrl+P next buffer, Ctrl+N previous buffer.
|
||||
keymap.set("n", "<C-p>", ":bnext<CR>", { noremap = true, silent = true })
|
||||
keymap.set("n", "<C-n>", ":bprev<CR>", { noremap = true, silent = true })
|
||||
|
||||
-- Coding hacks
|
||||
--- Coding shortcuts — React import, trailing comma/semicolon, run with Node.
|
||||
keymap.set(
|
||||
"n",
|
||||
"<leader>re",
|
||||
@@ -100,11 +82,7 @@ keymap.set("n", "<leader>xr", ":!node %<CR>", { desc = "Run file with node" })
|
||||
|
||||
-- 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" })
|
||||
keymap.set("n", "<leader>pd", ":DebugProject<CR>", { desc = "Debug Project" })
|
||||
|
||||
-- Copilot Chat (all Copilot keymaps moved to lua/cargdev/core/keymaps/copilot.lua)
|
||||
--- Copilot Chat — rename, explain, review, fix, optimize, and generate docs.
|
||||
keymap.set("v", "<leader>zn", ":CopilotChatRename<CR>", { desc = "Rename variable (Copilot Chat)" })
|
||||
keymap.set("n", "<leader>zc", ":CopilotChat<CR>", { desc = "Open Copilot Chat" })
|
||||
keymap.set("v", "<leader>ze", ":CopilotChatExplain<CR>", { desc = "Explain code (Copilot Chat)" })
|
||||
@@ -113,15 +91,17 @@ keymap.set("v", "<leader>zf", ":CopilotChatFix<CR>", { desc = "Fix code issues (
|
||||
keymap.set("v", "<leader>zo", ":CopilotChatOptimize<CR>", { desc = "Optimize code (Copilot Chat)" })
|
||||
keymap.set("v", "<leader>zd", ":CopilotChatDocs<CR>", { desc = "Generate docs (Copilot Chat)" })
|
||||
|
||||
-- Paste HTML as Markdown using pandoc
|
||||
keymap.set("n", "<leader>p", function()
|
||||
vim.cmd("read !pbpaste -Prefer html | pandoc -f html -t gfm")
|
||||
end, { desc = "Paste HTML clipboard as Markdown" })
|
||||
--- Paste HTML from the system clipboard as GitHub-Flavored Markdown (via pandoc).
|
||||
--- TODO: Fix this keymap
|
||||
-- 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 (under <leader>x for Trouble/Diagnostics group)
|
||||
-- =============================================================================
|
||||
|
||||
--- Quickfix list navigation — next, previous, open, close, first, last.
|
||||
keymap.set("n", "<leader>xn", ":cnext<CR>zz", { desc = "Quickfix: Next item" })
|
||||
keymap.set("n", "<leader>xp", ":cprev<CR>zz", { desc = "Quickfix: Previous item" })
|
||||
keymap.set("n", "<leader>xo", ":copen<CR>", { desc = "Quickfix: Open list" })
|
||||
@@ -129,7 +109,7 @@ keymap.set("n", "<leader>xq", ":cclose<CR>", { desc = "Quickfix: Close list" })
|
||||
keymap.set("n", "<leader>xf", ":cfirst<CR>zz", { desc = "Quickfix: First item" })
|
||||
keymap.set("n", "<leader>xl", ":clast<CR>zz", { desc = "Quickfix: Last item" })
|
||||
|
||||
-- Location list navigation
|
||||
--- Location list navigation — next, previous, open, close.
|
||||
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" })
|
||||
|
||||
@@ -1,125 +1,140 @@
|
||||
-- Plugin-specific keymaps
|
||||
--- Plugin-specific keymaps. Centralizes keybindings for third-party plugins: NvimTree, Comment,
|
||||
--- LazyGit, DAP/DAP-UI, Trouble, ToggleTerm, sessions, formatting,
|
||||
--- Substitute, Surround, LeetCode, Telescope/safe_files, database clients,
|
||||
--- text wrapping, and auto-wrap controls.
|
||||
--- @module keymaps.plugins
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
-- =============================================================================
|
||||
-- PLUGIN KEYMAPS
|
||||
-- =============================================================================
|
||||
|
||||
-- NvimTree
|
||||
--- Toggle the NvimTree file explorer sidebar.
|
||||
keymap.set("n", "<leader>e", "<cmd>NvimTreeToggle<CR>", { desc = "Toggle file explorer" })
|
||||
|
||||
-- Buffer management
|
||||
--- Buffer management — cycle through listed buffers with Shift+L / Shift+H.
|
||||
keymap.set("n", "<S-l>", ":bnext<CR>", { noremap = true, silent = true })
|
||||
keymap.set("n", "<S-h>", ":bprevious<CR>", { noremap = true, silent = true })
|
||||
|
||||
-- Comment
|
||||
keymap.set("n", "<leader>/", "<cmd>lua require('Comment.api').toggle_current_linewise()<CR>", { desc = "Toggle comment" })
|
||||
keymap.set("v", "<leader>/", "<ESC><cmd>lua require('Comment.api').toggle_linewise_op(vim.fn.visualmode())<CR>", { desc = "Toggle comment" })
|
||||
--- Comment.nvim — toggle line/block comments in normal and visual mode.
|
||||
keymap.set(
|
||||
"n",
|
||||
"<leader>/",
|
||||
"<cmd>lua require('Comment.api').toggle_current_linewise()<CR>",
|
||||
{ desc = "Toggle comment" }
|
||||
)
|
||||
keymap.set(
|
||||
"v",
|
||||
"<leader>/",
|
||||
"<ESC><cmd>lua require('Comment.api').toggle_linewise_op(vim.fn.visualmode())<CR>",
|
||||
{ desc = "Toggle comment" }
|
||||
)
|
||||
|
||||
-- Git
|
||||
--- Open LazyGit in a floating terminal.
|
||||
keymap.set("n", "<leader>gg", "<cmd>LazyGit<CR>", { desc = "LazyGit" })
|
||||
|
||||
-- DAP
|
||||
keymap.set("n", "<leader>db", "<cmd>lua require'dap'.toggle_breakpoint()<cr>", { desc = "Toggle breakpoint" })
|
||||
keymap.set("n", "<leader>dcc", "<cmd>lua require'dap'.continue()<cr>", { desc = "Continue" })
|
||||
keymap.set("n", "<leader>di", "<cmd>lua require'dap'.step_into()<cr>", { desc = "Step into" })
|
||||
keymap.set("n", "<leader>do", "<cmd>lua require'dap'.step_over()<cr>", { desc = "Step over" })
|
||||
keymap.set("n", "<leader>dO", "<cmd>lua require'dap'.step_out()<cr>", { desc = "Step out" })
|
||||
keymap.set("n", "<leader>dr", "<cmd>lua require'dap'.repl.toggle()<cr>", { desc = "Toggle REPL" })
|
||||
keymap.set("n", "<leader>dl", "<cmd>lua require'dap'.run_last()<cr>", { desc = "Run last" })
|
||||
keymap.set("n", "<leader>du", "<cmd>lua require'dapui'.toggle()<cr>", { desc = "Toggle DAP UI" })
|
||||
keymap.set("n", "<leader>dt", "<cmd>lua require'dapui'.float_element()<cr>", { desc = "Float element" })
|
||||
--- Trouble — diagnostics, workspace errors, location list, and quickfix viewer.
|
||||
keymap.set("n", "<leader>Xx", "<cmd>TroubleToggle<cr>", { desc = "Toggle Trouble" })
|
||||
keymap.set("n", "<leader>Xw", "<cmd>TroubleToggle workspace_diagnostics<cr>", { desc = "Workspace diagnostics" })
|
||||
keymap.set("n", "<leader>Xd", "<cmd>TroubleToggle document_diagnostics<cr>", { desc = "Document diagnostics" })
|
||||
keymap.set("n", "<leader>Xl", "<cmd>TroubleToggle loclist<cr>", { desc = "Location list" })
|
||||
keymap.set("n", "<leader>Xq", "<cmd>TroubleToggle quickfix<cr>", { desc = "Quickfix list" })
|
||||
|
||||
-- Trouble
|
||||
keymap.set("n", "<leader>xx", "<cmd>TroubleToggle<cr>", { desc = "Toggle Trouble" })
|
||||
keymap.set("n", "<leader>xw", "<cmd>TroubleToggle workspace_diagnostics<cr>", { desc = "Workspace diagnostics" })
|
||||
keymap.set("n", "<leader>xd", "<cmd>TroubleToggle document_diagnostics<cr>", { desc = "Document diagnostics" })
|
||||
keymap.set("n", "<leader>xl", "<cmd>TroubleToggle loclist<cr>", { desc = "Location list" })
|
||||
keymap.set("n", "<leader>xq", "<cmd>TroubleToggle quickfix<cr>", { desc = "Quickfix list" })
|
||||
|
||||
-- Terminal
|
||||
--- ToggleTerm — open terminals as float, horizontal, or vertical splits.
|
||||
keymap.set("n", "<leader>tf", "<cmd>ToggleTerm direction=float<cr>", { desc = "ToggleTerm float" })
|
||||
keymap.set("n", "<leader>th", "<cmd>ToggleTerm size=10 direction=horizontal<cr>", { desc = "ToggleTerm horizontal split" })
|
||||
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 (using <leader>sS and <leader>sR to avoid conflicts with substitute)
|
||||
--- Session management — save/restore sessions (uppercase S/R to avoid substitute conflicts).
|
||||
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" })
|
||||
--- Format the current buffer using the attached LSP formatter.
|
||||
--- TODO: add format buffer keymap
|
||||
--- keymap.set("n", "<leader>f", "<cmd>lua vim.lsp.buf.format()<cr>", { desc = "Format buffer" })
|
||||
|
||||
-- Substitute
|
||||
--- Substitute.nvim — operator, line, and end-of-line substitution.
|
||||
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
|
||||
--- nvim-surround — add, delete, and replace surrounding pairs.
|
||||
keymap.set("n", "<leader>sa", "<cmd>lua require('nvim-surround').surround_add()<cr>", { desc = "Add surrounding" })
|
||||
keymap.set("n", "<leader>sd", "<cmd>lua require('nvim-surround').surround_delete()<cr>", { desc = "Delete surrounding" })
|
||||
keymap.set("n", "<leader>sr", "<cmd>lua require('nvim-surround').surround_replace()<cr>", { desc = "Replace surrounding" })
|
||||
keymap.set(
|
||||
"n",
|
||||
"<leader>sd",
|
||||
"<cmd>lua require('nvim-surround').surround_delete()<cr>",
|
||||
{ desc = "Delete surrounding" }
|
||||
)
|
||||
keymap.set(
|
||||
"n",
|
||||
"<leader>sr",
|
||||
"<cmd>lua require('nvim-surround').surround_replace()<cr>",
|
||||
{ desc = "Replace surrounding" }
|
||||
)
|
||||
|
||||
-- Git conflicts (moved to lua/cargdev/core/keymaps/gitconflict.lua)
|
||||
|
||||
-- LeetCode
|
||||
keymap.set("n", "<leader>lr", "<cmd>Leet run<CR>", { desc = "LeetCode: Run Code" })
|
||||
keymap.set("n", "<leader>ls", "<cmd>Leet submit<CR>", { desc = "LeetCode: Submit Code" })
|
||||
keymap.set("n", "<leader>ld", "<cmd>Leet daily<CR>", { desc = "LeetCode: Daily Challenge" })
|
||||
keymap.set("n", "<leader>ll", "<cmd>Leet list<CR>", { desc = "LeetCode: List Problems" })
|
||||
keymap.set("n", "<leader>lc", "<cmd>Leet console<CR>", { desc = "LeetCode: Open Console" })
|
||||
keymap.set("n", "<leader>lu", "<cmd>Leet cookie update<CR>", { desc = "LeetCode: Update Cookie" })
|
||||
keymap.set("n", "<leader>lh", "<cmd>Leet hints<cr>", { desc = "LeetCode: Open hints" })
|
||||
keymap.set("n", "<leader>lls", "<cmd>Leet last<cr>", { desc = "LeetCode: Get latest submission" })
|
||||
--- Run project command via project_commands module.
|
||||
keymap.set(
|
||||
"n",
|
||||
"<leader>p",
|
||||
"<cmd>lua require('cargdev.core.function.project_commands').run_project()<cr>",
|
||||
{ desc = "Run project" }
|
||||
)
|
||||
|
||||
-- Linting
|
||||
keymap.set("n", "<leader>l", "<cmd>Lint<cr>", { desc = "Lint current file" })
|
||||
|
||||
-- Project commands
|
||||
keymap.set("n", "<leader>p", "<cmd>lua require('cargdev.core.function.project_commands').run_project()<cr>", { desc = "Run project" })
|
||||
|
||||
-- Console log (different from personal <leader>con)
|
||||
--- Insert a `console.log()` snippet on the line below and enter insert mode.
|
||||
keymap.set("n", "<leader>cl", "oconsole.log()<ESC>i", { desc = "Add console.log" })
|
||||
|
||||
-- DAP UI reset
|
||||
keymap.set("n", "<leader>drt", "<cmd>lua require('dapui').float_element()<cr>", { desc = "Reset DAP UI layout" })
|
||||
|
||||
-- DAP commands
|
||||
keymap.set("n", "<leader>dco", "<cmd>lua require('dap').commands()<cr>", { desc = "DAP commands" })
|
||||
keymap.set("n", "<leader>dcf", "<cmd>lua require('dap').list_breakpoints()<cr>", { desc = "DAP configs" })
|
||||
keymap.set("n", "<leader>dcb", "<cmd>lua require('dap').list_breakpoints()<cr>", { desc = "List breakpoints" })
|
||||
|
||||
-- Step out
|
||||
keymap.set("n", "<leader>dot", "<cmd>lua require('dap').step_out()<cr>", { desc = "Step out" })
|
||||
|
||||
-- Todos in trouble
|
||||
--- Open TODO comments in the Trouble panel.
|
||||
keymap.set("n", "<leader>xt", "<cmd>TodoTrouble<cr>", { desc = "Open todos in trouble" })
|
||||
|
||||
-- Surround mappings
|
||||
--- nvim-surround classic-style mappings (ys, yss, yS, ySS).
|
||||
keymap.set("n", "ys", "<cmd>lua require('nvim-surround').surround_add()<cr>", { desc = "Add surrounding" })
|
||||
keymap.set("n", "yss", "<cmd>lua require('nvim-surround').surround_add()<cr>", { desc = "Add surrounding to line" })
|
||||
keymap.set("n", "yS", "<cmd>lua require('nvim-surround').surround_add()<cr>", { desc = "Add surrounding on new lines" })
|
||||
keymap.set("n", "ySS", "<cmd>lua require('nvim-surround').surround_add()<cr>", { desc = "Add surrounding to line on new lines" })
|
||||
keymap.set(
|
||||
"n",
|
||||
"ySS",
|
||||
"<cmd>lua require('nvim-surround').surround_add()<cr>",
|
||||
{ desc = "Add surrounding to line on new lines" }
|
||||
)
|
||||
|
||||
-- Comment mappings
|
||||
--- Comment.nvim classic-style mappings (gc, gcc, gco, gcO, gcA, gb, gbc).
|
||||
keymap.set("n", "gc", "<cmd>lua require('Comment.api').toggle_current_linewise()<cr>", { desc = "Toggle comment" })
|
||||
keymap.set("n", "gcc", "<cmd>lua require('Comment.api').toggle_current_linewise()<cr>", { desc = "Toggle current line comment" })
|
||||
keymap.set(
|
||||
"n",
|
||||
"gcc",
|
||||
"<cmd>lua require('Comment.api').toggle_current_linewise()<cr>",
|
||||
{ desc = "Toggle current line comment" }
|
||||
)
|
||||
keymap.set("n", "gco", "<cmd>lua require('Comment.api').insert_below()<cr>", { desc = "Insert comment below" })
|
||||
keymap.set("n", "gcO", "<cmd>lua require('Comment.api').insert_above()<cr>", { desc = "Insert comment above" })
|
||||
keymap.set("n", "gcA", "<cmd>lua require('Comment.api').insert_eol()<cr>", { desc = "Insert comment at end of line" })
|
||||
keymap.set("n", "gb", "<cmd>lua require('Comment.api').toggle_current_blockwise()<cr>", { desc = "Toggle block comment" })
|
||||
keymap.set("n", "gbc", "<cmd>lua require('Comment.api').toggle_current_blockwise()<cr>", { desc = "Toggle current block comment" })
|
||||
keymap.set(
|
||||
"n",
|
||||
"gb",
|
||||
"<cmd>lua require('Comment.api').toggle_current_blockwise()<cr>",
|
||||
{ desc = "Toggle block comment" }
|
||||
)
|
||||
keymap.set(
|
||||
"n",
|
||||
"gbc",
|
||||
"<cmd>lua require('Comment.api').toggle_current_blockwise()<cr>",
|
||||
{ desc = "Toggle current block comment" }
|
||||
)
|
||||
|
||||
-- =============================================================================
|
||||
-- TELESCOPE KEYMAPS (Enhanced with safe file searching)
|
||||
-- =============================================================================
|
||||
|
||||
-- Safe file search (prevents LSP errors and image freezing)
|
||||
keymap.set("n", "<leader>ff", "<cmd>Telescope safe_files find_files<CR>", { desc = "Find files (safe)" })
|
||||
keymap.set("n", "<leader>fs", "<cmd>Telescope live_grep<CR>", { desc = "Live grep (safe)" })
|
||||
keymap.set("n", "<leader>fg", "<cmd>Telescope git_files<CR>", { desc = "Git files (safe)" })
|
||||
keymap.set("n", "<leader>ft", "<cmd>Telescope text_files find_files<CR>", { desc = "Text files only" })
|
||||
|
||||
-- Regular telescope (use with caution)
|
||||
--- Unfiltered Telescope file search (may include binaries — use with caution).
|
||||
keymap.set("n", "<leader>fF", "<cmd>Telescope find_files<CR>", { desc = "Find files (all)" })
|
||||
|
||||
-- =============================================================================
|
||||
@@ -158,12 +173,12 @@ keymap.set("n", "<leader>fF", "<cmd>Telescope find_files<CR>", { desc = "Find fi
|
||||
-- keymap.set("n", "<leader>dus", "<cmd>DBUISaveBuffer<CR>", { desc = "Save database buffer" })
|
||||
-- keymap.set("n", "<leader>dul", "<cmd>DBUILoadBuffer<CR>", { desc = "Load database buffer" })
|
||||
|
||||
-- Redis specific
|
||||
--- Redis CLI — open, list keys, show info.
|
||||
keymap.set("n", "<leader>rds", "<cmd>Redis<CR>", { desc = "Open Redis" })
|
||||
keymap.set("n", "<leader>rdk", "<cmd>RedisKeys<CR>", { desc = "Show Redis keys" })
|
||||
keymap.set("n", "<leader>rdi", "<cmd>RedisInfo<CR>", { desc = "Show Redis info" })
|
||||
|
||||
-- MongoDB specific
|
||||
--- MongoDB — open shell, connect, disconnect.
|
||||
keymap.set("n", "<leader>mdb", "<cmd>MongoDB<CR>", { desc = "Open MongoDB" })
|
||||
keymap.set("n", "<leader>mdc", "<cmd>MongoDBConnect<CR>", { desc = "Connect to MongoDB" })
|
||||
keymap.set("n", "<leader>mdd", "<cmd>MongoDBDisconnect<CR>", { desc = "Disconnect from MongoDB" })
|
||||
@@ -172,30 +187,30 @@ keymap.set("n", "<leader>mdd", "<cmd>MongoDBDisconnect<CR>", { desc = "Disconnec
|
||||
-- NATIVE AUTO WRAPPER KEYMAPS
|
||||
-- =============================================================================
|
||||
|
||||
-- Text wrapping controls
|
||||
--- Text wrapping controls — toggle wrap, linebreak, and column guide.
|
||||
keymap.set("n", "<leader>tw", "<cmd>set wrap!<cr>", { desc = "Toggle line wrapping" })
|
||||
keymap.set("n", "<leader>tl", "<cmd>set linebreak!<cr>", { desc = "Toggle line break" })
|
||||
keymap.set("n", "<leader>tc", "<cmd>set colorcolumn=80<cr>", { desc = "Show 80 char column" })
|
||||
keymap.set("n", "<leader>tC", "<cmd>set colorcolumn=<cr>", { desc = "Hide column guide" })
|
||||
keymap.set("n", "<leader>tx", "<cmd>set colorcolumn=80<cr>", { desc = "Show 80 char column" })
|
||||
keymap.set("n", "<leader>tH", "<cmd>set colorcolumn=<cr>", { desc = "Hide column guide" })
|
||||
|
||||
-- Format text using native Neovim commands
|
||||
keymap.set("n", "<leader>tf", "gqap", { desc = "Format paragraph" })
|
||||
--- Format text using native Neovim `gq` command (paragraph, selection, file).
|
||||
keymap.set("n", "<leader>tpg", "gqap", { desc = "Format paragraph" })
|
||||
keymap.set("v", "<leader>tf", "gq", { desc = "Format selection" })
|
||||
keymap.set("n", "<leader>tF", "gggqG", { desc = "Format entire file" })
|
||||
|
||||
-- Text width adjustments
|
||||
--- Text width adjustments — set to 80, 100, 120, or disable (0).
|
||||
keymap.set("n", "<leader>t80", "<cmd>set textwidth=80<cr>", { desc = "Set text width to 80" })
|
||||
keymap.set("n", "<leader>t100", "<cmd>set textwidth=100<cr>", { desc = "Set text width to 100" })
|
||||
keymap.set("n", "<leader>t120", "<cmd>set textwidth=120<cr>", { desc = "Set text width to 120" })
|
||||
keymap.set("n", "<leader>t0", "<cmd>set textwidth=0<cr>", { desc = "Disable text width" })
|
||||
|
||||
-- Auto-wrap controls
|
||||
--- Auto-wrap controls — toggle `formatoptions` flags for text and comments.
|
||||
keymap.set("n", "<leader>ta", "<cmd>set formatoptions+=t<cr>", { desc = "Enable auto-wrap text" })
|
||||
keymap.set("n", "<leader>tA", "<cmd>set formatoptions-=t<cr>", { desc = "Disable auto-wrap text" })
|
||||
keymap.set("n", "<leader>tc", "<cmd>set formatoptions+=c<cr>", { desc = "Enable auto-wrap comments" })
|
||||
keymap.set("n", "<leader>tC", "<cmd>set formatoptions-=c<cr>", { desc = "Disable auto-wrap comments" })
|
||||
|
||||
-- Indent and wrap
|
||||
--- Indent and wrap — toggle break indent and show/hide break indicator.
|
||||
keymap.set("n", "<leader>ti", "<cmd>set breakindent!<cr>", { desc = "Toggle break indent" })
|
||||
keymap.set("n", "<leader>ts", "<cmd>set showbreak=↪ <cr>", { desc = "Show break indicator" })
|
||||
keymap.set("n", "<leader>tS", "<cmd>set showbreak=<cr>", { desc = "Hide break indicator" })
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
-- Project Run/Debug keymaps
|
||||
--- Project run and debug keymaps.
|
||||
--- Provides `<leader>p` prefixed shortcuts that invoke the `:RunProject`
|
||||
--- and `:DebugProject` user commands defined in `project_commands.lua`.
|
||||
--- @module keymaps.project
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
--- Execute the project run command from `.nvim/project.lua`.
|
||||
keymap.set("n", "<leader>pr", ":RunProject<CR>", { desc = "Run Project" })
|
||||
|
||||
--- Execute the project debug command from `.nvim/project.lua`.
|
||||
keymap.set("n", "<leader>pd", ":DebugProject<CR>", { desc = "Debug Project" })
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
-- Snacks keymaps (replacing Telescope)
|
||||
--- Snacks.nvim picker keymaps (replacing Telescope for most navigation).
|
||||
--- Uses snacks.picker for file, grep, buffer, marks, keymaps, and command
|
||||
--- searching. Falls back to Telescope for git operations and TODO search
|
||||
--- where Snacks pickers are not yet available.
|
||||
--- @module keymaps.snacks
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
-- =============================================================================
|
||||
-- SNACKS NAVIGATION
|
||||
-- =============================================================================
|
||||
|
||||
-- File navigation
|
||||
--- File navigation — find files, live grep, grep string, recent files.
|
||||
keymap.set("n", "<leader>ff", "<cmd>lua require('snacks.picker').files()<cr>", { desc = "Find files" })
|
||||
keymap.set("n", "<leader>fs", "<cmd>lua require('snacks.picker').grep()<cr>", { desc = "Live grep" })
|
||||
keymap.set("n", "<leader>fc", "<cmd>lua require('snacks.picker').grep_string()<cr>", { desc = "Grep string" })
|
||||
keymap.set("n", "<leader>fr", "<cmd>lua require('snacks.picker').oldfiles()<cr>", { desc = "Recent files" })
|
||||
|
||||
-- Buffer and session management
|
||||
--- Buffer and session management — buffers, help tags, marks, keymaps, commands.
|
||||
keymap.set("n", "<leader>fb", "<cmd>lua require('snacks.picker').buffers()<cr>", { desc = "Find buffers" })
|
||||
keymap.set("n", "<leader>fh", "<cmd>lua require('snacks.picker').help_tags()<cr>", { desc = "Help tags" })
|
||||
keymap.set("n", "<leader>fm", "<cmd>lua require('snacks.picker').marks()<cr>", { desc = "Find marks" })
|
||||
keymap.set("n", "<leader>fk", "<cmd>lua require('snacks.picker').keymaps()<cr>", { desc = "Find keymaps" })
|
||||
keymap.set("n", "<leader>fC", "<cmd>lua require('snacks.picker').commands()<cr>", { desc = "Find commands" })
|
||||
|
||||
-- Git (using Telescope for git features as Snacks may not have all git pickers)
|
||||
--- Git — commits, buffer commits, branches, and status (via Telescope fallback).
|
||||
keymap.set("n", "<leader>fG", "<cmd>Telescope git_commits<cr>", { desc = "Git commits" })
|
||||
keymap.set("n", "<leader>fB", "<cmd>Telescope git_bcommits<cr>", { desc = "Git buffer commits" })
|
||||
keymap.set("n", "<leader>fg", "<cmd>Telescope git_branches<cr>", { desc = "Git branches" })
|
||||
keymap.set("n", "<leader>gs", "<cmd>Telescope git_status<cr>", { desc = "Git status" })
|
||||
|
||||
-- Todos (keep Telescope for todos as Snacks may not have this)
|
||||
--- Search TODO/FIXME/HACK comments (via Telescope — Snacks lacks this picker).
|
||||
keymap.set("n", "<leader>ft", "<cmd>TodoTelescope<cr>", { desc = "Find todos" })
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
-- Sudoku keymaps
|
||||
-- WARNING: <leader>sng is mapped to two different commands below. Only the last one will take effect in Neovim.
|
||||
-- Consider changing one of the mappings if you want both actions available.
|
||||
local keymap = vim.keymap
|
||||
|
||||
keymap.set("n", "<leader>si1", ":Sudoku insert=1<CR>", { desc = "Add number 1" })
|
||||
keymap.set("n", "<leader>si2", ":Sudoku insert=2<CR>", { desc = "Add number 2" })
|
||||
keymap.set("n", "<leader>si3", ":Sudoku insert=3<CR>", { desc = "Add number 3" })
|
||||
keymap.set("n", "<leader>si4", ":Sudoku insert=4<CR>", { desc = "Add number 4" })
|
||||
keymap.set("n", "<leader>si5", ":Sudoku insert=5<CR>", { desc = "Add number 5" })
|
||||
keymap.set("n", "<leader>si6", ":Sudoku insert=6<CR>", { desc = "Add number 6" })
|
||||
keymap.set("n", "<leader>si7", ":Sudoku insert=7<CR>", { desc = "Add number 7" })
|
||||
keymap.set("n", "<leader>si8", ":Sudoku insert=8<CR>", { desc = "Add number 8" })
|
||||
keymap.set("n", "<leader>si9", ":Sudoku insert=9<CR>", { desc = "Add number 9" })
|
||||
keymap.set("n", "<leader>scc", ":Sudoku clear_cell<CR>", { desc = "Clear current cell" })
|
||||
keymap.set("n", "<leader>su", ":Sudoku undo<CR>", { desc = "Undo last action" })
|
||||
keymap.set("n", "<leader>sng", ":Sudoku new_game<CR>", { desc = "Starts new game" })
|
||||
keymap.set("n", "<leader>sng", ":Sudoku view=settings<CR>", { desc = "Display the settings" })
|
||||
@@ -1,12 +1,27 @@
|
||||
-- nvim-ufo folding keymaps
|
||||
--- nvim-ufo folding keymaps.
|
||||
--- Overrides the default `z` fold commands with nvim-ufo equivalents for
|
||||
--- improved fold rendering. Also overrides `K` to peek folded lines under
|
||||
--- the cursor, falling back to LSP hover when no fold is present.
|
||||
--- All keymaps are only registered when nvim-ufo loads successfully.
|
||||
--- @module keymaps.ufo
|
||||
|
||||
local ok_ufo, ufo = pcall(require, "ufo")
|
||||
local keymap = vim.keymap.set
|
||||
|
||||
if ok_ufo then
|
||||
--- Open every fold in the buffer.
|
||||
keymap("n", "zR", ufo.openAllFolds, { desc = "Open all folds" })
|
||||
|
||||
--- Close every fold in the buffer.
|
||||
keymap("n", "zM", ufo.closeAllFolds, { desc = "Close all folds" })
|
||||
|
||||
--- Open folds except specific kinds (e.g. imports, comments).
|
||||
keymap("n", "zr", ufo.openFoldsExceptKinds, { desc = "Open folds except kinds" })
|
||||
|
||||
--- Incrementally close folds by level.
|
||||
keymap("n", "zm", ufo.closeFoldsWith, { desc = "Close folds with" })
|
||||
|
||||
--- Peek the folded lines under the cursor; fall back to LSP hover.
|
||||
keymap("n", "K", function()
|
||||
local winid = ufo.peekFoldedLinesUnderCursor()
|
||||
if not winid then
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
-- Window management keymaps
|
||||
--- Window and tab management keymaps.
|
||||
--- Provides split creation/closing, tab navigation, and Ctrl-based
|
||||
--- resize shortcuts for both vertical and horizontal splits.
|
||||
--- @module keymaps.window
|
||||
|
||||
local keymap = vim.keymap
|
||||
|
||||
--- Split management — vertical, horizontal, equalize, and close.
|
||||
keymap.set("n", "<leader>sv", "<C-w>v", { desc = "Split window vertically" })
|
||||
keymap.set("n", "<leader>sh", "<C-w>s", { desc = "Split window horizontally" })
|
||||
keymap.set("n", "<leader>se", "<C-w>=", { desc = "Make splits equal size" })
|
||||
keymap.set("n", "<leader>sx", "<cmd>close<CR>", { desc = "Close current split" })
|
||||
|
||||
--- Tab management — new, close, next, previous, and open buffer in new tab.
|
||||
keymap.set("n", "<leader>to", "<cmd>tabnew<CR>", { desc = "Open new tab" })
|
||||
keymap.set("n", "<leader>tx", "<cmd>tabclose<CR>", { desc = "Close current tab" })
|
||||
keymap.set("n", "<leader>cx", "<cmd>tabclose<CR>", { desc = "Close current tab" })
|
||||
keymap.set("n", "<leader>tn", "<cmd>tabn<CR>", { desc = "Go to next tab" })
|
||||
keymap.set("n", "<leader>tp", "<cmd>tabp<CR>", { desc = "Go to previous tab" })
|
||||
keymap.set("n", "<leader>tf", "<cmd>tabnew %<CR>", { desc = "Open current buffer in new tab" })
|
||||
keymap.set("n", "<leader>tt", "<cmd>tabnew %<CR>", { desc = "Open current buffer in new tab" })
|
||||
|
||||
--- Resize splits — Ctrl+H/L for width, Ctrl+K/J for height (step of 5).
|
||||
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 })
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
-- ============================================================================
|
||||
-- CODETYPER.NVIM: AI-powered coding assistant plugin
|
||||
-- ============================================================================
|
||||
-- A local development plugin that provides AI-assisted coding capabilities
|
||||
-- using various LLM providers (Ollama, Claude, OpenAI, Gemini, Copilot).
|
||||
-- Features include: inline code transformation with /@ @/ tags, Ask panel
|
||||
-- for interactive queries, Agent panel for autonomous coding tasks,
|
||||
-- Tree-sitter integration for scope detection, and diff review.
|
||||
--
|
||||
-- Key keymaps:
|
||||
-- <leader>co - Open Coder view <leader>ca - Open Ask panel
|
||||
-- <leader>ct - Toggle Coder view <leader>cg - Open Agent panel
|
||||
-- <leader>cp - Process prompt <leader>cd - Open Diff Review
|
||||
-- <leader>ctt - Transform tag at cursor (also works in visual mode)
|
||||
-- ============================================================================
|
||||
|
||||
-- Get local config (loaded in core/init.lua)
|
||||
local local_cfg = vim.g.cargdev_local or {}
|
||||
|
||||
-- Skip plugin if local config is missing required values
|
||||
if not local_cfg.CODE_TYPER_DIR then
|
||||
return {}
|
||||
end
|
||||
|
||||
return {
|
||||
-- Codetyper.nvim - AI-powered coding partner
|
||||
-- Local development version
|
||||
dir = local_cfg.CODE_TYPER_DIR,
|
||||
name = "codetyper.nvim",
|
||||
lazy = false, -- Load on startup to create .coder folder
|
||||
priority = 100, -- Load early
|
||||
dependencies = {
|
||||
"nvim-lua/plenary.nvim", -- Required: async utilities
|
||||
-- "nvim-treesitter/nvim-treesitter", -- Required: scope detection via Tree-sitter
|
||||
-- "nvim-treesitter/nvim-treesitter-textobjects", -- Optional: better text object support
|
||||
"MunifTanjim/nui.nvim", -- Optional: UI components
|
||||
},
|
||||
event = {
|
||||
"BufReadPre *.coder.*",
|
||||
"BufNewFile *.coder.*",
|
||||
},
|
||||
cmd = {
|
||||
"Coder",
|
||||
"CoderOpen",
|
||||
"CoderClose",
|
||||
"CoderToggle",
|
||||
"CoderProcess",
|
||||
"CoderTree",
|
||||
"CoderTreeView",
|
||||
-- Ask commands
|
||||
"CoderAsk",
|
||||
"CoderAskToggle",
|
||||
"CoderAskClear",
|
||||
-- Agent commands
|
||||
"CoderAgent",
|
||||
"CoderAgentToggle",
|
||||
"CoderAgentStop",
|
||||
"CoderMode",
|
||||
},
|
||||
keys = {
|
||||
-- Coder view commands
|
||||
{ "<leader>co", "<cmd>Coder open<cr>", desc = "Coder: Open view" },
|
||||
{ "<leader>cC", "<cmd>Coder close<cr>", desc = "Coder: Close view" },
|
||||
{ "<leader>ct", "<cmd>Coder toggle<cr>", desc = "Coder: Toggle view" },
|
||||
{ "<leader>cp", "<cmd>Coder process<cr>", desc = "Coder: Process prompt" },
|
||||
{ "<leader>cs", "<cmd>Coder status<cr>", desc = "Coder: Show status" },
|
||||
{ "<leader>cf", "<cmd>Coder focus<cr>", desc = "Coder: Switch focus" },
|
||||
{ "<leader>cv", "<cmd>Coder tree-view<cr>", desc = "Coder: View tree" },
|
||||
{ "<leader>cr", "<cmd>Coder tree<cr>", desc = "Coder: Refresh tree" },
|
||||
-- Ask panel commands
|
||||
{ "<leader>ca", "<cmd>Coder ask<cr>", desc = "Coder: Open Ask panel" },
|
||||
{ "<leader>cA", "<cmd>Coder ask-toggle<cr>", desc = "Coder: Toggle Ask panel" },
|
||||
{ "<leader>cx", "<cmd>Coder ask-clear<cr>", desc = "Coder: Clear Ask history" },
|
||||
-- Agent panel commands
|
||||
{ "<leader>cg", "<cmd>Coder agent<cr>", desc = "Coder: Open Agent panel" },
|
||||
{ "<leader>cG", "<cmd>Coder agent-toggle<cr>", desc = "Coder: Toggle Agent panel" },
|
||||
{ "<leader>cS", "<cmd>Coder agent-stop<cr>", desc = "Coder: Stop Agent" },
|
||||
{ "<leader>cd", "<cmd>CoderDiffReview<cr>", desc = "Coder: Open Diff Review" },
|
||||
-- Transform commands (inline /@ @/ replacement)
|
||||
{ "<leader>ctt", mode = "n", desc = "Coder: Transform tag at cursor" },
|
||||
{ "<leader>ctt", mode = "v", desc = "Coder: Transform selected tags" },
|
||||
{ "<leader>ctT", "<cmd>Coder transform<cr>", desc = "Coder: Transform all tags" },
|
||||
},
|
||||
config = function()
|
||||
require("codetyper").setup({
|
||||
llm = {
|
||||
-- Available providers: "ollama", "claude", "openai", "gemini", "copilot"
|
||||
provider = "copilot", -- Using GitHub Copilot
|
||||
|
||||
-- Ollama (local LLM)
|
||||
ollama = {
|
||||
host = "http://localhost:11434",
|
||||
model = "deepseek-coder:6.7b",
|
||||
-- model = "codellama:7b",
|
||||
-- model = "qwen2.5-coder:7b",
|
||||
},
|
||||
|
||||
-- GitHub Copilot (uses OAuth from copilot.vim/copilot.lua)
|
||||
copilot = {
|
||||
model = "gpt-4o", -- or "gpt-4", "gpt-3.5-turbo"
|
||||
},
|
||||
},
|
||||
window = {
|
||||
width = 0.25, -- 1/4 of window
|
||||
position = "left",
|
||||
border = "rounded",
|
||||
},
|
||||
patterns = {
|
||||
open_tag = "/@",
|
||||
close_tag = "@/",
|
||||
file_pattern = "*.coder.*",
|
||||
},
|
||||
auto_gitignore = true,
|
||||
auto_open_ask = false, -- Don't auto-open Ask panel on startup
|
||||
scheduler = {
|
||||
enabled = true,
|
||||
ollama_scout = false, -- Disabled since using Copilot directly
|
||||
escalation_threshold = 0.7,
|
||||
max_concurrent = 2,
|
||||
completion_delay_ms = 100, -- Delay before checking completion visibility
|
||||
apply_delay_ms = 2000, -- Wait 2 seconds before applying code
|
||||
},
|
||||
})
|
||||
end,
|
||||
}
|
||||
@@ -1,27 +1,33 @@
|
||||
-- ============================================================================
|
||||
-- COPILOT: GitHub AI code completion and chat
|
||||
-- ============================================================================
|
||||
-- AI-powered code suggestions that appear as ghost text while typing.
|
||||
-- Includes copilot-cmp for completion menu integration and codecompanion
|
||||
-- for AI chat/refactoring. Disabled for LaTeX files. Accept with <C-l>.
|
||||
-- AI-powered code suggestions (ghost text + cmp menu) and chat.
|
||||
-- Autocomplete: <C-l> accept ghost text, also shows in cmp menu.
|
||||
-- Chat: <leader>cc toggle, <leader>cq quick chat, <leader>ce explain.
|
||||
--
|
||||
-- MODEL SELECTION:
|
||||
-- Chat: :CopilotChatModels (pick from gpt-4o, claude-sonnet-4, o3-mini, etc.)
|
||||
-- Autocomplete: controlled server-side by GitHub, not user-selectable.
|
||||
-- ============================================================================
|
||||
return {
|
||||
-- Copilot core: ghost text suggestions + LSP backend
|
||||
{
|
||||
"zbirenbaum/copilot.lua",
|
||||
cmd = "Copilot",
|
||||
event = "InsertEnter",
|
||||
config = function()
|
||||
require("copilot").setup({
|
||||
copilot_model = "gpt-41-copilot",
|
||||
panel = {
|
||||
enabled = true,
|
||||
auto_refresh = false,
|
||||
layout = {
|
||||
position = "bottom", -- | top | left | right
|
||||
position = "bottom",
|
||||
ratio = 0.4,
|
||||
},
|
||||
},
|
||||
suggestion = {
|
||||
enabled = true, -- Codetyper will use copilot when available
|
||||
enabled = true,
|
||||
auto_trigger = true,
|
||||
debounce = 75,
|
||||
keymap = {
|
||||
@@ -39,10 +45,10 @@ return {
|
||||
hgcommit = true,
|
||||
svn = true,
|
||||
cvs = true,
|
||||
tex = false, -- Disable Copilot for LaTeX files by default
|
||||
tex = false,
|
||||
["."] = true,
|
||||
},
|
||||
copilot_node_command = "node", -- Node.js version must be > 16.x
|
||||
copilot_node_command = "node",
|
||||
server_opts_overrides = {},
|
||||
})
|
||||
|
||||
@@ -50,18 +56,18 @@ return {
|
||||
vim.api.nvim_create_autocmd({ "FileType", "BufEnter" }, {
|
||||
pattern = "tex",
|
||||
callback = function()
|
||||
-- Safely dismiss any active suggestions
|
||||
local ok, suggestion = pcall(require, "copilot.suggestion")
|
||||
if ok and suggestion and suggestion.is_visible() then
|
||||
suggestion.dismiss()
|
||||
end
|
||||
-- Disable Copilot for this buffer
|
||||
vim.cmd("Copilot disable")
|
||||
end,
|
||||
desc = "Disable Copilot for LaTeX files",
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
||||
-- Copilot CMP: adds Copilot as a completion source in nvim-cmp menu
|
||||
{
|
||||
"zbirenbaum/copilot-cmp",
|
||||
dependencies = { "zbirenbaum/copilot.lua" },
|
||||
@@ -69,28 +75,58 @@ return {
|
||||
require("copilot_cmp").setup()
|
||||
end,
|
||||
},
|
||||
|
||||
-- CopilotChat: full chat interface with model selection
|
||||
{
|
||||
"olimorris/codecompanion.nvim",
|
||||
"CopilotC-Nvim/CopilotChat.nvim",
|
||||
dependencies = {
|
||||
"zbirenbaum/copilot.lua",
|
||||
"nvim-lua/plenary.nvim",
|
||||
"nvim-telescope/telescope.nvim",
|
||||
},
|
||||
cmd = { "CodeCompanion" },
|
||||
build = "make tiktoken",
|
||||
cmd = {
|
||||
"CopilotChat",
|
||||
"CopilotChatToggle",
|
||||
"CopilotChatModels",
|
||||
"CopilotChatExplain",
|
||||
"CopilotChatReview",
|
||||
"CopilotChatFix",
|
||||
"CopilotChatOptimize",
|
||||
"CopilotChatDocs",
|
||||
"CopilotChatTests",
|
||||
"CopilotChatCommit",
|
||||
},
|
||||
keys = {
|
||||
{ "<leader>cc", "<cmd>CopilotChatToggle<cr>", desc = "CopilotChat: Toggle chat window" },
|
||||
{ "<leader>cq", function()
|
||||
local input = vim.fn.input("Quick Chat: ")
|
||||
if input ~= "" then
|
||||
require("CopilotChat").ask(input, { selection = require("CopilotChat.select").buffer })
|
||||
end
|
||||
end, desc = "CopilotChat: Quick chat (whole buffer)" },
|
||||
{ "<leader>ce", "<cmd>CopilotChatExplain<cr>", mode = { "n", "v" }, desc = "CopilotChat: Explain code" },
|
||||
{ "<leader>cr", "<cmd>CopilotChatReview<cr>", mode = { "n", "v" }, desc = "CopilotChat: Review code" },
|
||||
{ "<leader>cf", "<cmd>CopilotChatFix<cr>", mode = { "n", "v" }, desc = "CopilotChat: Fix code" },
|
||||
{ "<leader>co", "<cmd>CopilotChatOptimize<cr>", mode = { "n", "v" }, desc = "CopilotChat: Optimize code" },
|
||||
{ "<leader>cd", "<cmd>CopilotChatDocs<cr>", mode = { "n", "v" }, desc = "CopilotChat: Generate docs" },
|
||||
{ "<leader>ct", "<cmd>CopilotChatTests<cr>", mode = { "n", "v" }, desc = "CopilotChat: Generate tests" },
|
||||
{ "<leader>cm", "<cmd>CopilotChatModels<cr>", desc = "CopilotChat: Select model" },
|
||||
},
|
||||
config = function()
|
||||
require("codecompanion").setup({
|
||||
-- Use GitHub Copilot as the provider
|
||||
providers = {
|
||||
copilot = {
|
||||
enabled = true,
|
||||
},
|
||||
require("CopilotChat").setup({
|
||||
-- Default model (change with :CopilotChatModels at runtime)
|
||||
-- Options include: gpt-4o, claude-sonnet-4, o3-mini, gemini-2.0-flash, etc.
|
||||
model = "claude-sonnet-4",
|
||||
window = {
|
||||
layout = "vertical",
|
||||
width = 0.35,
|
||||
border = "rounded",
|
||||
},
|
||||
-- Configure the UI
|
||||
ui = {
|
||||
window = {
|
||||
width = 0.8,
|
||||
height = 0.8,
|
||||
},
|
||||
mappings = {
|
||||
complete = { insert = "<Tab>" },
|
||||
close = { normal = "q", insert = "<C-c>" },
|
||||
reset = { normal = "<C-x>", insert = "<C-x>" },
|
||||
submit_prompt = { normal = "<CR>", insert = "<C-s>" },
|
||||
},
|
||||
})
|
||||
end,
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
-- ============================================================================
|
||||
-- REST.NVIM: HTTP client for making API requests from Neovim
|
||||
-- ============================================================================
|
||||
-- A fork of rest.nvim that allows executing HTTP requests directly from
|
||||
-- .http files within Neovim. Features include request highlighting,
|
||||
-- automatic response formatting, cookie management, and environment
|
||||
-- variable support. Requires LuaRocks dependencies: mimetypes and xml2lua.
|
||||
--
|
||||
-- Key UI keybinds:
|
||||
-- H - Navigate to previous response
|
||||
-- L - Navigate to next response
|
||||
-- ============================================================================
|
||||
|
||||
return {
|
||||
"CarGDev/rest.nvim",
|
||||
build = function()
|
||||
-- Install LuaRocks dependencies for Lua 5.1 (Neovim uses LuaJIT which is Lua 5.1 compatible)
|
||||
local packages = { "mimetypes", "xml2lua" }
|
||||
for _, pkg in ipairs(packages) do
|
||||
local result = vim.fn.system("luarocks install --local --lua-version=5.1 " .. pkg .. " 2>&1")
|
||||
if vim.v.shell_error ~= 0 and not result:match("already installed") then
|
||||
vim.notify("Warning: Failed to install " .. pkg .. ": " .. result, vim.log.levels.WARN)
|
||||
end
|
||||
end
|
||||
end,
|
||||
dependencies = {
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
opts = function(_, opts)
|
||||
opts.ensure_installed = opts.ensure_installed or {}
|
||||
table.insert(opts.ensure_installed, "http")
|
||||
end,
|
||||
},
|
||||
config = function()
|
||||
-- Verify LuaRocks dependencies are available
|
||||
local function check_dependency(name)
|
||||
local success = pcall(require, name)
|
||||
if not success then
|
||||
vim.notify(
|
||||
string.format(
|
||||
"rest.nvim: Missing dependency '%s'. Please run: luarocks install --local %s",
|
||||
name,
|
||||
name
|
||||
),
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
-- Check for required dependencies
|
||||
check_dependency("mimetypes")
|
||||
check_dependency("xml2lua")
|
||||
|
||||
-- Basic configuration for rest.nvim
|
||||
vim.g.rest_nvim = {
|
||||
-- Enable request highlighting
|
||||
highlight = {
|
||||
enable = true,
|
||||
timeout = 750,
|
||||
},
|
||||
-- Enable response formatting
|
||||
response = {
|
||||
hooks = {
|
||||
format = true,
|
||||
decode_url = true,
|
||||
},
|
||||
},
|
||||
-- Enable cookies
|
||||
cookies = {
|
||||
enable = true,
|
||||
},
|
||||
-- Enable environment variables
|
||||
env = {
|
||||
enable = true,
|
||||
pattern = ".*%.env.*",
|
||||
},
|
||||
-- UI configuration
|
||||
ui = {
|
||||
winbar = true,
|
||||
keybinds = {
|
||||
prev = "H",
|
||||
next = "L",
|
||||
},
|
||||
},
|
||||
}
|
||||
end,
|
||||
}
|
||||
@@ -88,7 +88,9 @@ return {
|
||||
require("mason-nvim-dap").setup({
|
||||
ensure_installed = { "python", "js", "javadbg", "javatest" },
|
||||
automatic_installation = true,
|
||||
handlers = {},
|
||||
handlers = {
|
||||
firefox = function() end, -- Disable Firefox auto-config for TS/JS
|
||||
},
|
||||
})
|
||||
|
||||
-- 🔍 Virtual Text
|
||||
@@ -232,6 +234,20 @@ return {
|
||||
}
|
||||
|
||||
dap.configurations.typescript = {
|
||||
{
|
||||
name = "Launch with Bun",
|
||||
type = "pwa-node",
|
||||
request = "launch",
|
||||
runtimeExecutable = "bun",
|
||||
runtimeArgs = { "--inspect-brk" },
|
||||
program = "${file}",
|
||||
cwd = "${workspaceFolder}",
|
||||
sourceMaps = true,
|
||||
resolveSourceMapLocations = { "${workspaceFolder}/**", "!**/node_modules/**" },
|
||||
console = "internalConsole",
|
||||
skipFiles = { "<node_internals>/**", "node_modules/**" },
|
||||
attachSimplePort = 6499,
|
||||
},
|
||||
{
|
||||
name = "Launch NestJS (dist/main.js)",
|
||||
type = "pwa-node",
|
||||
@@ -245,7 +261,7 @@ return {
|
||||
skipFiles = { "<node_internals>/**", "node_modules/**" },
|
||||
},
|
||||
{
|
||||
name = "Launch Current File",
|
||||
name = "Launch Current File (Node)",
|
||||
type = "pwa-node",
|
||||
request = "launch",
|
||||
program = "${file}",
|
||||
@@ -289,6 +305,74 @@ return {
|
||||
},
|
||||
}
|
||||
|
||||
-- 🎮 DAP Keymaps (registered here so dap/dapui are already loaded)
|
||||
keymap("n", "<leader>dcr", dap.continue, { desc = "▶ Start Debugging" })
|
||||
keymap("n", "<leader>do", dap.step_over, { desc = "⏭ Step Over" })
|
||||
keymap("n", "<leader>di", dap.step_into, { desc = "⤵ Step Into" })
|
||||
keymap("n", "<leader>dot", dap.step_out, { desc = "⤴ Step Out" })
|
||||
keymap("n", "<leader>db", dap.toggle_breakpoint, { desc = "🔴 Toggle Breakpoint" })
|
||||
keymap("n", "<leader>dB", function()
|
||||
dap.set_breakpoint(fn.input("Breakpoint condition: "))
|
||||
end, { desc = "⚠ Conditional Breakpoint" })
|
||||
keymap("n", "<leader>dr", dap.repl.open, { desc = "💬 Open REPL" })
|
||||
keymap("n", "<leader>dl", dap.run_last, { desc = "🔁 Run Last Debug" })
|
||||
keymap("n", "<leader>du", dapui.toggle, { desc = "🧩 Toggle DAP UI" })
|
||||
keymap("n", "<leader>dq", dap.terminate, { desc = "⛔ Stop Debugging" })
|
||||
keymap("n", "<leader>drt", function()
|
||||
dap.terminate()
|
||||
dapui.close()
|
||||
vim.defer_fn(function()
|
||||
dapui.open()
|
||||
end, 200)
|
||||
end, { desc = "🧼 Reset DAP UI Layout" })
|
||||
keymap("n", "<leader>dcf", function()
|
||||
local ft = vim.bo.filetype
|
||||
local configs = dap.configurations[ft] or {}
|
||||
if #configs == 0 then
|
||||
vim.notify("No DAP configurations for filetype: " .. ft, vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
vim.ui.select(configs, {
|
||||
prompt = "Select DAP configuration:",
|
||||
format_item = function(item) return item.name end,
|
||||
}, function(config)
|
||||
if config then dap.run(config) end
|
||||
end)
|
||||
end, { desc = "🔭 DAP Configs" })
|
||||
keymap("n", "<leader>dcb", function()
|
||||
dap.list_breakpoints()
|
||||
vim.cmd("copen")
|
||||
end, { desc = "🧷 List Breakpoints" })
|
||||
keymap("n", "<leader>dco", dap.repl.open, { desc = "⚙️ DAP Commands" })
|
||||
|
||||
-- 🔌 Dynamic Debug Attach (no hardcoded ports)
|
||||
-- Bun requires --inspect=host:port/debug to set a known WebSocket path
|
||||
-- because it doesn't implement /json/list for auto-discovery.
|
||||
keymap("n", "<leader>jd", function()
|
||||
vim.ui.input({ prompt = "Inspector port (default 6499): " }, function(input)
|
||||
if input == nil then return end -- cancelled
|
||||
local port = input ~= "" and input or "6499"
|
||||
local port_num = tonumber(port)
|
||||
if not port_num then
|
||||
vim.notify("Invalid port number", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
local ws_url = "ws://localhost:" .. port .. "/debug"
|
||||
vim.notify("Attaching to " .. ws_url, vim.log.levels.INFO)
|
||||
dap.run({
|
||||
name = "Attach (" .. ws_url .. ")",
|
||||
type = "pwa-node",
|
||||
request = "attach",
|
||||
websocketAddress = ws_url,
|
||||
cwd = fn.getcwd(),
|
||||
sourceMaps = true,
|
||||
resolveSourceMapLocations = { "${workspaceFolder}/**", "!**/node_modules/**" },
|
||||
skipFiles = { "<node_internals>/**", "node_modules/**" },
|
||||
restart = true,
|
||||
})
|
||||
end)
|
||||
end, { desc = "🔌 Debug Attach (dynamic)" })
|
||||
|
||||
-- JavaScript uses same configurations as TypeScript
|
||||
dap.configurations.javascript = {
|
||||
{
|
||||
@@ -309,5 +393,9 @@ return {
|
||||
skipFiles = { "<node_internals>/**", "node_modules/**" },
|
||||
},
|
||||
}
|
||||
|
||||
-- TSX/JSX use the same configurations as their base languages
|
||||
dap.configurations.typescriptreact = dap.configurations.typescript
|
||||
dap.configurations.javascriptreact = dap.configurations.javascript
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
-- ============================================================================
|
||||
-- EDGY: Window layout management
|
||||
-- ============================================================================
|
||||
-- Manages fixed window layouts for sidebars and panels (file tree, outline, etc.).
|
||||
-- Keeps special windows docked at consistent positions and sizes.
|
||||
-- Configures NvimTree (left), Outline (right), and various bottom panels.
|
||||
-- ============================================================================
|
||||
|
||||
return {
|
||||
"folke/edgy.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = {
|
||||
left = {
|
||||
{
|
||||
ft = "NvimTree",
|
||||
size = { width = 35 },
|
||||
},
|
||||
},
|
||||
right = {
|
||||
{
|
||||
ft = "Outline",
|
||||
size = { width = 30 },
|
||||
},
|
||||
},
|
||||
bottom = {
|
||||
{
|
||||
ft = "snacks_terminal",
|
||||
size = { height = 0.25 },
|
||||
},
|
||||
{
|
||||
ft = "trouble",
|
||||
size = { height = 0.25 },
|
||||
},
|
||||
{
|
||||
ft = "qf",
|
||||
size = { height = 0.2 },
|
||||
},
|
||||
},
|
||||
animate = { enabled = false },
|
||||
exit_when_last = true,
|
||||
wo = {
|
||||
winbar = false,
|
||||
winfixwidth = true,
|
||||
winfixheight = false,
|
||||
signcolumn = "no",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
-- ============================================================================
|
||||
-- FLASH: Fast navigation with search labels
|
||||
-- ============================================================================
|
||||
-- Enhanced motion plugin - type a few chars, then jump directly to any match
|
||||
-- using labeled hints. Works across windows. Press 's' to start flash jump,
|
||||
-- or use with 'f', 't' motions. Much faster than repeated w/b movements.
|
||||
-- ============================================================================
|
||||
return {
|
||||
"folke/flash.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = {
|
||||
labels = "asdfghjklqwertyuiopzxcvbnm",
|
||||
search = {
|
||||
multi_window = true,
|
||||
forward = true,
|
||||
wrap = true,
|
||||
},
|
||||
jump = {
|
||||
jumplist = true,
|
||||
pos = "start",
|
||||
history = false,
|
||||
register = false,
|
||||
nohlsearch = false,
|
||||
autojump = false,
|
||||
},
|
||||
label = {
|
||||
uppercase = false,
|
||||
rainbow = {
|
||||
enabled = true,
|
||||
shade = 5,
|
||||
},
|
||||
},
|
||||
modes = {
|
||||
search = {
|
||||
enabled = false, -- set to true to enable flash in search mode
|
||||
},
|
||||
char = {
|
||||
enabled = true,
|
||||
jump_labels = true,
|
||||
multi_line = false,
|
||||
},
|
||||
treesitter = {
|
||||
labels = "asdfghjklqwertyuiopzxcvbnm",
|
||||
jump = { pos = "range" },
|
||||
search = { incremental = false },
|
||||
label = { before = true, after = true, style = "inline" },
|
||||
highlight = {
|
||||
backdrop = false,
|
||||
matches = false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
keys = {
|
||||
{ "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" },
|
||||
{ "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
|
||||
{ "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
|
||||
{ "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
|
||||
{ "<c-s>", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
|
||||
},
|
||||
}
|
||||
@@ -45,7 +45,8 @@ return {
|
||||
lua = { "stylua" },
|
||||
python = { "isort", "black" },
|
||||
sql = { "sqlfluff" }, -- SQL formatting
|
||||
java = { "google-java-format" },
|
||||
-- java: no conform formatter (google-java-format needs JDK 21+)
|
||||
-- falls through to JDTLS LSP via lsp_fallback = true
|
||||
},
|
||||
format_on_save = function(bufnr)
|
||||
-- Disable autoformat for certain filetypes
|
||||
|
||||
@@ -88,7 +88,7 @@ return {
|
||||
end,
|
||||
})
|
||||
|
||||
keymap.set("n", "<leader>l", function()
|
||||
keymap.set("n", "<leader>lf", function()
|
||||
lint.try_lint()
|
||||
end, { desc = "Trigger linting for current file" })
|
||||
end,
|
||||
|
||||
@@ -75,6 +75,7 @@ return {
|
||||
}),
|
||||
-- sources for autocompletion
|
||||
sources = cmp.config.sources({
|
||||
{ name = "copilot", priority = 1100, group_index = 1 }, -- Copilot suggestions in menu
|
||||
{ name = "nvim_lsp", priority = 1000 },
|
||||
{ name = "luasnip", priority = 750 }, -- snippets
|
||||
{ name = "buffer", priority = 500, keyword_length = 3 }, -- text within current buffer
|
||||
@@ -86,6 +87,7 @@ return {
|
||||
format = lspkind.cmp_format({
|
||||
maxwidth = 50,
|
||||
ellipsis_char = "...",
|
||||
symbol_map = { Copilot = "" },
|
||||
}),
|
||||
},
|
||||
|
||||
|
||||
53
lua/cargdev/plugins/obsidian.lua
Normal file
53
lua/cargdev/plugins/obsidian.lua
Normal file
@@ -0,0 +1,53 @@
|
||||
-- ============================================================================
|
||||
-- OBSIDIAN: Full Obsidian vault integration for Neovim
|
||||
-- ============================================================================
|
||||
-- Wiki-link completion, daily notes, templates, backlinks, Telescope search,
|
||||
-- and more. Replaces the custom follow_obsidian_link() function.
|
||||
-- ============================================================================
|
||||
return {
|
||||
"epwalsh/obsidian.nvim",
|
||||
version = "*",
|
||||
dependencies = {
|
||||
"nvim-lua/plenary.nvim",
|
||||
"hrsh7th/nvim-cmp",
|
||||
"nvim-telescope/telescope.nvim",
|
||||
},
|
||||
event = {
|
||||
"BufReadPre " .. vim.fn.expand("~") .. "/Nextcloud/ObsidianVault/**.md",
|
||||
"BufNewFile " .. vim.fn.expand("~") .. "/Nextcloud/ObsidianVault/**.md",
|
||||
},
|
||||
ft = "markdown",
|
||||
keys = {
|
||||
{ "<leader>on", "<cmd>ObsidianNew<cr>", desc = "New note" },
|
||||
{ "<leader>od", "<cmd>ObsidianToday<cr>", desc = "Today's daily note" },
|
||||
{ "<leader>os", "<cmd>ObsidianSearch<cr>", desc = "Search notes" },
|
||||
{ "<leader>ob", "<cmd>ObsidianBacklinks<cr>", desc = "Show backlinks" },
|
||||
{ "<leader>ot", "<cmd>ObsidianTemplate<cr>", desc = "Insert template" },
|
||||
{ "<leader>of", "<cmd>ObsidianFollowLink<cr>", desc = "Follow link" },
|
||||
{ "<leader>ol", "<cmd>ObsidianLink<cr>", mode = "v", desc = "Link selection to note" },
|
||||
},
|
||||
opts = {
|
||||
workspaces = {
|
||||
{
|
||||
name = "vault",
|
||||
path = "/Users/carlos/Nextcloud/ObsidianVault",
|
||||
},
|
||||
},
|
||||
daily_notes = {
|
||||
folder = "daily",
|
||||
date_format = "%Y-%m-%d",
|
||||
},
|
||||
templates = {
|
||||
folder = "templates",
|
||||
},
|
||||
completion = {
|
||||
nvim_cmp = true,
|
||||
min_chars = 2,
|
||||
},
|
||||
preferred_link_style = "wiki",
|
||||
use_advanced_uri = false,
|
||||
picker = {
|
||||
name = "telescope.nvim",
|
||||
},
|
||||
},
|
||||
}
|
||||
149
scripts/detect_keymap_conflicts.lua
Normal file
149
scripts/detect_keymap_conflicts.lua
Normal file
@@ -0,0 +1,149 @@
|
||||
--- detect_keymap_conflicts.lua
|
||||
--- Detects duplicate keymap bindings across neovim config files.
|
||||
--- Run from the nvim config root: lua scripts/detect_keymap_conflicts.lua
|
||||
|
||||
local handle = io.popen("find lua -name '*.lua' -print")
|
||||
if not handle then
|
||||
print("Error: could not search for lua files")
|
||||
os.exit(1)
|
||||
end
|
||||
local files = {}
|
||||
for path in handle:lines() do
|
||||
files[#files + 1] = path
|
||||
end
|
||||
handle:close()
|
||||
|
||||
--- Build a lookup table: line_starts[i] = byte position where line i begins.
|
||||
local function build_line_index(content)
|
||||
local starts = { 1 }
|
||||
for i = 1, #content do
|
||||
if content:sub(i, i) == "\n" then
|
||||
starts[#starts + 1] = i + 1
|
||||
end
|
||||
end
|
||||
return starts
|
||||
end
|
||||
|
||||
--- Binary search to find the line number for a byte position.
|
||||
local function line_at(line_starts, pos)
|
||||
local lo, hi = 1, #line_starts
|
||||
while lo < hi do
|
||||
local mid = math.floor((lo + hi + 1) / 2)
|
||||
if line_starts[mid] <= pos then
|
||||
lo = mid
|
||||
else
|
||||
hi = mid - 1
|
||||
end
|
||||
end
|
||||
return lo
|
||||
end
|
||||
|
||||
--- Return true if `pos` sits after a "--" comment marker on the same line.
|
||||
local function is_in_comment(content, line_starts, pos)
|
||||
local ln = line_at(line_starts, pos)
|
||||
local line_start = line_starts[ln]
|
||||
local before = content:sub(line_start, pos - 1)
|
||||
return before:match("%-%-") ~= nil
|
||||
end
|
||||
|
||||
--- Split a mode argument into individual mode strings.
|
||||
--- "n" -> {"n"}, {"n", "v"} -> {"n", "v"}
|
||||
local function extract_modes(mode_arg)
|
||||
local modes = {}
|
||||
for m in mode_arg:gmatch([=["([^"]+)"]=]) do
|
||||
modes[#modes + 1] = m
|
||||
end
|
||||
if #modes == 0 then
|
||||
for m in mode_arg:gmatch("'([^']+)'") do
|
||||
modes[#modes + 1] = m
|
||||
end
|
||||
end
|
||||
if #modes == 0 then
|
||||
local trimmed = mode_arg:gsub("^%s+", ""):gsub("%s+$", "")
|
||||
if #trimmed > 0 then
|
||||
modes[#modes + 1] = trimmed
|
||||
end
|
||||
end
|
||||
return modes
|
||||
end
|
||||
|
||||
-- Patterns to match keymap setter calls.
|
||||
-- Two variants per caller style: single-string mode and table mode.
|
||||
-- Using [=[...]=] to avoid issues with ]] inside patterns.
|
||||
-- () captures the byte position for line-number lookup.
|
||||
local patterns = {
|
||||
-- vim.keymap.set("n", "<key>", ...)
|
||||
[=[()vim%.keymap%.set%(%s*["']([^"']+)["']%s*,%s*["']([^"']+)["']]=],
|
||||
-- vim.keymap.set({"n", "v"}, "<key>", ...)
|
||||
[=[()vim%.keymap%.set%(%s*(%b{})%s*,%s*["']([^"']+)["']]=],
|
||||
-- keymap.set("n", "<key>", ...)
|
||||
[=[()keymap%.set%(%s*["']([^"']+)["']%s*,%s*["']([^"']+)["']]=],
|
||||
-- keymap.set({"n", "v"}, "<key>", ...)
|
||||
[=[()keymap%.set%(%s*(%b{})%s*,%s*["']([^"']+)["']]=],
|
||||
-- keymap("n", "<key>", ...) — when local keymap = vim.keymap.set
|
||||
[=[()keymap%(%s*["']([^"']+)["']%s*,%s*["']([^"']+)["']]=],
|
||||
-- keymap({"n", "v"}, "<key>", ...)
|
||||
[=[()keymap%(%s*(%b{})%s*,%s*["']([^"']+)["']]=],
|
||||
-- map("n", "<key>", ...) — wrapper function
|
||||
[=[()map%(%s*["']([^"']+)["']%s*,%s*["']([^"']+)["']]=],
|
||||
-- map({"n", "v"}, "<key>", ...)
|
||||
[=[()map%(%s*(%b{})%s*,%s*["']([^"']+)["']]=],
|
||||
}
|
||||
|
||||
local keymaps = {} -- "mode|lhs" -> list of "file:line"
|
||||
local seen = {} -- dedup: "file:line:lhs" -> true
|
||||
|
||||
for _, f in ipairs(files) do
|
||||
local fh = io.open(f, "r")
|
||||
if fh then
|
||||
-- Read entire file so patterns can span multiple lines (%s matches \n).
|
||||
local content = fh:read("*a")
|
||||
fh:close()
|
||||
local line_starts = build_line_index(content)
|
||||
|
||||
for _, pat in ipairs(patterns) do
|
||||
for pos, mode_arg, lhs in content:gmatch(pat) do
|
||||
if not is_in_comment(content, line_starts, pos) then
|
||||
local ln = line_at(line_starts, pos)
|
||||
local dedup_key = f .. ":" .. ln .. ":" .. lhs
|
||||
if not seen[dedup_key] then
|
||||
seen[dedup_key] = true
|
||||
local modes = extract_modes(mode_arg)
|
||||
for _, mode in ipairs(modes) do
|
||||
local key = mode .. "|" .. lhs
|
||||
keymaps[key] = keymaps[key] or {}
|
||||
keymaps[key][#keymaps[key] + 1] = string.format("%s:%d", f, ln)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Collect and sort conflicts
|
||||
local conflicts = {}
|
||||
for key, locations in pairs(keymaps) do
|
||||
if #locations > 1 then
|
||||
local mode, lhs = key:match("^(.-)|(.*)")
|
||||
conflicts[#conflicts + 1] = { mode = mode, lhs = lhs, locations = locations }
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(conflicts, function(a, b)
|
||||
if a.mode == b.mode then return a.lhs < b.lhs end
|
||||
return a.mode < b.mode
|
||||
end)
|
||||
|
||||
if #conflicts == 0 then
|
||||
print("No duplicate keymaps found.")
|
||||
else
|
||||
print(string.format("Found %d conflicting keymap(s):\n", #conflicts))
|
||||
for _, c in ipairs(conflicts) do
|
||||
print(string.format(" [%s] %s", c.mode, c.lhs))
|
||||
for _, loc in ipairs(c.locations) do
|
||||
print(" - " .. loc)
|
||||
end
|
||||
print()
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user