diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua index e5ba039..40f1fc6 100644 --- a/.config/nvim/init.lua +++ b/.config/nvim/init.lua @@ -7,6 +7,11 @@ require("config.lazy") -- Plugin settings require("config.plugins.treesitter") +require("config.plugins.lsp") +require("config.plugins.completion") +require("config.plugins.telescope") +require("config.plugins.explorer") +require("config.plugins.whichkey") -- Configure UI components last require("config.theme") diff --git a/.config/nvim/lazy-lock.json b/.config/nvim/lazy-lock.json index ec6feba..2873526 100644 --- a/.config/nvim/lazy-lock.json +++ b/.config/nvim/lazy-lock.json @@ -9,9 +9,9 @@ "mason.nvim": { "branch": "main", "commit": "fc98833b6da5de5a9c5b1446ac541577059555be" }, "nvim-cmp": { "branch": "main", "commit": "059e89495b3ec09395262f16b1ad441a38081d04" }, "nvim-deus": { "branch": "master", "commit": "b930172dc75d00084233abc6f19f0708c298d8be" }, - "nvim-lspconfig": { "branch": "master", "commit": "40f120c10ea4b87311175539a183c3b75eab95a3" }, - "nvim-tree.lua": { "branch": "master", "commit": "44d9b58f11d5a426c297aafd0be1c9d45617a849" }, - "nvim-treesitter": { "branch": "master", "commit": "30654ee72a69e7c76a54b66d748dae088429e863" }, + "nvim-lspconfig": { "branch": "master", "commit": "3e873195f501b1e02d9fd7e5af5cbe74fc2f98c1" }, + "nvim-tree.lua": { "branch": "master", "commit": "c3c193594213c5e2f89ec5d7729cad805f76b256" }, + "nvim-treesitter": { "branch": "master", "commit": "523a9e148919f58eb5a013f76787e57696e00c93" }, "nvim-web-devicons": { "branch": "master", "commit": "4c3a5848ee0b09ecdea73adcd2a689190aeb728c" }, "plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" }, "telescope.nvim": { "branch": "master", "commit": "a4ed82509cecc56df1c7138920a1aeaf246c0ac5" }, diff --git a/.config/nvim/lua/config/plugins/completion.lua b/.config/nvim/lua/config/plugins/completion.lua new file mode 100644 index 0000000..e52f164 --- /dev/null +++ b/.config/nvim/lua/config/plugins/completion.lua @@ -0,0 +1,81 @@ +-- completion.lua +local has_cmp, cmp = pcall(require, 'cmp') +if not has_cmp then + print("Warning: nvim-cmp not found. Autocompletion won't be available.") + return +end + +local has_luasnip, luasnip = pcall(require, 'luasnip') +if not has_luasnip then + print("Warning: luasnip not found. Snippet expansion won't be available.") + return +end + +cmp.setup({ + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + window = { + completion = cmp.config.window.bordered(), + documentation = cmp.config.window.bordered(), + }, + mapping = cmp.mapping.preset.insert({ + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.abort(), + [''] = cmp.mapping.confirm({ select = false }), -- Accept explicitly selected item + + -- Tab support + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + else + fallback() + end + end, { 'i', 's' }), + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { 'i', 's' }), + }), + sources = cmp.config.sources({ + { name = 'nvim_lsp' }, + { name = 'luasnip' }, + { name = 'buffer' }, + { name = 'path' }, + }), + formatting = { + format = function(entry, vim_item) + -- Add icons + vim_item.menu = ({ + nvim_lsp = "[LSP]", + luasnip = "[Snippet]", + buffer = "[Buffer]", + path = "[Path]", + })[entry.source.name] + return vim_item + end, + }, +}) + +-- Enable command-line completion +cmp.setup.cmdline(':', { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ + { name = 'path' }, + { name = 'cmdline' } + }) +}) + +print("Completion system initialized!") + diff --git a/.config/nvim/lua/config/plugins/explorer.lua b/.config/nvim/lua/config/plugins/explorer.lua new file mode 100644 index 0000000..7b55020 --- /dev/null +++ b/.config/nvim/lua/config/plugins/explorer.lua @@ -0,0 +1,51 @@ +-- explorer.lua +-- Check if nvim-tree is available +local has_tree, nvim_tree = pcall(require, "nvim-tree") +if not has_tree then + print("Warning: nvim-tree not found. File explorer won't be available.") + return +end + +-- Set up nvim-tree with error handling +local setup_ok, _ = pcall(nvim_tree.setup, { + sort_by = "case_sensitive", + view = { + width = 30, + }, + renderer = { + group_empty = true, + icons = { + show = { + git = true, + folder = true, + file = true, + folder_arrow = true, + }, + }, + }, + filters = { + dotfiles = false, + }, + git = { + enable = true, + ignore = false, + }, + actions = { + open_file = { + quit_on_open = false, + resize_window = true, + }, + }, +}) + +if not setup_ok then + print("Error setting up nvim-tree. Some features might not work correctly.") + return +end + +-- Recommended mappings +vim.keymap.set('n', 'e', 'NvimTreeToggle', { desc = "Toggle file explorer" }) +vim.keymap.set('n', 'fe', 'NvimTreeFocus', { desc = "Focus file explorer" }) + +print("File explorer initialized!") + diff --git a/.config/nvim/lua/config/plugins/lsp.lua b/.config/nvim/lua/config/plugins/lsp.lua new file mode 100644 index 0000000..422e669 --- /dev/null +++ b/.config/nvim/lua/config/plugins/lsp.lua @@ -0,0 +1,108 @@ +-- lsp.lua +-- Install Mason first for managing servers +require("mason").setup({ + ui = { + icons = { + package_installed = "✓", + package_pending = "➜", + package_uninstalled = "✗" + } + } +}) + +-- Connect Mason with lspconfig +require("mason-lspconfig").setup({ + -- Automatically install these servers + ensure_installed = { + "lua_ls", -- Lua + "pyright", -- Python + "biome", -- TypeScript/JavaScript + "rust_analyzer", -- Rust + "gopls", -- Go + "clangd", -- C/C++ + "bashls", -- Bash + }, + automatic_installation = true, +}) + +-- Set up LSP capabilities (used by completion) +local capabilities = vim.lsp.protocol.make_client_capabilities() +-- Check if nvim-cmp is available to enhance capabilities +local has_cmp, cmp_lsp = pcall(require, 'cmp_nvim_lsp') +if has_cmp then + capabilities = cmp_lsp.default_capabilities(capabilities) +end + +-- Function to set up all installed LSP servers +local on_attach = function(client, bufnr) + -- Enable completion triggered by + vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') + + -- Key mappings + local bufopts = { noremap=true, silent=true, buffer=bufnr } + vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts) + vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts) + vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts) + vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, bufopts) + vim.keymap.set('n', '', vim.lsp.buf.signature_help, bufopts) + vim.keymap.set('n', 'rn', vim.lsp.buf.rename, bufopts) + vim.keymap.set('n', 'ca', vim.lsp.buf.code_action, bufopts) + vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts) + vim.keymap.set('n', 'lf', function() vim.lsp.buf.format { async = true } end, bufopts) + + -- Log a message when a server attaches + print(string.format("LSP server '%s' attached to this buffer", client.name)) +end + +-- Set up all servers installed via Mason +require("mason-lspconfig").setup_handlers { + -- Default handler for installed servers + function(server_name) + require('lspconfig')[server_name].setup { + on_attach = on_attach, + capabilities = capabilities, + } + end, + + -- Special configurations for specific servers + ["lua_ls"] = function() + require('lspconfig').lua_ls.setup { + on_attach = on_attach, + capabilities = capabilities, + settings = { + Lua = { + runtime = { version = 'LuaJIT' }, + diagnostics = { globals = {'vim'} }, + workspace = { + library = vim.api.nvim_get_runtime_file("", true), + checkThirdParty = false, + }, + telemetry = { enable = false }, + }, + }, + } + end, +} + +-- Configure diagnostic display +vim.diagnostic.config({ + virtual_text = { + prefix = '●', -- Could be '■', '▎', 'x' + source = "if_many", + }, + float = { + source = "always", + border = "rounded", + }, + signs = true, + underline = true, + update_in_insert = false, + severity_sort = true, +}) + +-- Change diagnostic symbols in the sign column +local signs = { Error = " ", Warn = " ", Hint = " ", Info = " " } +for type, icon in pairs(signs) do + local hl = "DiagnosticSign" .. type + vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl }) +end diff --git a/.config/nvim/lua/config/plugins/telescope.lua b/.config/nvim/lua/config/plugins/telescope.lua new file mode 100644 index 0000000..dd9558a --- /dev/null +++ b/.config/nvim/lua/config/plugins/telescope.lua @@ -0,0 +1,56 @@ +-- telescope.lua +-- Check if telescope is available +local has_telescope, telescope = pcall(require, "telescope") +if not has_telescope then + print("Warning: telescope not found. Fuzzy finding won't be available.") + return +end + +-- Set up telescope with error handling +local setup_ok, _ = pcall(telescope.setup, { + defaults = { + prompt_prefix = "🔍 ", + selection_caret = "❯ ", + path_display = { "truncate" }, + layout_config = { + horizontal = { + preview_width = 0.55, + results_width = 0.8, + }, + width = 0.87, + height = 0.80, + preview_cutoff = 120, + }, + file_ignore_patterns = { + "node_modules/", + ".git/", + ".DS_Store" + }, + }, + extensions = { + -- Configure any extensions here + } +}) + +if not setup_ok then + print("Error setting up telescope. Some features might not work correctly.") + return +end + +-- Load telescope extensions if available +pcall(function() require('telescope').load_extension('fzf') end) + +-- Useful Telescope mappings with error handling +local builtin_ok, builtin = pcall(require, 'telescope.builtin') +if builtin_ok then + vim.keymap.set('n', 'ff', builtin.find_files, { desc = "Find files" }) + vim.keymap.set('n', 'fg', builtin.live_grep, { desc = "Live grep" }) + vim.keymap.set('n', 'fb', builtin.buffers, { desc = "Buffers" }) + vim.keymap.set('n', 'fh', builtin.help_tags, { desc = "Help tags" }) + -- LSP-related searches + vim.keymap.set('n', 'fd', builtin.lsp_definitions, { desc = "Find definitions" }) + vim.keymap.set('n', 'fr', builtin.lsp_references, { desc = "Find references" }) +end + +print("Fuzzy finder initialized!") + diff --git a/.config/nvim/lua/config/plugins/whichkey.lua b/.config/nvim/lua/config/plugins/whichkey.lua new file mode 100644 index 0000000..a57d1cb --- /dev/null +++ b/.config/nvim/lua/config/plugins/whichkey.lua @@ -0,0 +1,78 @@ +-- whichkey.lua +-- Check if which-key is available +local has_which_key, which_key = pcall(require, "which-key") +if not has_which_key then + print("Warning: which-key not found. Key binding help won't be available.") + return +end + +-- Set up which-key with error handling +local setup_ok, _ = pcall(which_key.setup, { + plugins = { + marks = true, + registers = true, + spelling = { + enabled = true, + suggestions = 20, + }, + presets = { + operators = true, + motions = true, + text_objects = true, + windows = true, + nav = true, + z = true, + g = true, + }, + }, + window = { + border = "rounded", + padding = { 2, 2, 2, 2 }, + }, + layout = { + height = { min = 4, max = 25 }, + width = { min = 20, max = 50 }, + }, + ignore_missing = false, +}) + +if not setup_ok then + print("Error setting up which-key. Key binding help won't work correctly.") + return +end + +-- Register key bindings with which-key +local register_ok, _ = pcall(which_key.register, { + f = { + name = "File", -- Optional group name + f = { "Telescope find_files", "Find File" }, + r = { "Telescope oldfiles", "Recent Files" }, + g = { "Telescope live_grep", "Live Grep" }, + b = { "Telescope buffers", "Buffers" }, + n = { "enew", "New File" }, + }, + e = { "NvimTreeToggle", "Explorer" }, + l = { + name = "LSP", + d = { "Telescope lsp_definitions", "Definitions" }, + r = { "Telescope lsp_references", "References" }, + a = { "lua vim.lsp.buf.code_action()", "Code Action" }, + f = { "lua vim.lsp.buf.format()", "Format" }, + h = { "lua vim.lsp.buf.hover()", "Hover" }, + R = { "lua vim.lsp.buf.rename()", "Rename" }, + }, + b = { + name = "Buffer", + n = { "bnext", "Next Buffer" }, + p = { "bprevious", "Previous Buffer" }, + d = { "bdelete", "Delete Buffer" }, + }, +}, { prefix = "" }) + +if not register_ok then + print("Error registering which-key bindings.") + return +end + +print("Key binding help initialized!") +