diff --git a/.gitignore b/.gitignore index f7876f6..afcbcf2 100644 --- a/.gitignore +++ b/.gitignore @@ -16,11 +16,9 @@ Thumbs.db *~ # Plugin artifacts -lazy-lock.json .luarc.json # Development artifacts .envrc -*.disabled todo.md CLAUDE.md diff --git a/init.lua b/init.lua index 697d948..8bd0578 100644 --- a/init.lua +++ b/init.lua @@ -7,6 +7,8 @@ require 'core.keymaps' require 'core.autocmds' require('core.shared-session').setup() +vim.env.DEVELOPER_DIR = '/Applications/Xcode.app/Contents/Developer' + -- Load plugins via lazy.nvim require('lazy').setup('plugins.spec', { change_detection = { enabled = true, notify = false }, diff --git a/lazy-lock.json b/lazy-lock.json new file mode 100644 index 0000000..93849d6 --- /dev/null +++ b/lazy-lock.json @@ -0,0 +1,40 @@ +{ + "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, + "blink-cmp-copilot": { "branch": "main", "commit": "439cff78780c033aa23cf061d7315314b347e3c1" }, + "blink.cmp": { "branch": "main", "commit": "485c03400608cb6534bbf84da8c1c471fc4808c0" }, + "conform.nvim": { "branch": "master", "commit": "235dd79731c1dc51ec04abb4045cbc54727a172a" }, + "copilot.lua": { "branch": "master", "commit": "3123983d00ae6859f8bc987d14ebb524bb41b618" }, + "fidget.nvim": { "branch": "main", "commit": "3f5475949679953af6d78654db29b944fa826e6a" }, + "gitsigns.nvim": { "branch": "main", "commit": "20ad4419564d6e22b189f6738116b38871082332" }, + "harpoon": { "branch": "harpoon2", "commit": "ed1f853847ffd04b2b61c314865665e1dadf22c7" }, + "image.nvim": { "branch": "master", "commit": "446a8a5cc7a3eae3185ee0c697732c32a5547a0b" }, + "indent-blankline.nvim": { "branch": "master", "commit": "005b56001b2cb30bfa61b7986bc50657816ba4ba" }, + "lazy.nvim": { "branch": "main", "commit": "1ea3c4085785f460fb0e46d2fe1ee895f5f9e7c1" }, + "lazydev.nvim": { "branch": "main", "commit": "e28ce52fc7ff79fcb76f0e79ee6fb6182fca90b9" }, + "leetcode.nvim": { "branch": "master", "commit": "fdd3f91800b3983e27bc9fcfb99cfa7293d7f11a" }, + "mini.nvim": { "branch": "main", "commit": "cf32454e91b3d963a12fef0314811fb035b62d49" }, + "molten-nvim": { "branch": "main", "commit": "a286aa914d9a154bc359131aab788b5a077a5a99" }, + "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-autopairs": { "branch": "master", "commit": "7a2c97cccd60abc559344042fefb1d5a85b3e33b" }, + "nvim-dap": { "branch": "master", "commit": "6782b097af2417a4c3e33849b0a26ae2188bd7ea" }, + "nvim-dap-ui": { "branch": "master", "commit": "cf91d5e2d07c72903d052f5207511bf7ecdb7122" }, + "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, + "nvim-lspconfig": { "branch": "master", "commit": "e5c61b02f33b5c6538be25b2696b33b4cc91e667" }, + "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, + "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, + "nvim-treesitter-textobjects": { "branch": "master", "commit": "a9742cbc1f95db9eaf3293bf8cd0622ca36542bb" }, + "nvim-web-devicons": { "branch": "master", "commit": "b8221e42cf7287c4dcde81f232f58d7b947c210d" }, + "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "1f08ed60cafc8f6168b72b80be2b2ea149813e55" }, + "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, + "telescope.nvim": { "branch": "0.1.x", "commit": "a0bbec21143c7bc5f8bb02e0005fa0b982edc026" }, + "todo-comments.nvim": { "branch": "main", "commit": "19d461ddd543e938eb22505fb03fa878800270b6" }, + "tokyonight.nvim": { "branch": "main", "commit": "e63c42a42b11cd6225f009dd949b9ee0fccc15ef" }, + "vim-fugitive": { "branch": "master", "commit": "61b51c09b7c9ce04e821f6cf76ea4f6f903e3cf4" }, + "vim-illuminate": { "branch": "master", "commit": "0d1e93684da00ab7c057410fecfc24f434698898" }, + "vim-ocaml": { "branch": "master", "commit": "ee14abbe433dcf5b85863e19900dea60e090b87d" }, + "vim-sleuth": { "branch": "master", "commit": "be69bff86754b1aa5adcbb527d7fcd1635a84080" }, + "vim-slime": { "branch": "main", "commit": "67b24bf93cff3ac39db94694a7aefcdb3f44b927" }, + "vim-tmux-navigator": { "branch": "master", "commit": "c45243dc1f32ac6bcf6068e5300f3b2b237e576a" }, + "which-key.nvim": { "branch": "main", "commit": "b4177e3eaf15fe5eb8357ebac2286d488be1ed00" } +} diff --git a/lua/core/autocmds.lua b/lua/core/autocmds.lua index 12eb674..1380e91 100644 --- a/lua/core/autocmds.lua +++ b/lua/core/autocmds.lua @@ -12,21 +12,15 @@ vim.api.nvim_create_autocmd('TextYankPost', { end, }) --- Fix for netrw not properly detecting filetypes --- This is a global issue that affects all filetypes when using :Ex -vim.api.nvim_create_autocmd("BufReadPost", { - group = vim.api.nvim_create_augroup('netrw-filetype-fix', { clear = true }), - pattern = "*", - callback = function() - -- If filetype is empty after opening a file, force detection - -- This commonly happens when navigating through netrw - if vim.bo.filetype == "" then - vim.schedule(function() - if vim.bo.filetype == "" then - vim.cmd("filetype detect") - end - end) +vim.api.nvim_create_autocmd('LspAttach', { + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + if client and client.server_capabilities.codeLensProvider then + vim.lsp.codelens.refresh() + vim.api.nvim_create_autocmd({ 'BufEnter', 'CursorHold', 'InsertLeave' }, { + buffer = args.buf, + callback = vim.lsp.codelens.refresh, + }) end end, - desc = "Fix netrw filetype detection for all files" }) diff --git a/lua/core/keymaps.lua b/lua/core/keymaps.lua index d53f662..e5b5574 100644 --- a/lua/core/keymaps.lua +++ b/lua/core/keymaps.lua @@ -14,23 +14,20 @@ vim.keymap.set('t', '', '', { desc = 'Exit terminal mode' } local function reload_lsp() local clients = vim.lsp.get_clients() if #clients == 0 then - print('No LSP clients running') + print 'No LSP clients running' return end - + for _, client in ipairs(clients) do vim.lsp.stop_client(client.id) end - + vim.defer_fn(function() - vim.cmd('LspStart') - print('LSP servers reloaded') + vim.cmd 'LspStart' + print 'LSP servers reloaded' end, 500) end --- Reload LSP keybind -vim.keymap.set('n', 'lr', reload_lsp, { desc = '[L]SP [R]eload all servers' }) - -- Buffer management keymaps vim.keymap.set('n', 'bb', 'Telescope buffers', { desc = '[B]rowse [B]uffers' }) vim.keymap.set('n', '[b', 'bprevious', { desc = 'Previous buffer' }) @@ -58,5 +55,10 @@ vim.keymap.set('n', '', 'resize -2', { desc = 'Decrease window vim.keymap.set('n', '', 'vertical resize -2', { desc = 'Decrease window width' }) vim.keymap.set('n', '', 'vertical resize +2', { desc = 'Increase window width' }) +-- Editing/Navigation +vim.keymap.set('n', 'S', ':%s//', { desc = '[S]ubstitute current word' }) +vim.keymap.set('v', 'J', ":m '>+1gv=gv") +vim.keymap.set('v', 'K', ":m '<-2gv=gv") + -- Standard practice for Lua modules that don't need to return complex data return {} diff --git a/lua/plugins/config/autopairs.lua b/lua/plugins/config/autopairs.lua new file mode 100644 index 0000000..8986101 --- /dev/null +++ b/lua/plugins/config/autopairs.lua @@ -0,0 +1,67 @@ +-- Auto-pairs - Automatically close brackets, quotes, etc. +local M = {} + +function M.setup() + pcall(function() + require('vim._extui').enable {} + end) + + require('blink.pairs').setup { + mappings = { + enabled = true, + cmdline = true, + disable_filetype = { 'TelescopePrompt', 'spectre_panel' }, + }, + highlights = { + enabled = true, + cmdline = true, + groups = { + 'BlinkPairsOrange', + 'BlinkPairsPurple', + 'BlinkPairsBlue', + }, + unmatched_group = 'BlinkPairsUnmatched', + + -- highlights matching pairs under the cursor + matchparen = { + enabled = true, + -- known issue where typing won't update matchparen highlight, disabled by default + cmdline = false, + -- also include pairs not on top of the cursor, but surrounding the cursor + include_surrounding = false, + group = 'BlinkPairsMatchParen', + priority = 250, + }, + }, + debug = false, + } + + -- UNIFIED KEY TO KILL AUTO-INSERTED STUFF + -- already kills auto-inserted comments (built-in) + -- Let's add to also kill auto-paired character + + vim.keymap.set('i', '', function() + local line = vim.api.nvim_get_current_line() + local col = vim.fn.col '.' - 1 + + -- Check if we're at the beginning of a line with just comment chars + local comment_pattern = '^%s*[#%-/]+%s*$' + if line:sub(1, col):match(comment_pattern) then + -- Kill the whole comment prefix (default behavior) + return '' + -- Check if cursor is between paired characters + elseif col > 0 and col < #line then + local before = line:sub(col, col) + local after = line:sub(col + 1, col + 1) + local pairs = { ['('] = ')', ['['] = ']', ['{'] = '}', ['"'] = '"', ["'"] = "'" } + if pairs[before] == after then + -- Delete the closing pair + return '' + end + end + -- Otherwise, regular (kill to start of line) + return '' + end, { expr = true, desc = 'Kill auto-insert or line to start' }) +end + +return M diff --git a/lua/plugins/config/blink.lua b/lua/plugins/config/blink.lua index f59b0a6..4496226 100644 --- a/lua/plugins/config/blink.lua +++ b/lua/plugins/config/blink.lua @@ -2,30 +2,58 @@ local M = {} function M.setup() - require('blink.cmp').setup({ + require('blink.cmp').setup { -- Keymap configuration keymap = { preset = 'default', - [''] = { 'show', 'show_documentation', 'hide_documentation' }, + [''] = { 'show', 'show_documentation', 'hide_documentation' }, [''] = { 'hide' }, [''] = { 'select_and_accept' }, - + [''] = { 'select_prev', 'fallback' }, [''] = { 'select_next', 'fallback' }, - + [''] = { 'scroll_documentation_up', 'fallback' }, [''] = { 'scroll_documentation_down', 'fallback' }, - - [''] = { 'snippet_forward', 'fallback' }, - [''] = { 'snippet_backward', 'fallback' }, + + [''] = { 'snippet_forward', 'fallback' }, + [''] = { 'snippet_backward', 'fallback' }, }, - + -- Appearance configuration appearance = { - use_nvim_cmp_as_default = true, + -- use_nvim_cmp_as_default = true, nerd_font_variant = 'mono', + kind_icons = { + Copilot = '', + Text = '', + Method = 'ƒ', + Function = 'ƒ', + Constructor = '', + Field = '', + Variable = '', + Property = '', + Class = '', + Interface = '', + Struct = '', + Module = '', + Unit = '', + Value = '', + Enum = '', + EnumMember = '', + Keyword = '', + Constant = '', + Snippet = ' ', + Color = '', + File = '', + Reference = '', + Folder = '', + Event = '', + Operator = '', + TypeParameter = '', + }, }, - + -- Sources configuration with Copilot integration sources = { default = { 'lsp', 'path', 'snippets', 'buffer', 'copilot' }, @@ -33,24 +61,26 @@ function M.setup() copilot = { name = 'copilot', module = 'blink-cmp-copilot', - score_offset = 100, + score_offset = -5, async = true, transform_items = function(_, items) - -- Add copilot icon to copilot suggestions + local CompletionItemKind = require('blink.cmp.types').CompletionItemKind + local kind_idx = #CompletionItemKind + 1 + CompletionItemKind[kind_idx] = 'Copilot' for _, item in ipairs(items) do - item.kind = 'Copilot' + item.kind = kind_idx end return items end, }, }, }, - + -- Command line configuration (new API) cmdline = { - enabled = false, -- Disable cmdline completion for now + enabled = true, }, - + -- Signature help configuration signature = { enabled = true, @@ -58,9 +88,10 @@ function M.setup() border = 'rounded', }, }, - + -- Completion configuration completion = { + keyword = { range = 'full' }, accept = { -- Auto-insert brackets for functions auto_brackets = { @@ -71,7 +102,7 @@ function M.setup() draw = { columns = { { 'label', 'label_description', gap = 1 }, - { 'kind_icon', 'kind' } + { 'kind_icon', 'kind' }, }, }, border = 'rounded', @@ -79,16 +110,16 @@ function M.setup() }, documentation = { auto_show = true, - auto_show_delay_ms = 200, + auto_show_delay_ms = 500, window = { border = 'rounded', }, }, ghost_text = { - enabled = false, -- Disabled: was showing unwanted text on Tab + enabled = false, -- Disabled: was showing unwanted text on Tab }, }, - + -- Fuzzy matching configuration fuzzy = { -- Use Rust implementation for better performance @@ -106,7 +137,7 @@ function M.setup() download = true, }, }, - + -- Snippet configuration snippets = { expand = function(snippet) @@ -120,7 +151,7 @@ function M.setup() end end, }, - }) + } end -return M \ No newline at end of file +return M diff --git a/lua/plugins/config/compile-commands-picker.lua b/lua/plugins/config/compile-commands-picker.lua deleted file mode 100644 index ecd095d..0000000 --- a/lua/plugins/config/compile-commands-picker.lua +++ /dev/null @@ -1,142 +0,0 @@ --- Telescope picker for selecting compile_commands.json -local M = {} - -local function find_compile_commands() - local root = vim.fn.getcwd() - local cmd = string.format('find "%s" -name compile_commands.json -type f 2>/dev/null', root) - local handle = io.popen(cmd) - if not handle then - return {} - end - - local result = handle:read('*a') - handle:close() - - local files = {} - for line in result:gmatch('[^\n]+') do - -- Get relative path for display - local relative = line:gsub('^' .. vim.pesc(root) .. '/', '') - table.insert(files, { - path = line, - display = relative, - dir = vim.fn.fnamemodify(line, ':h'), - relative_dir = vim.fn.fnamemodify(relative, ':h'), - }) - end - - return files -end - -function M.pick_compile_commands() - local files = find_compile_commands() - - if #files == 0 then - vim.notify('No compile_commands.json files found', vim.log.levels.WARN) - return - elseif #files == 1 then - vim.notify('Using: ' .. files[1].display, vim.log.levels.INFO) - M.set_compile_commands(files[1]) - return - end - - -- Use Telescope's built-in find_files with custom settings - local builtin = require('telescope.builtin') - local actions = require('telescope.actions') - local action_state = require('telescope.actions.state') - - builtin.find_files({ - prompt_title = 'Select compile_commands.json', - cwd = vim.fn.getcwd(), - find_command = { 'find', '.', '-name', 'compile_commands.json', '-type', 'f' }, - attach_mappings = function(prompt_bufnr, map) - actions.select_default:replace(function() - actions.close(prompt_bufnr) - local selection = action_state.get_selected_entry() - if selection then - -- Convert the selection to our file_info format - local path = selection[1] - local relative = path:gsub('^%./', '') - local file_info = { - path = vim.fn.getcwd() .. '/' .. relative, - display = relative, - dir = vim.fn.fnamemodify(path, ':h'), - relative_dir = vim.fn.fnamemodify(relative, ':h'), - } - M.set_compile_commands(file_info) - end - end) - return true - end, - }) -end - -function M.set_compile_commands(file_info) - local clangd_config = string.format([[ -CompileFlags: - CompilationDatabase: %s -]], file_info.relative_dir) - - -- Write .clangd file - local clangd_file = vim.fn.getcwd() .. '/.clangd' - local file = io.open(clangd_file, 'w') - if file then - file:write(clangd_config) - file:close() - vim.notify('Created .clangd pointing to: ' .. file_info.relative_dir, vim.log.levels.INFO) - - -- Restart LSP if clangd is running - local clients = vim.lsp.get_clients({ name = 'clangd' }) - if #clients > 0 then - vim.notify('Restarting clangd...', vim.log.levels.INFO) - -- Stop and start clangd to pick up new config - for _, client in ipairs(clients) do - client.stop() - end - vim.defer_fn(function() - vim.cmd('LspStart clangd') - vim.notify('Clangd restarted with new configuration', vim.log.levels.INFO) - end, 100) - end - else - vim.notify('Failed to create .clangd file', vim.log.levels.ERROR) - end -end - --- Auto-detect multiple compile_commands.json on startup -function M.auto_detect() - local files = find_compile_commands() - - if #files > 1 then - -- Check if .clangd already exists - local clangd_file = vim.fn.getcwd() .. '/.clangd' - if vim.fn.filereadable(clangd_file) == 0 then - vim.notify( - string.format('Found %d compile_commands.json files. Use :CompileCommandsPicker to select one.', #files), - vim.log.levels.INFO - ) - end - end -end - --- Setup function to create command -function M.setup() - vim.api.nvim_create_user_command('CompileCommandsPicker', function() - M.pick_compile_commands() - end, { desc = 'Select compile_commands.json for clangd' }) - - -- Auto-detect on entering a C/C++ file - vim.api.nvim_create_autocmd('FileType', { - pattern = { 'c', 'cpp', 'objc', 'objcpp' }, - callback = function() - -- Only run once per session - if not vim.g.compile_commands_detected then - vim.g.compile_commands_detected = true - vim.defer_fn(function() - M.auto_detect() - end, 100) - end - end, - }) -end - -return M \ No newline at end of file diff --git a/lua/plugins/config/completion.lua b/lua/plugins/config/completion.lua new file mode 100644 index 0000000..7f9b4fa --- /dev/null +++ b/lua/plugins/config/completion.lua @@ -0,0 +1,52 @@ +local M = {} + +function M.setup_blink() + local ok, blink = pcall(require, 'blink.cmp') + if not ok then + return + end + + local opts = blink.config or {} + opts.sources = opts.sources or {} + + local default_sources = opts.sources.default or { 'lsp', 'path', 'buffer', 'snippets' } + + if vim.g.use_copilot then + local seen = {} + local new = { 'copilot' } + for _, name in ipairs(default_sources) do + if name ~= 'copilot' and not seen[name] then + table.insert(new, name) + seen[name] = true + end + end + default_sources = new + else + local new = {} + for _, name in ipairs(default_sources) do + if name ~= 'copilot' then + table.insert(new, name) + end + end + default_sources = new + end + + opts.sources.default = default_sources + blink.setup(opts) +end + +function M.setup_copilot() + require('copilot').setup { + suggestion = { enabled = false }, + panel = { enabled = false }, + } +end + +function M.setup_blink_copilot() + local ok, src = pcall(require, 'blink-cmp-copilot') + if ok and src.setup then + src.setup {} + end +end + +return M diff --git a/lua/plugins/config/debug/adapters.lua b/lua/plugins/config/debug/adapters.lua index 93629e5..8ea6a74 100644 --- a/lua/plugins/config/debug/adapters.lua +++ b/lua/plugins/config/debug/adapters.lua @@ -5,10 +5,10 @@ local M = {} -- In Nix environments, use whatever Python is in PATH local function get_python_path() -- Use the Python from current environment (Nix or system) - if vim.fn.executable('python3') == 1 then - return vim.fn.exepath('python3') - elseif vim.fn.executable('python') == 1 then - return vim.fn.exepath('python') + if vim.fn.executable 'python3' == 1 then + return vim.fn.exepath 'python3' + elseif vim.fn.executable 'python' == 1 then + return vim.fn.exepath 'python' else -- Fallback to system Python return '/usr/bin/python3' @@ -16,12 +16,12 @@ local function get_python_path() end function M.setup() - local dap = require('dap') - + local dap = require 'dap' + -- Setup all language-specific adapters M.setup_python(dap) M.setup_cpp(dap) - + -- Add more adapters as needed -- M.setup_rust(dap) -- M.setup_go(dap) @@ -32,10 +32,10 @@ end function M.setup_python(dap) dap.adapters.python = { type = 'executable', - command = vim.fn.exepath('python3') ~= '' and vim.fn.exepath('python3') or 'python', + command = vim.fn.exepath 'python3' ~= '' and vim.fn.exepath 'python3' or 'python', args = { '-m', 'debugpy.adapter' }, } - + dap.configurations.python = { { type = 'python', @@ -50,7 +50,7 @@ function M.setup_python(dap) name = 'Launch file with arguments', program = '${file}', args = function() - local args_string = vim.fn.input('Arguments: ') + local args_string = vim.fn.input 'Arguments: ' return vim.split(args_string, ' ') end, pythonPath = get_python_path, @@ -65,15 +65,21 @@ function M.setup_python(dap) } end +local function suggest_build_dir() + local cwd = vim.fn.getcwd() + local build_dir = vim.fn.resolve(cwd .. '/compile_commands.json'):match '(.+)/compile_commands.json' + local suggestion = build_dir and build_dir or cwd + return suggestion .. '/' +end + -- C/C++/Rust debugger configuration (using lldb-dap) function M.setup_cpp(dap) - -- LLDB-DAP adapter (modern LLDB with DAP support) dap.adapters.lldb = { type = 'executable', - command = 'lldb-dap', -- Will use lldb-dap from PATH (Nix environment) + command = vim.fn.exepath 'lldb-dap', name = 'lldb', } - + -- C++ configuration dap.configurations.cpp = { { @@ -81,27 +87,29 @@ function M.setup_cpp(dap) type = 'lldb', request = 'launch', program = function() - return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') + return vim.fn.input('Path to executable: ', suggest_build_dir(), 'file') end, cwd = '${workspaceFolder}', stopOnEntry = false, args = {}, runInTerminal = false, + -- sourceInitFile = true, }, { name = 'Launch with arguments', type = 'lldb', request = 'launch', program = function() - return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') + return vim.fn.input('Path to executable: ', suggest_build_dir(), 'file') end, cwd = '${workspaceFolder}', stopOnEntry = false, args = function() - local args_string = vim.fn.input('Arguments: ') + local args_string = vim.fn.input 'Arguments: ' return vim.split(args_string, ' ') end, runInTerminal = false, + -- sourceInitFile = true, }, { name = 'Attach to process', @@ -111,7 +119,7 @@ function M.setup_cpp(dap) args = {}, }, } - + -- Share C++ configuration with C and Rust dap.configurations.c = dap.configurations.cpp dap.configurations.rust = dap.configurations.cpp @@ -127,7 +135,7 @@ end -- args = { 'dap', '-l', '127.0.0.1:${port}' }, -- }, -- } --- +-- -- dap.configurations.go = { -- { -- type = 'delve', @@ -145,4 +153,4 @@ end -- } -- end -return M \ No newline at end of file +return M diff --git a/lua/plugins/config/debug/init.lua b/lua/plugins/config/debug/init.lua index 69fbcd2..c9a1fdf 100644 --- a/lua/plugins/config/debug/init.lua +++ b/lua/plugins/config/debug/init.lua @@ -2,11 +2,11 @@ local M = {} function M.setup() - local dap = require('dap') - local dapui = require('dapui') - + local dap = require 'dap' + local dapui = require 'dapui' + -- Setup DAP UI with icons and controls - dapui.setup({ + dapui.setup { icons = { expanded = '▾', collapsed = '▸', current_frame = '*' }, controls = { icons = { @@ -21,18 +21,19 @@ function M.setup() disconnect = '⏏', }, }, - }) - + } + -- Automatically open/close DAP UI on debug events dap.listeners.after.event_initialized['dapui_config'] = dapui.open dap.listeners.before.event_terminated['dapui_config'] = dapui.close dap.listeners.before.event_exited['dapui_config'] = dapui.close - + -- Configure debug adapters for different languages require('plugins.config.debug.adapters').setup() - + -- Setup debug keymaps require('plugins.config.debug.keymaps').setup() end -return M \ No newline at end of file +return M + diff --git a/lua/plugins/config/debug/keymaps.lua b/lua/plugins/config/debug/keymaps.lua index 7c55b28..b45439a 100644 --- a/lua/plugins/config/debug/keymaps.lua +++ b/lua/plugins/config/debug/keymaps.lua @@ -2,52 +2,53 @@ local M = {} function M.setup() - local dap = require('dap') - local dapui = require('dapui') - - -- Function key mappings for common debug operations + local dap = require 'dap' + local dapui = require 'dapui' + + -- Start debugging + vim.keymap.set('n', '', dap.run_last, { desc = 'Debug: Run Last' }) + vim.keymap.set('n', '', dap.continue, { desc = 'Debug: Start/Continue' }) + + -- Toggle UI + vim.keymap.set('n', '', dapui.toggle, { desc = 'Debug: Toggle UI' }) + + -- Debugging controls vim.keymap.set('n', '', dap.step_over, { desc = 'Debug: Step Over' }) vim.keymap.set('n', '', dap.step_into, { desc = 'Debug: Step Into' }) vim.keymap.set('n', '', dap.step_out, { desc = 'Debug: Step Out' }) - + vim.keymap.set('n', 'dt', dap.terminate, { desc = 'Debug: Terminate Session' }) + + vim.keymap.set('n', 'de', dapui.eval, { desc = 'Debug: Eval under cursor' }) + vim.keymap.set('v', 'de', dapui.eval, { desc = 'Debug: Eval selection' }) + -- Breakpoint management vim.keymap.set('n', 'db', dap.toggle_breakpoint, { desc = 'Debug: Toggle Breakpoint' }) vim.keymap.set('n', 'dB', function() dap.set_breakpoint(vim.fn.input 'Breakpoint condition: ') end, { desc = 'Debug: Set Conditional Breakpoint' }) - vim.keymap.set('n', 'lp', function() - dap.set_breakpoint(nil, nil, vim.fn.input('Log point message: ')) + vim.keymap.set('n', 'dL', function() + dap.set_breakpoint(nil, nil, vim.fn.input 'Log point message: ') end, { desc = 'Debug: Set Log Point' }) - - -- DAP UI controls - vim.keymap.set('n', '', dapui.toggle, { desc = 'Debug: Toggle UI' }) - vim.keymap.set('n', 'de', dapui.eval, { desc = 'Debug: Eval under cursor' }) - vim.keymap.set('v', 'de', dapui.eval, { desc = 'Debug: Eval selection' }) - + -- REPL and additional features vim.keymap.set('n', 'dr', dap.repl.open, { desc = 'Debug: Open REPL' }) - vim.keymap.set('n', 'dl', dap.run_last, { desc = 'Debug: Run Last' }) - + -- Widget-based inspections vim.keymap.set('n', 'dh', function() require('dap.ui.widgets').hover() end, { desc = 'Debug: Hover Variables' }) - + vim.keymap.set('n', 'ds', function() - local widgets = require('dap.ui.widgets') + local widgets = require 'dap.ui.widgets' widgets.centered_float(widgets.scopes) end, { desc = 'Debug: View Scopes' }) - + vim.keymap.set('n', 'df', function() - local widgets = require('dap.ui.widgets') + local widgets = require 'dap.ui.widgets' widgets.centered_float(widgets.frames) end, { desc = 'Debug: View Frames' }) - - -- Session management - vim.keymap.set('n', 'dt', dap.terminate, { desc = 'Debug: Terminate Session' }) - vim.keymap.set('n', 'dc', dap.run_to_cursor, { desc = 'Debug: Continue to Cursor' }) - + -- Create visual indicators for breakpoints vim.fn.sign_define('DapBreakpoint', { text = '🔴', texthl = 'DapBreakpoint', linehl = '', numhl = '' }) vim.fn.sign_define('DapBreakpointCondition', { text = '🟡', texthl = 'DapBreakpoint', linehl = '', numhl = '' }) @@ -56,4 +57,4 @@ function M.setup() vim.fn.sign_define('DapStopped', { text = '▶️', texthl = 'DapStopped', linehl = 'DapStopped', numhl = 'DapStopped' }) end -return M \ No newline at end of file +return M diff --git a/lua/plugins/config/harpoon.lua b/lua/plugins/config/harpoon.lua index 1a7efb6..ddc78ad 100644 --- a/lua/plugins/config/harpoon.lua +++ b/lua/plugins/config/harpoon.lua @@ -16,55 +16,27 @@ function M.setup() vim.keymap.set('n', 'ma', function() harpoon:list():add() vim.notify('Added to Harpoon', vim.log.levels.INFO) - end, { desc = '[M]ark [A]dd file (Harpoon)' }) + end, { desc = 'Harpoon [A]dd file' }) + + -- Remove current file from harpoon + vim.keymap.set('n', 'md', function() + harpoon:list():remove() + vim.notify('Removed from Harpoon', vim.log.levels.INFO) + end, { desc = 'Harpoon [D]elete file' }) -- Toggle quick menu - vim.keymap.set('n', '', function() + vim.keymap.set('n', 'mi', function() harpoon.ui:toggle_quick_menu(harpoon:list()) - end, { desc = 'Toggle Harpoon menu' }) - - -- Quick navigation to files 1-4 using leader+m prefix - vim.keymap.set('n', 'm1', function() - harpoon:list():select(1) - end, { desc = 'Jump to mark 1' }) - - vim.keymap.set('n', 'm2', function() - harpoon:list():select(2) - end, { desc = 'Jump to mark 2' }) - - vim.keymap.set('n', 'm3', function() - harpoon:list():select(3) - end, { desc = 'Jump to mark 3' }) - - vim.keymap.set('n', 'm4', function() - harpoon:list():select(4) - end, { desc = 'Jump to mark 4' }) - - -- Alternative quick access with Alt/Option key (doesn't conflict) - vim.keymap.set('n', '', function() - harpoon:list():select(1) - end, { desc = 'Harpoon file 1' }) - - vim.keymap.set('n', '', function() - harpoon:list():select(2) - end, { desc = 'Harpoon file 2' }) - - vim.keymap.set('n', '', function() - harpoon:list():select(3) - end, { desc = 'Harpoon file 3' }) - - vim.keymap.set('n', '', function() - harpoon:list():select(4) - end, { desc = 'Harpoon file 4' }) + end, { desc = 'Toggle Harpoon [M]enu' }) -- Navigate between harpoon files vim.keymap.set('n', '[m', function() harpoon:list():prev() - end, { desc = 'Previous marked file' }) + end, { desc = 'Harpoon previous file' }) vim.keymap.set('n', ']m', function() harpoon:list():next() - end, { desc = 'Next marked file' }) + end, { desc = 'Harpoon next file' }) -- Show harpoon files in Telescope local conf = require('telescope.config').values @@ -86,21 +58,15 @@ function M.setup() :find() end - vim.keymap.set('n', 'mm', function() + vim.keymap.set('n', 'mt', function() toggle_telescope(harpoon:list()) - end, { desc = '[M]arked files in Telescope' }) + end, { desc = 'Harpoon [T]elescope' }) -- Clear all marks vim.keymap.set('n', 'mc', function() harpoon:list():clear() vim.notify('Cleared all Harpoon marks', vim.log.levels.INFO) - end, { desc = '[M]arks [C]lear all' }) - - -- Remove current file from harpoon - vim.keymap.set('n', 'mr', function() - harpoon:list():remove() - vim.notify('Removed from Harpoon', vim.log.levels.INFO) - end, { desc = '[M]ark [R]emove current file' }) + end, { desc = 'Harpoon [C]lear all' }) end -return M \ No newline at end of file +return M diff --git a/lua/plugins/config/leetcode.lua b/lua/plugins/config/leetcode.lua index fcea4e5..1dfe077 100644 --- a/lua/plugins/config/leetcode.lua +++ b/lua/plugins/config/leetcode.lua @@ -2,37 +2,37 @@ local M = {} M.setup = function() - require('leetcode').setup({ + require('leetcode').setup { lang = 'python3', -- Default to Python for initial solving - + -- Alternative languages alternate = { 'cpp', 'python3', }, - + storage = { - home = vim.fn.stdpath('data') .. '/leetcode', - cache = vim.fn.stdpath('cache') .. '/leetcode', + home = vim.fn.stdpath 'data' .. '/leetcode', + cache = vim.fn.stdpath 'cache' .. '/leetcode', }, - + -- Auto-disable Copilot in LeetCode buffers hooks = { ['enter'] = { function() -- Disable Copilot when entering LeetCode problems - vim.cmd('Copilot disable') + vim.cmd 'Copilot disable' vim.notify('Copilot disabled for LeetCode practice', vim.log.levels.INFO) end, }, ['question_leave'] = { function() -- Re-enable Copilot when leaving LeetCode - vim.cmd('Copilot enable') + vim.cmd 'Copilot enable' end, }, }, - + injector = { ['python3'] = { before = [[ @@ -50,7 +50,7 @@ using namespace std; ]], }, }, - + keys = { toggle = { 'q', '' }, confirm = { '' }, @@ -59,38 +59,38 @@ using namespace std; focus_testcases = 'H', focus_result = 'L', }, - }) - + } + -- Keymaps for LeetCode local keymap = vim.keymap.set local opts = { noremap = true, silent = true } - - keymap('n', 'lq', 'Leet tabs', vim.tbl_extend('force', opts, { desc = 'LeetCode tabs' })) - keymap('n', 'lm', 'Leet menu', vim.tbl_extend('force', opts, { desc = 'LeetCode menu' })) - keymap('n', 'lc', 'Leet console', vim.tbl_extend('force', opts, { desc = 'LeetCode console' })) - keymap('n', 'li', 'Leet info', vim.tbl_extend('force', opts, { desc = 'LeetCode info' })) - keymap('n', 'll', 'Leet lang', vim.tbl_extend('force', opts, { desc = 'LeetCode language' })) - keymap('n', 'ld', 'Leet desc', vim.tbl_extend('force', opts, { desc = 'LeetCode description' })) - keymap('n', 'lr', 'Leet run', vim.tbl_extend('force', opts, { desc = 'LeetCode run' })) - keymap('n', 'ls', 'Leet submit', vim.tbl_extend('force', opts, { desc = 'LeetCode submit' })) - keymap('n', 'lt', 'Leet test', vim.tbl_extend('force', opts, { desc = 'LeetCode test' })) - keymap('n', 'ly', 'Leet yank', vim.tbl_extend('force', opts, { desc = 'LeetCode yank' })) - keymap('n', 'lo', 'Leet open', vim.tbl_extend('force', opts, { desc = 'LeetCode open in browser' })) - keymap('n', 'lR', 'Leet restore', vim.tbl_extend('force', opts, { desc = 'LeetCode restore' })) - + + keymap('n', 'Lq', 'Leet tabs', vim.tbl_extend('force', opts, { desc = 'LeetCode tabs' })) + keymap('n', 'Lm', 'Leet menu', vim.tbl_extend('force', opts, { desc = 'LeetCode menu' })) + keymap('n', 'Lc', 'Leet console', vim.tbl_extend('force', opts, { desc = 'LeetCode console' })) + keymap('n', 'Li', 'Leet info', vim.tbl_extend('force', opts, { desc = 'LeetCode info' })) + keymap('n', 'Ll', 'Leet lang', vim.tbl_extend('force', opts, { desc = 'LeetCode language' })) + keymap('n', 'Ld', 'Leet desc', vim.tbl_extend('force', opts, { desc = 'LeetCode description' })) + keymap('n', 'Lr', 'Leet run', vim.tbl_extend('force', opts, { desc = 'LeetCode run' })) + keymap('n', 'Ls', 'Leet submit', vim.tbl_extend('force', opts, { desc = 'LeetCode submit' })) + keymap('n', 'Lt', 'Leet test', vim.tbl_extend('force', opts, { desc = 'LeetCode test' })) + keymap('n', 'Ly', 'Leet yank', vim.tbl_extend('force', opts, { desc = 'LeetCode yank' })) + keymap('n', 'Lo', 'Leet open', vim.tbl_extend('force', opts, { desc = 'LeetCode open in browser' })) + keymap('n', 'Lx', 'Leet restore', vim.tbl_extend('force', opts, { desc = 'LeetCode restore' })) + -- Daily practice reminder - keymap('n', 'lD', function() + keymap('n', 'LD', function() local problems = { Monday = 'Dynamic Programming', Tuesday = 'Graphs', - Wednesday = 'Math/Probability', + Wednesday = 'Math/Probability', Thursday = 'Trees/Recursion', Friday = 'Bit Manipulation', Saturday = 'Jane Street Tagged', Sunday = 'Jane Street Tagged', } - local day = os.date('%A') - vim.notify('Today\'s focus: ' .. problems[day], vim.log.levels.INFO) + local day = os.date '%A' + vim.notify("Today's focus: " .. problems[day], vim.log.levels.INFO) end, vim.tbl_extend('force', opts, { desc = 'LeetCode daily focus' })) end diff --git a/lua/plugins/config/lint.lua b/lua/plugins/config/lint.lua new file mode 100644 index 0000000..febe3bc --- /dev/null +++ b/lua/plugins/config/lint.lua @@ -0,0 +1,20 @@ +local M = {} + +function M.setup() + local lint = require 'lint' + + lint.linters_by_ft = { + cpp = { 'clangtidy' }, + python = { 'ruff' }, + bash = { 'shellcheck' }, + nix = { 'statix' }, + } + + vim.api.nvim_create_autocmd({ 'BufWritePost' }, { + callback = function() + lint.try_lint() + end, + }) +end + +return M diff --git a/lua/plugins/config/lsp/init.lua b/lua/plugins/config/lsp/init.lua index 4100911..fca3571 100644 --- a/lua/plugins/config/lsp/init.lua +++ b/lua/plugins/config/lsp/init.lua @@ -2,8 +2,6 @@ local M = {} function M.setup() - local lspconfig = require 'lspconfig' - -- Get capabilities from blink.cmp if available local capabilities = vim.lsp.protocol.make_client_capabilities() @@ -11,7 +9,7 @@ function M.setup() if ok then capabilities = blink_cmp.get_lsp_capabilities(capabilities) end - -- + -- Set global position encoding preference capabilities.general.positionEncodings = { 'utf-16' } @@ -22,11 +20,27 @@ function M.setup() for name, config in pairs(servers) do config.capabilities = vim.tbl_deep_extend('force', {}, capabilities, config.capabilities or {}) vim.lsp.config(name, config) - vim.lsp.enable(name) -- Actually start the server! + vim.lsp.enable(name) -- Actually start the server! end -- Setup LSP keymaps require('plugins.config.lsp.keymaps').setup() + + vim.diagnostic.config { + virtual_text = { + source = true, + prefix = '●', + }, + float = { + source = true, + }, + signs = true, + underline = true, + update_in_insert = false, + severity_sort = true, + } + + vim.api.nvim_set_hl(0, 'DiagnosticUnnecessary', {}) end return M diff --git a/lua/plugins/config/lsp/keymaps.lua b/lua/plugins/config/lsp/keymaps.lua index ed8a1fa..df774c2 100644 --- a/lua/plugins/config/lsp/keymaps.lua +++ b/lua/plugins/config/lsp/keymaps.lua @@ -12,35 +12,58 @@ function M.setup() vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) end - -- Navigation keymaps (using kickstart.nvim patterns) - map('gd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') - map('grr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') - map('gri', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') - map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype definition') - map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') - + -- Navigation keymaps + map('cd', require('telescope.builtin').lsp_definitions, '[C]ode [D]efinition') + map('cr', require('telescope.builtin').lsp_references, '[C]ode [R]eferences') + map('ci', require('telescope.builtin').lsp_implementations, '[C]ode [I]mplementation') + map('ct', require('telescope.builtin').lsp_type_definitions, '[C]ode [T]ype definition') + map('cD', vim.lsp.buf.declaration, '[C]ode [D]eclaration') + -- Symbol operations - map('grn', vim.lsp.buf.rename, '[G]oto [R]e[n]ame') - map('gra', vim.lsp.buf.code_action, '[G]oto code [A]ction', { 'n', 'x' }) - map('gO', require('telescope.builtin').lsp_document_symbols, '[G]oto [O]pen document symbols') - map('gW', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[G]oto [W]orkspace symbols') - + map('cf', vim.lsp.buf.rename, '[C]ode Re[f]actor') + map('ca', vim.lsp.buf.code_action, '[C]ode [A]ction', { 'n', 'x' }) + map('cs', require('telescope.builtin').lsp_document_symbols, '[C]ode [S]ymbols') + map('cS', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[C]ode workspace [S]ymbols') + -- Documentation map('K', vim.lsp.buf.hover, 'Hover Documentation') - map('', vim.lsp.buf.signature_help, 'Signature help') - - -- Formatting - map('f', function() - vim.lsp.buf.format { async = true } - end, '[F]ormat buffer') + -- map('', vim.lsp.buf.signature_help, 'Signature help') + map('ch', function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) + end, '[C]ode [H]int toggle') end, }) - + + -- LSP reload function + local function reload_lsp() + local clients = vim.lsp.get_clients() + if #clients == 0 then + print 'No LSP clients running' + return + end + + for _, client in ipairs(clients) do + vim.lsp.stop_client(client.id) + end + + vim.defer_fn(function() + vim.cmd 'LspStart' + print 'LSP servers reloaded' + end, 500) + end + + -- Reload LSP keybind + vim.keymap.set('n', 'cR', reload_lsp, { desc = 'LSP: [C]ode [R]eload LSP servers' }) + -- Diagnostic keymaps (available globally, not just when LSP attaches) - vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Go to previous [D]iagnostic message' }) - vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Go to next [D]iagnostic message' }) + vim.keymap.set('n', '[d', function() + vim.diagnostic.goto_prev { float = false } + end, { desc = 'Go to previous [D]iagnostic message' }) + vim.keymap.set('n', ']d', function() + vim.diagnostic.goto_next { float = false } + end, { desc = 'Go to next [D]iagnostic message' }) vim.keymap.set('n', 'e', vim.diagnostic.open_float, { desc = 'Show diagnostic [E]rror messages' }) vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' }) end -return M \ No newline at end of file +return M diff --git a/lua/plugins/config/lsp/servers.lua b/lua/plugins/config/lsp/servers.lua index 7e244c4..521f2e9 100644 --- a/lua/plugins/config/lsp/servers.lua +++ b/lua/plugins/config/lsp/servers.lua @@ -1,62 +1,26 @@ -- LSP Server Configurations local M = {} -local util = require 'lspconfig.util' - --- Get clang-wrapper resource-root for Nix environments -local function get_clang_resource_dir() - -- Try to find clang-wrapper's resource-root - local handle = io.popen 'ls -d /nix/store/*clang-wrapper*/resource-root 2>/dev/null | head -1' - if handle then - local resource_root = handle:read '*l' - handle:close() - if resource_root and resource_root ~= '' then - return resource_root - end - end - return nil -- Let clangd use its default -end - function M.get_servers() -- Build clangd command - local clangd_cmd = { - 'clangd', - '--query-driver=/nix/store/*/bin/clang*', - '--background-index', - '--clang-tidy', - '--enable-config', - '--fallback-style=llvm', - '--function-arg-placeholders', - '--header-insertion-decorators', - '--header-insertion=iwyu', - } - - -- Add resource-dir if in Nix environment - local resource_dir = get_clang_resource_dir() - if resource_dir then - table.insert(clangd_cmd, '--resource-dir=' .. resource_dir) - end return { -- C/C++ Language Server clangd = { - cmd = clangd_cmd, + cmd = { + 'clangd', + '--background-index', + '--completion-style=detailed', + '--enable-config', + '--fallback-style=llvm', + '--function-arg-placeholders=1', + '--header-insertion-decorators', + '--header-insertion=iwyu', + '--pch-storage=memory', + }, filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'cuda' }, -- Look for project markers - clangd will find compile_commands.json itself - root_dir = util.root_pattern( - -- First check for any compile_commands.json anywhere - 'compile_commands.json', - -- Then check common build directories - 'build/compile_commands.json', - 'Debug/compile_commands.json', - 'Release/compile_commands.json', - -- Project markers - '.clangd', - 'compile_flags.txt', - 'CMakeLists.txt', - 'Makefile', - '.git' - ), + root_markers = { '.clangd', 'compile_commands.json', 'CMakeLists.txt', '.git' }, single_file_support = true, }, @@ -70,7 +34,7 @@ function M.get_servers() typeCheckingMode = 'basic', useLibraryCodeForTypes = true, autoImportCompletions = true, - + -- Help with type hints inlayHints = { variableTypes = true, @@ -84,13 +48,13 @@ function M.get_servers() reportOptionalMemberAccess = 'none', reportOptionalIterable = 'none', reportAttributeAccessIssue = 'none', - reportUnknownMemberType = 'none', -- Changed to none for less noise - reportUnknownVariableType = 'none', -- Changed to none - reportUnknownArgumentType = 'none', -- Added - reportGeneralTypeIssues = 'none', -- Added - reportUnknownParameterType = 'none', -- Added - reportUnknownAssignmentType = 'none', -- From main - reportMissingTypeStubs = 'none', -- From main + reportUnknownMemberType = 'none', -- Changed to none for less noise + reportUnknownVariableType = 'none', -- Changed to none + reportUnknownArgumentType = 'none', -- Added + reportGeneralTypeIssues = 'none', -- Added + reportUnknownParameterType = 'none', -- Added + reportUnknownAssignmentType = 'none', -- From main + reportMissingTypeStubs = 'none', -- From main }, }, }, @@ -117,7 +81,7 @@ function M.get_servers() cmake = { cmd = { 'cmake-language-server' }, filetypes = { 'cmake' }, - root_dir = util.root_pattern('CMakeLists.txt', '.git'), + root_markers = { 'compile_commands.json', 'CMakeLists.txt', '.git' }, }, -- Lua Language Server @@ -127,6 +91,7 @@ function M.get_servers() runtime = { version = 'LuaJIT' }, diagnostics = { globals = { 'vim' }, + unusedLocalExclude = { '_*' }, }, workspace = { library = vim.api.nvim_get_runtime_file('', true), @@ -158,7 +123,10 @@ function M.get_servers() -- OCaml Language Server ocamllsp = { filetypes = { 'ocaml', 'ocaml.menhir', 'ocaml.interface', 'ocaml.ocamllex', 'reason', 'dune' }, - root_dir = util.root_pattern('*.opam', 'esy.json', 'package.json', '.git', 'dune-project', 'dune-workspace'), + root_markers = { '*.opam', 'esy.json', 'package.json', '.git', 'dune-project', 'dune-workspace' }, + cmd_env = { + PATH = vim.env.PATH, -- Inherit PATH from Neovim's environment + }, settings = { ocaml = { lens = { diff --git a/lua/plugins/config/molten.lua b/lua/plugins/config/molten.lua index 29379dd..7dc4eb5 100644 --- a/lua/plugins/config/molten.lua +++ b/lua/plugins/config/molten.lua @@ -4,15 +4,15 @@ function M.setup() -- Keybindings local map = vim.keymap.set - map('n', 'mi', ':MoltenInit', { desc = 'Molten: Initialize' }) - map('n', 'me', ':MoltenEvaluateOperator', { desc = 'Molten: Evaluate operator' }) - map('n', 'ml', ':MoltenEvaluateLine', { desc = 'Molten: Evaluate line' }) - map('n', 'mr', ':MoltenReevaluateCell', { desc = 'Molten: Re-evaluate cell' }) - map('v', 'me', ':MoltenEvaluateVisualgv', { desc = 'Molten: Evaluate visual' }) - map('n', 'md', ':MoltenDelete', { desc = 'Molten: Delete cell' }) - map('n', 'mo', ':MoltenShowOutput', { desc = 'Molten: Show output' }) - map('n', 'mh', ':MoltenHideOutput', { desc = 'Molten: Hide output' }) - map('n', 'mx', ':MoltenInterrupt', { desc = 'Molten: Interrupt kernel' }) + map('n', 'Mi', ':MoltenInit', { desc = 'Molten: Initialize' }) + map('n', 'Me', ':MoltenEvaluateOperator', { desc = 'Molten: Evaluate operator' }) + map('v', 'Me', ':MoltenEvaluateVisualgv', { desc = 'Molten: Evaluate visual' }) + map('n', 'Ml', ':MoltenEvaluateLine', { desc = 'Molten: Evaluate line' }) + map('n', 'Mr', ':MoltenReevaluateCell', { desc = 'Molten: Re-evaluate cell' }) + map('n', 'Md', ':MoltenDelete', { desc = 'Molten: Delete cell' }) + map('n', 'Mo', ':MoltenShowOutput', { desc = 'Molten: Show output' }) + map('n', 'Mh', ':MoltenHideOutput', { desc = 'Molten: Hide output' }) + map('n', 'Mx', ':MoltenInterrupt', { desc = 'Molten: Interrupt kernel' }) end return M diff --git a/lua/plugins/config/telescope.lua b/lua/plugins/config/telescope.lua index a22343c..7799f4f 100644 --- a/lua/plugins/config/telescope.lua +++ b/lua/plugins/config/telescope.lua @@ -2,10 +2,10 @@ local M = {} function M.setup() - local telescope = require('telescope') - local builtin = require('telescope.builtin') - - telescope.setup({ + local telescope = require 'telescope' + local builtin = require 'telescope.builtin' + + telescope.setup { defaults = { prompt_prefix = '> ', selection_caret = '> ', @@ -41,14 +41,14 @@ function M.setup() case_mode = 'smart_case', }, }, - }) - + } + -- Load extensions pcall(telescope.load_extension, 'fzf') pcall(telescope.load_extension, 'ui-select') - + -- Setup keymaps - vim.keymap.set('n', 'sf', builtin.find_files, { desc = '[S]earch [F]iles' }) + vim.keymap.set('n', '', builtin.find_files, { desc = '[S]earch files' }) vim.keymap.set('n', 'sg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) vim.keymap.set('n', 'sh', builtin.help_tags, { desc = '[S]earch [H]elp' }) vim.keymap.set('n', 'sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' }) @@ -65,7 +65,7 @@ function M.setup() previewer = false, }) end, { desc = '[/] Fuzzily search in current buffer' }) - + -- Search in open files vim.keymap.set('n', 's/', function() builtin.live_grep { @@ -73,15 +73,11 @@ function M.setup() prompt_title = 'Live Grep in Open Files', } end, { desc = '[S]earch [/] in Open Files' }) - + -- Search in neovim config vim.keymap.set('n', 'sn', function() builtin.find_files { cwd = vim.fn.stdpath 'config' } end, { desc = '[S]earch [N]eovim files' }) - - -- C/C++ compile_commands.json picker - vim.keymap.set('n', 'sc', 'CompileCommandsPicker', - { desc = '[S]earch [C]ompile commands.json' }) end -return M \ No newline at end of file +return M diff --git a/lua/plugins/spec/autopairs.lua b/lua/plugins/spec/autopairs.lua index 9e0ac70..48f8577 100644 --- a/lua/plugins/spec/autopairs.lua +++ b/lua/plugins/spec/autopairs.lua @@ -1,58 +1,9 @@ -- Auto-pairs - Automatically close brackets, quotes, etc. return { - 'windwp/nvim-autopairs', - event = 'InsertEnter', - opts = { - check_ts = true, - ts_config = { - lua = { 'string', 'source' }, - javascript = { 'string', 'template_string' }, - }, - disable_filetype = { 'TelescopePrompt', 'spectre_panel' }, - fast_wrap = { - map = '', - chars = { '{', '[', '(', '"', "'" }, - pattern = string.gsub([[ [%'%"%)%>%]%)%}%,] ]], '%s+', ''), - offset = 0, - end_key = '$', - keys = 'qwertyuiopzxcvbnmasdfghjkl', - check_comma = true, - highlight = 'PmenuSel', - highlight_grey = 'LineNr', - }, - }, - config = function(_, opts) - local npairs = require('nvim-autopairs') - npairs.setup(opts) - - -- UNIFIED KEY TO KILL AUTO-INSERTED STUFF - -- already kills auto-inserted comments (built-in) - -- Let's add to also kill auto-paired character - - vim.keymap.set('i', '', function() - local line = vim.api.nvim_get_current_line() - local col = vim.fn.col('.') - 1 - - -- Check if we're at the beginning of a line with just comment chars - local comment_pattern = '^%s*[#%-/]+%s*$' - if line:sub(1, col):match(comment_pattern) then - -- Kill the whole comment prefix (default behavior) - return '' - -- Check if cursor is between paired characters - elseif col > 0 and col < #line then - local before = line:sub(col, col) - local after = line:sub(col + 1, col + 1) - local pairs = {['('] = ')', ['['] = ']', ['{'] = '}', ['"'] = '"', ["'"] = "'"} - if pairs[before] == after then - -- Delete the closing pair - return '' - end - end - -- Otherwise, regular (kill to start of line) - return '' - end, { expr = true, desc = 'Kill auto-insert or line to start' }) - - -- Alternative: to delete just the auto-paired closing character - vim.keymap.set('i', '', '', { desc = 'Delete next char (kills auto-pair)' }) + 'saghen/blink.pairs', + version = '0.4.0', + dependencies = 'saghen/blink.download', + config = function() + require('plugins.config.autopairs').setup() end, -} \ No newline at end of file +} diff --git a/lua/plugins/spec/blink.lua b/lua/plugins/spec/blink.lua deleted file mode 100644 index 0c3acd8..0000000 --- a/lua/plugins/spec/blink.lua +++ /dev/null @@ -1,12 +0,0 @@ --- Blink.cmp - Modern completion plugin -return { - 'saghen/blink.cmp', - lazy = false, -- Lazy loading handled internally - dependencies = { - 'giuxtaposition/blink-cmp-copilot', - }, - version = 'v0.*', -- Use stable releases - config = function() - require('plugins.config.blink').setup() - end, -} \ No newline at end of file diff --git a/lua/plugins/spec/completion.lua b/lua/plugins/spec/completion.lua new file mode 100644 index 0000000..9c1c979 --- /dev/null +++ b/lua/plugins/spec/completion.lua @@ -0,0 +1,26 @@ +return { + { + 'saghen/blink.cmp', + version = 'v0.*', -- Use stable releases + event = { 'InsertEnter', 'CmdlineEnter' }, + config = function() + require('plugins.config.completion').setup_blink() + end, + }, + { + 'zbirenbaum/copilot.lua', + enabled = vim.g.copilot_enabled, + event = 'InsertEnter', + config = function() + require('plugins.config.completion').setup_copilot() + end, + }, + { + 'saghen/blink-cmp-copilot', + enabled = vim.g.copilot_enabled, + dependencies = { 'saghen/blink.cmp', 'zbirenbaum/copilot.lua' }, + config = function() + require('plugins.config.completion').setup_blink_copilot() + end, + }, +} diff --git a/lua/plugins/spec/copilot.lua b/lua/plugins/spec/copilot.lua deleted file mode 100644 index a63b99b..0000000 --- a/lua/plugins/spec/copilot.lua +++ /dev/null @@ -1,12 +0,0 @@ --- GitHub Copilot integration -return { - 'zbirenbaum/copilot.lua', - enabled = vim.g.copilot_enabled == true, -- Only load if enabled by Nix - cmd = 'Copilot', - event = 'InsertEnter', - opts = { - panel = { - layout = { position = 'right' }, - }, - }, -} diff --git a/lua/plugins/spec/formatting.lua b/lua/plugins/spec/formatting.lua index ecf66fe..7951f93 100644 --- a/lua/plugins/spec/formatting.lua +++ b/lua/plugins/spec/formatting.lua @@ -7,8 +7,16 @@ return { { 'stevearc/conform.nvim', event = 'BufWritePre', -- Format on save - -- cmd = { 'ConformInfo' }, -- Optional: If you want the command available - -- keys = { ... } -- Optional: Define keys if needed + cmd = { 'ConformInfo' }, + keys = { + { + 'f', + function() + return require('conform').format { async = true, lsp_fallback = true } + end, + desc = '[F]ormat buffer', + }, + }, opts = { formatters_by_ft = { -- Core languages diff --git a/lua/plugins/spec/init.lua b/lua/plugins/spec/init.lua deleted file mode 100644 index 332df01..0000000 --- a/lua/plugins/spec/init.lua +++ /dev/null @@ -1,30 +0,0 @@ --- Main plugin loader - imports all plugin specifications -return { - -- UI and Theme - { import = 'plugins.spec.ui' }, - { import = 'plugins.spec.editor' }, - { import = 'plugins.spec.autopairs' }, - { import = 'plugins.spec.indent-line' }, - - -- Core functionality - { import = 'plugins.spec.lsp' }, - { import = 'plugins.spec.treesitter' }, - { import = 'plugins.spec.telescope' }, - { import = 'plugins.spec.blink' }, - - -- Git integration - { import = 'plugins.spec.git' }, - - -- Development tools - { import = 'plugins.spec.ocaml' }, - { import = 'plugins.spec.jupyter' }, - { import = 'plugins.spec.copilot' }, - { import = 'plugins.spec.debug' }, - { import = 'plugins.spec.formatting' }, - { import = 'plugins.spec.leetcode' }, - { import = 'plugins.spec.training' }, - - -- Navigation - { import = 'plugins.spec.nvim-tmux-navigator' }, - { import = 'plugins.spec.harpoon' }, -} diff --git a/lua/plugins/spec/lint.lua b/lua/plugins/spec/lint.lua new file mode 100644 index 0000000..1d93357 --- /dev/null +++ b/lua/plugins/spec/lint.lua @@ -0,0 +1,7 @@ +return { + 'mfussenegger/nvim-lint', + event = { 'BufReadPost', 'BufNewFile' }, + config = function() + require('plugins.config.lint').setup() + end, +} diff --git a/lua/plugins/spec/oil.lua b/lua/plugins/spec/oil.lua new file mode 100644 index 0000000..32a62b9 --- /dev/null +++ b/lua/plugins/spec/oil.lua @@ -0,0 +1,26 @@ +return { + 'stevearc/oil.nvim', + dependencies = { 'nvim-tree/nvim-web-devicons' }, + lazy = false, + keys = { + { '-', 'Oil', desc = 'Open parent directory' }, + { '-', 'Oil .', desc = 'Open current directory' }, + }, + opts = { + default_file_explorer = true, + delete_to_trash = true, + skip_confirm_for_simple_edits = true, + view_options = { + show_hidden = true, + is_hidden_file = function(name, _) + return vim.startswith(name, '.') + end, + }, + keymaps = { + [''] = false, + [''] = false, + [''] = false, + [''] = false, + }, + }, +} diff --git a/lua/plugins/spec/telescope.lua b/lua/plugins/spec/telescope.lua index e6759e6..eba782e 100644 --- a/lua/plugins/spec/telescope.lua +++ b/lua/plugins/spec/telescope.lua @@ -17,7 +17,6 @@ return { }, config = function() require('plugins.config.telescope').setup() - -- Setup compile_commands.json picker for C/C++ projects - require('plugins.config.compile-commands-picker').setup() end, -} \ No newline at end of file +} + diff --git a/lua/plugins/spec/treesitter.lua b/lua/plugins/spec/treesitter.lua index 0c3cf5d..7e21f6b 100644 --- a/lua/plugins/spec/treesitter.lua +++ b/lua/plugins/spec/treesitter.lua @@ -35,11 +35,12 @@ return { incremental_selection = { enable = true, keymaps = { - init_selection = '', - node_incremental = '', - scope_incremental = false, - node_decremental = '', + init_selection = 'gnn', + node_incremental = 'grn', + scope_incremental = 'grc', + node_decremental = 'grm', }, }, }, -} \ No newline at end of file +} +