diff --git a/lazy-lock.json b/lazy-lock.json index 6f8f445..2c62387 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -1,23 +1,37 @@ { + "LuaSnip": { "branch": "master", "commit": "0abc8f390b278c3b4aabc4c004ac8a088b65cf24" }, + "barbar.nvim": { "branch": "master", "commit": "53b5a2f34b68875898f0531032fbf090e3952ad7" }, + "cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" }, + "cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" }, + "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "gitsigns.nvim": { "branch": "main", "commit": "2038c666bd9d8a0b7349a0b6ee00dc83104b9ecf" }, "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, "lazygit.nvim": { "branch": "main", "commit": "a04ad0dbc725134edbee3a5eea29290976695357" }, "leetcode.nvim": { "branch": "master", "commit": "4e8b3683940a8377379ce9398e7f329e3560b42c" }, "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "47059d71b42d74b0a1e9f61c1d99d301039c3b5b" }, + "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, "mini.ai": { "branch": "main", "commit": "d73c36349aa7b0bab5f77ad71701a1d42211a1df" }, "mini.bracketed": { "branch": "main", "commit": "7662c280946faf573c4eabf307d78406ad0783e4" }, "mini.comment": { "branch": "main", "commit": "4677392f091e8b5c18d4b535130220a6d1da4aca" }, "mini.cursorword": { "branch": "main", "commit": "331bc17172e41343d39d91a4ab571d510766812e" }, "mini.indentscope": { "branch": "main", "commit": "d3f955f09b1a05d25d5a7740338fba2baaee41a3" }, "mini.move": { "branch": "main", "commit": "b9e452f9c83565a1520e14f7531632160f3b0170" }, + "mini.nvim": { "branch": "main", "commit": "1599a473aa6f5290a5d740b1144846e6f0c3963d" }, "mini.pairs": { "branch": "main", "commit": "4a014143fcb4e9df26198ccb3ecff3b9e77a048c" }, "mini.surround": { "branch": "main", "commit": "580e4cb98c5900d9fe743865fb5a5b2178b4ab18" }, "mini.tabline": { "branch": "main", "commit": "7e8584a06b86902c64227e4abd0c39ae74061101" }, "mini.trailspace": { "branch": "main", "commit": "22653218f1aedc9bf306c8b4e8ec2c8a575f6fae" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-cmp": { "branch": "main", "commit": "a1d504892f2bc56c2e79b65c6faded2fd21f3eca" }, + "nvim-lspconfig": { "branch": "master", "commit": "3371bf298c1f56efc26771ee961f461176958fb5" }, "nvim-tree.lua": { "branch": "master", "commit": "85d1145ac71c1b8e1423862c78165a1f609faf60" }, "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, "nvim-web-devicons": { "branch": "master", "commit": "dfbfaa967a6f7ec50789bead7ef87e336c1fa63c" }, "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, + "render-markdown.nvim": { "branch": "main", "commit": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a" }, "telescope-fzf-native.nvim": { "branch": "main", "commit": "b25b749b9db64d375d782094e2b9dce53ad53a40" }, "telescope.nvim": { "branch": "master", "commit": "5255aa27c422de944791318024167ad5d40aad20" } } diff --git a/lua/config/keymaps.lua b/lua/config/keymaps.lua index 159cdbb..fa5fb49 100644 --- a/lua/config/keymaps.lua +++ b/lua/config/keymaps.lua @@ -3,6 +3,8 @@ vim.g.maplocalleader = " " vim.keymap.set("n", "bn", ":bnext", { desc = "Next buffer" }) vim.keymap.set("n", "bp", ":bprevious", { desc = "Previous buffer" }) +vim.keymap.set("n", "H", ":bprevious", { desc = "Previous buffer" }) +vim.keymap.set("n", "L", ":bnext", { desc = "Next buffer" }) vim.keymap.set("n", "bd", ":bdelete", { desc = "Delete current buffer" }) vim.keymap.set("n", "bo", function() local current_buf = vim.api.nvim_get_current_buf() @@ -21,6 +23,12 @@ vim.keymap.set("n", "", ":resize -2", { desc = "Decrease window heig vim.keymap.set("n", "", ":vertical resize -2", { desc = "Decrease window width" }) vim.keymap.set("n", "", ":vertical resize +2", { desc = "Increase window width" }) +-- Window navigation +vim.keymap.set("n", "", "h", { desc = "Go to left window" }) +vim.keymap.set("n", "", "j", { desc = "Go to lower window" }) +vim.keymap.set("n", "", "k", { desc = "Go to upper window" }) +vim.keymap.set("n", "", "l", { desc = "Go to right window" }) + vim.keymap.set("n", "", ":m .+1==", { desc = "Move line down" }) vim.keymap.set("n", "", ":m .-2==", { desc = "Move line up" }) vim.keymap.set("v", "", ":m '>+1gv=gv", { desc = "Move selection down" }) @@ -29,7 +37,7 @@ vim.keymap.set("v", "", ":m '<-2gv=gv", { desc = "Move selection up" }) vim.keymap.set("n", "e", "NvimTreeToggle", {desc = "Togle Nvim Tree"}) -- Telescope keymaps (loaded on demand) -vim.keymap.set('n', '', function() require('telescope.builtin').find_files() end, { desc = 'Telescope find files' }) +vim.keymap.set('n', '', function() require('telescope.builtin').find_files({ hidden = true }) end, { desc = 'Telescope find files' }) vim.keymap.set('n', 'fg', function() require('telescope.builtin').live_grep() end, { desc = 'Telescope live grep' }) vim.keymap.set('n', 'fb', function() require('telescope.builtin').buffers() end, { desc = 'Telescope buffers' }) vim.keymap.set('n', 'fh', function() require('telescope.builtin').help_tags() end, { desc = 'Telescope help tags' }) diff --git a/lua/plugins/barbar.lua b/lua/plugins/barbar.lua new file mode 100644 index 0000000..d08d857 --- /dev/null +++ b/lua/plugins/barbar.lua @@ -0,0 +1,15 @@ +return { + {'romgrk/barbar.nvim', + dependencies = { + 'lewis6991/gitsigns.nvim', -- OPTIONAL: for git status + 'nvim-tree/nvim-web-devicons', -- OPTIONAL: for file icons + }, + init = function() vim.g.barbar_auto_setup = false end, + opts = { + -- lazy.nvim will automatically call setup for you. put your options here, anything missing will use the default: + -- animation = true, + -- insert_at_start = true, + -- …etc. + }, + version = '^1.0.0', -- optional: only update when a new 1.x version is released + }} diff --git a/lua/plugins/completion.lua b/lua/plugins/completion.lua new file mode 100644 index 0000000..ee5b022 --- /dev/null +++ b/lua/plugins/completion.lua @@ -0,0 +1,65 @@ +return { + { + "hrsh7th/nvim-cmp", + event = "InsertEnter", + dependencies = { + "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-buffer", + "hrsh7th/cmp-path", + "L3MON4D3/LuaSnip", + "saadparwaiz1/cmp_luasnip", + "rafamadriz/friendly-snippets", + }, + config = function() + local cmp = require("cmp") + local luasnip = require("luasnip") + + require("luasnip.loaders.from_vscode").lazy_load() + + 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.select_next_item({ behavior = cmp.SelectBehavior.Insert }), + [""] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }), + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.abort(), + [""] = cmp.mapping.confirm({ select = true }), -- Confirm suggestion + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_locally_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.locally_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" }, + }), + }) + end, + }, +} diff --git a/lua/plugins/lsp.lua b/lua/plugins/lsp.lua new file mode 100644 index 0000000..9c97c40 --- /dev/null +++ b/lua/plugins/lsp.lua @@ -0,0 +1,127 @@ +return { + -- Mason for managing external tooling (LSPs, linters, formatters) + { + "williamboman/mason.nvim", + build = ":MasonUpdate", + config = function() + require("mason").setup({ + ui = { + border = "rounded", + icons = { + package_installed = "✓", + package_pending = "➜", + package_uninstalled = "✗", + }, + }, + }) + end, + }, + + -- Bridge between mason and lspconfig + { + "williamboman/mason-lspconfig.nvim", + dependencies = { + "williamboman/mason.nvim", + }, + opts = { + ensure_installed = { + "pyright", + "ruff", + }, + automatic_installation = true, + }, + }, + + -- LSP Config + { + "neovim/nvim-lspconfig", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { + "williamboman/mason.nvim", + "williamboman/mason-lspconfig.nvim", + "hrsh7th/cmp-nvim-lsp", + }, + config = function() + local cmp_lsp = require("cmp_nvim_lsp") + + -- Capabilities for auto-completion + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities = vim.tbl_deep_extend("force", capabilities, cmp_lsp.default_capabilities()) + + -- Diagnostic customization + vim.diagnostic.config({ + virtual_text = true, + signs = true, + update_in_insert = false, + underline = true, + severity_sort = true, + float = { + focusable = false, + style = "minimal", + border = "rounded", + source = "always", + header = "", + prefix = "", + }, + }) + + -- Keybindings and setup for buffers with an active LSP client + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(args) + local bufnr = args.buf + local client = vim.lsp.get_client_by_id(args.data.client_id) + + -- Configure specific client overrides + if client and client.name == "ruff" then + -- Disable hover in favor of Pyright hover to avoid duplicate boxes + client.server_capabilities.hoverProvider = false + end + + -- LSP Keymaps + vim.keymap.set("n", "gd", function() vim.lsp.buf.definition() end, { buffer = bufnr, desc = "Go to definition" }) + vim.keymap.set("n", "K", function() vim.lsp.buf.hover() end, { buffer = bufnr, desc = "LSP Hover info" }) + vim.keymap.set("n", "vws", function() vim.lsp.buf.workspace_symbol() end, { buffer = bufnr, desc = "Workspace symbol" }) + vim.keymap.set("n", "vd", function() vim.diagnostic.open_float() end, { buffer = bufnr, desc = "Open diagnostics float" }) + vim.keymap.set("n", "[d", function() vim.diagnostic.goto_next() end, { buffer = bufnr, desc = "Next diagnostic" }) + vim.keymap.set("n", "]d", function() vim.diagnostic.goto_prev() end, { buffer = bufnr, desc = "Previous diagnostic" }) + vim.keymap.set("n", "vca", function() vim.lsp.buf.code_action() end, { buffer = bufnr, desc = "Code action" }) + vim.keymap.set("n", "vrr", function() vim.lsp.buf.references() end, { buffer = bufnr, desc = "References" }) + vim.keymap.set("n", "vrn", function() vim.lsp.buf.rename() end, { buffer = bufnr, desc = "Rename symbol" }) + vim.keymap.set("i", "", function() vim.lsp.buf.signature_help() end, { buffer = bufnr, desc = "Signature help" }) + end, + }) + + -- Configure Pyright (Python LSP) using native Neovim 0.11+ API + vim.lsp.config("pyright", { + capabilities = capabilities, + settings = { + python = { + analysis = { + autoSearchPaths = true, + useLibraryCodeForTypes = true, + diagnosticMode = "workspace", + }, + }, + }, + }) + vim.lsp.enable("pyright") + + -- Configure Ruff (Python Linter/Formatter LSP) using native Neovim 0.11+ API + vim.lsp.config("ruff", { + capabilities = capabilities, + }) + vim.lsp.enable("ruff") + + -- Auto-format on save for Python using ruff + vim.api.nvim_create_autocmd("BufWritePre", { + pattern = "*.py", + callback = function(args) + local clients = vim.lsp.get_clients({ bufnr = args.buf, name = "ruff" }) + if #clients > 0 then + vim.lsp.buf.format({ bufnr = args.buf, id = clients[1].id, async = false }) + end + end, + }) + end, + }, +} diff --git a/lua/plugins/markdown-render.lua b/lua/plugins/markdown-render.lua new file mode 100644 index 0000000..a516a41 --- /dev/null +++ b/lua/plugins/markdown-render.lua @@ -0,0 +1,9 @@ +return { + 'MeanderingProgrammer/render-markdown.nvim', + dependencies = { 'nvim-treesitter/nvim-treesitter', 'nvim-mini/mini.nvim' }, -- if you use the mini.nvim suite + -- dependencies = { 'nvim-treesitter/nvim-treesitter', 'nvim-mini/mini.icons' }, -- if you use standalone mini plugins + -- dependencies = { 'nvim-treesitter/nvim-treesitter', 'nvim-tree/nvim-web-devicons' }, -- if you prefer nvim-web-devicons + ---@module 'render-markdown' + ---@type render.md.UserConfig + opts = {}, +} diff --git a/lua/plugins/nvim-tree.lua b/lua/plugins/nvim-tree.lua index bd0d403..ec5ee27 100644 --- a/lua/plugins/nvim-tree.lua +++ b/lua/plugins/nvim-tree.lua @@ -8,6 +8,9 @@ return { config = function() -- vim.cmd([[hi NvimTreeNormal guibg=NONE ctermbd=NONE]]) require("nvim-tree").setup { + git = { + ignore = false, + }, filters= { dotfiles = false, }, diff --git a/lua/plugins/telescope.lua b/lua/plugins/telescope.lua index fef8e18..2b4256a 100644 --- a/lua/plugins/telescope.lua +++ b/lua/plugins/telescope.lua @@ -4,5 +4,26 @@ return { 'nvim-lua/plenary.nvim', -- optional but recommended { 'nvim-telescope/telescope-fzf-native.nvim', build = 'make' }, - } + }, + config = function() + require('telescope').setup({ + defaults = { + vimgrep_arguments = { + "rg", + "--color=never", + "--no-heading", + "--with-filename", + "--line-number", + "--column", + "--smart-case", + "--no-ignore", + }, + }, + pickers = { + find_files = { + no_ignore = true, + }, + }, + }) + end }