diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9bbbeea --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.luarc.json diff --git a/init.lua b/init.lua index b65b2ab..192a969 100644 --- a/init.lua +++ b/init.lua @@ -129,10 +129,10 @@ vim.keymap.set("n", "Q", "qa!", { silent = true, desc = "[Q]uit -- Global Yank/Paste vim.keymap.set( - { "n", "v" }, - "y", - '"*y :let @+=@*', - { noremap = true, silent = true, desc = "Global [Y]ank" } + { "n", "v" }, + "y", + '"*y :let @+=@*', + { noremap = true, silent = true, desc = "Global [Y]ank" } ) vim.keymap.set({ "n", "v" }, "p", '"+p', { noremap = true, silent = true, desc = "Global [P]aste" }) @@ -149,9 +149,9 @@ vim.api.nvim_create_autocmd('filetype', { desc = 'Better mappings for netrw', callback = function() -- edit new file - vim.keymap.set("n", "n", "%", {remap = true, buffer = true}) + vim.keymap.set("n", "n", "%", { remap = true, buffer = true }) -- rename file - vim.keymap.set("n", "r", "R", {remap = true, buffer = true}) + vim.keymap.set("n", "r", "R", { remap = true, buffer = true }) end }) @@ -161,11 +161,11 @@ vim.api.nvim_create_autocmd('filetype', { -- See `:help vim.highlight.on_yank()` local highlight_group = vim.api.nvim_create_augroup("YankHighlight", { clear = true }) vim.api.nvim_create_autocmd("TextYankPost", { - callback = function() - vim.highlight.on_yank() - end, - group = highlight_group, - pattern = "*", + callback = function() + vim.highlight.on_yank() + end, + group = highlight_group, + pattern = "*", }) ------------------------------------------------------------------------------- @@ -174,9 +174,9 @@ vim.api.nvim_create_autocmd("TextYankPost", { -- See `:help restore-cursor` local restore_group = vim.api.nvim_create_augroup("RestoreGroup", { clear = true }) vim.api.nvim_create_autocmd("BufRead", { - command = [[call setpos(".", getpos("'\""))]], - group = restore_group, - pattern = "*", + command = [[call setpos(".", getpos("'\""))]], + group = restore_group, + pattern = "*", }) ------------------------------------------------------------------------------- @@ -184,14 +184,14 @@ vim.api.nvim_create_autocmd("BufRead", { ------------------------------------------------------------------------------- local lazypath = vim.fn.stdpath("data") .. "/lazy2/lazy.nvim" if not vim.loop.fs_stat(lazypath) then - vim.fn.system({ - "git", - "clone", - "--filter=blob:none", - "https://github.com/folke/lazy.nvim.git", - "--branch=stable", -- latest stable release - lazypath, - }) + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", -- latest stable release + lazypath, + }) end vim.opt.rtp:prepend(lazypath) @@ -199,595 +199,623 @@ vim.opt.rtp:prepend(lazypath) -- Plugins ------------------------------------------------------------------------------- require("lazy").setup({ - { - "folke/tokyonight.nvim", -- Set colorscheme to Gruvbox Theme - lazy = false, -- make sure we load this during startup if it is your main colorscheme - priority = 1000, -- make sure to load this before all - config = function() - vim.o.termguicolors = true - vim.o.background = "dark" - vim.cmd.colorscheme("tokyonight") - end, + { + "folke/tokyonight.nvim", -- Set colorscheme to Gruvbox Theme + lazy = false, -- make sure we load this during startup if it is your main colorscheme + priority = 1000, -- make sure to load this before all + config = function() + vim.o.termguicolors = true + vim.o.background = "dark" + vim.cmd.colorscheme("tokyonight") + end, keys = { - { "L", "Lazy", desc = "[L]azy" }, - { "L", "Lazy", desc = "[L]azy" }, + { "l", "Lazy", desc = "[L]azy" }, } - }, - { - "nvim-lualine/lualine.nvim", -- Fancier statusline - event = "VeryLazy", - dependencies = { "folke/tokyonight.nvim" }, - config = function() - require("lualine").setup({ - options = { - icons_enabled = false, - theme = "tokyonight", - component_separators = "|", - section_separators = "", - }, - }) - end, - }, - { - "nvim-telescope/telescope.nvim", -- Telescope - branch = "0.1.x", - dependencies = "nvim-lua/plenary.nvim", - keys = { - { "?", "Telescope oldfiles", desc = "[?] Find recently opened files" }, - { "", "Telescope buffers", desc = "[ ] Find existing buffers" }, - { - "/", - "Telescope current_buffer_fuzzy_find", - desc = "[/] Fuzzily search in current buffer]", - }, - - { "sf", "Telescope find_files", desc = "[S]earch [F]iles" }, - { "sh", "Telescope help_tags", desc = "[S]earch [H]elp" }, - { "sw", "Telescope grep_string", desc = "[S]earch current [W]ord" }, - { "sg", "Telescope live_grep", desc = "[S]earch by [G]rep" }, - { "sd", "Telescope diagnostics", desc = "[S]earch [D]iagnostics" }, - }, - config = function() - -- See `:help telescope` and `:help telescope.setup()` - require("telescope").setup({ - defaults = { - mappings = { - i = { - [""] = false, - [""] = false, - [""] = "move_selection_next", - [""] = "move_selection_previous", - [""] = function(...) - return require("telescope.actions").cycle_history_next(...) - end, - [""] = function(...) - return require("telescope.actions").cycle_history_prev(...) - end, - [""] = function(...) - return require("telescope.actions").preview_scrolling_down(...) - end, - [""] = function(...) - return require("telescope.actions").preview_scrolling_up(...) - end, - }, - n = { - ["q"] = function(...) - return require("telescope.actions").close(...) - end, - }, - }, - }, - }) - end, - }, - { - -- LSP Configuration & Plugins - "neovim/nvim-lspconfig", - event = { "BufReadPre", "BufNewFile" }, - dependencies = { - "hrsh7th/cmp-nvim-lsp", -- LSP source for nvim-cmp - "hrsh7th/nvim-cmp", -- Autocompletion plugin - -- "hrsh7th/cmp-buffer", -- nvim-cmp source for buffer words - "hrsh7th/cmp-path", -- nvim-cmp source for filesystem paths - "hrsh7th/cmp-nvim-lua", -- nvim-cmp source for neovim Lua API - "saadparwaiz1/cmp_luasnip", -- Snippets source for nvim-cmp - "L3MON4D3/LuaSnip", -- Snippets plugin - -- Copilot - { - "zbirenbaum/copilot-cmp", - dependencies = { - "zbirenbaum/copilot.lua", - cmd = "Copilot", - build = ":Copilot auth", - opts = { - suggestion = { enabled = false }, - panel = { enabled = false }, - filetypes = { - markdown = true, - help = true, - }, - }, - }, - }, - }, - config = function() - local lsp = require("lspconfig") - -- Global mappings. - -- See `:help vim.diagnostic.*` for documentation on any of the below functions - vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, { desc = "[D]iagnostics: Goto Previous" }) - vim.keymap.set("n", "]d", vim.diagnostic.goto_next, { desc = "[D]iagnostics: Goto Next" }) - vim.keymap.set("n", "e", vim.diagnostic.open_float, { desc = "[D]iagnostics: Op[e]n Float" }) - vim.keymap.set("n", "k", vim.diagnostic.setloclist, { desc = "[D]iagnostics: Set" }) - local on_attach = function(_, bufnr) - -- Buffer local mappings. - -- See `:help vim.lsp.*` for documentation on any of the below functions - -- Code Actions - vim.keymap.set("n", "rn", vim.lsp.buf.rename, { buffer = bufnr, desc = "[R]e[n]ame" }) - vim.keymap.set( - "n", - "ca", - vim.lsp.buf.code_action, - { buffer = bufnr, desc = "[C]ode [A]ction" } - ) - -- Definitions - vim.keymap.set("n", "gd", vim.lsp.buf.definition, { buffer = bufnr, desc = "[G]oto [D]efinition" }) - vim.keymap.set( - "n", - "gi", - vim.lsp.buf.implementation, - { buffer = bufnr, desc = "[G]oto [I]mplementation" } - ) - vim.keymap.set("n", "gr", require("telescope.builtin").lsp_references) - vim.keymap.set( - "n", - "ds", - require("telescope.builtin").lsp_document_symbols, - { buffer = bufnr, desc = "[D]ocument [S]ymbols" } - ) - vim.keymap.set( - "n", - "ws", - require("telescope.builtin").lsp_dynamic_workspace_symbols, - { buffer = bufnr, desc = "[W]orkspace [S]ymbols" } - ) - -- See `:help K` for why this keymap - vim.keymap.set("n", "K", vim.lsp.buf.hover, { buffer = bufnr, desc = "Hover Documentation" }) - vim.keymap.set( - "n", - "", - vim.lsp.buf.signature_help, - { buffer = bufnr, desc = "Signature Documentation" } - ) - -- Lesser used LSP functionality - vim.keymap.set( - "n", - "gD", - vim.lsp.buf.declaration, - { buffer = bufnr, desc = "[G]oto [D]eclaration" } - ) - vim.keymap.set( - "n", - "D", - vim.lsp.buf.type_definition, - { buffer = bufnr, desc = "Type [D]efinition" } - ) - vim.keymap.set( - "n", - "wa", - vim.lsp.buf.add_workspace_folder, - { buffer = bufnr, desc = "[W]orkspace [A]dd Folder" } - ) - vim.keymap.set( - "n", - "wr", - vim.lsp.buf.remove_workspace_folder, - { buffer = bufnr, desc = "[W]orkspace [R]emove Folder" } - ) - vim.keymap.set("n", "wl", function() - print(vim.inspect(vim.lsp.buf.list_workspace_folders())) - end, { buffer = bufnr, desc = "[W]orkspace [L]ist Folders" }) - -- Format - vim.keymap.set("n", "f", - vim.lsp.buf.format({ async = true }), - { buffer = bufnr, desc = "[F]ormat current buffer with LSP" }) - -- Autoformat on save - vim.api.nvim_create_autocmd("BufWritePre", { - buffer = bufnr, - callback = function() - vim.lsp.buf.format({ async = true }) - end, - }) - end - -- Enable some language servers with the additional completion capabilities offered by nvim-cmp - local servers = { - pyright = {}, -- requires pyright to be installed - tsserver = {}, -- requires typescript-language-server to be installed - bashls = {}, -- requires bash-language-server to be installed - html = {}, -- requires vscode-langservers-extracted to be installed - css = {}, -- requires vscode-langservers-extracted to be installed - jsonls = {}, -- requires vscode-langservers-extracted to be installed - eslint = {}, -- requires vscode-langservers-extracted to be installed - lua_ls = { -- requires lua-language-server to be installed - Lua = { - workspace = { checkThirdParty = false }, - telemetry = { enable = false }, - }, - }, - rust_analyzer = { -- requires rust-analyzer to be installed - settings = { - ["rust-analyzer"] = { - checkOnSave = { - allFeatures = true, - command = "clippy", - extraArgs = { "--no-deps" }, - }, - }, - }, - }, - } - -- nvim-cmp supports additional completion capabilities, so broadcast that to servers - local capabilities = vim.lsp.protocol.make_client_capabilities() - capabilities = require("cmp_nvim_lsp").default_capabilities(capabilities) - for _, l in ipairs(servers) do - lsp[l].setup({ - capabilities = capabilities, - on_attach = on_attach, - settings = servers[l].settings or {}, - filetypes = (servers[l] or {}).filetypes, - }) - end - - -- nvim-cmp setup - local cmp = require("cmp") - -- luasnip setup - local luasnip = require("luasnip") - require("luasnip.loaders.from_vscode").lazy_load() - luasnip.config.setup({}) - -- tab fix for copilot - local has_words_before = function() - if vim.api.nvim_buf_get_option(0, "buftype") == "prompt" then - return false - end - local line, col = unpack(vim.api.nvim_win_get_cursor(0)) - return col ~= 0 - and vim.api.nvim_buf_get_text(0, line - 1, 0, line - 1, col, {})[1]:match("^%s*$") == nil - end - cmp.setup({ - completion = { - completeopt = "menu,menuone,noinsert", - }, - snippet = { - expand = function(args) - luasnip.lsp_expand(args.body) - end, - }, - mapping = cmp.mapping.preset.insert({ - [""] = cmp.mapping.scroll_docs(-4), -- Up - [""] = cmp.mapping.scroll_docs(4), -- Down - -- C-b (back) C-f (forward) for snippet placeholder navigation. - [""] = cmp.mapping.complete(), - [""] = cmp.mapping.confirm({ - behavior = cmp.ConfirmBehavior.Replace, - select = true, - }), - [""] = cmp.mapping.abort(), - [""] = vim.schedule_wrap(function(fallback) - if cmp.visible() and has_words_before() then - cmp.select_next_item({ behavior = cmp.SelectBehavior.Select }) - 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 = { - { name = "copilot", group_index = 2 }, - { name = "nvim_lsp", group_index = 2 }, - { name = "luasnip", group_index = 2 }, - -- { name = "buffer", group_index = 2 }, - { name = "path", group_index = 2 }, - }, - sorting = { -- copilot_cmp suggestion - priority_weight = 2, - comparators = { - require("copilot_cmp.comparators").prioritize, - - -- Below is the default comparator list and order for nvim-cmp - cmp.config.compare.offset, - -- cmp.config.compare.scopes, --this is commented in nvim-cmp too - cmp.config.compare.exact, - cmp.config.compare.score, - cmp.config.compare.recently_used, - cmp.config.compare.locality, - cmp.config.compare.kind, - cmp.config.compare.sort_text, - cmp.config.compare.length, - cmp.config.compare.order, - }, - }, - }) - end, - }, - -- LSP Formatters and Linters - -- null-ls is archived - -- { - -- "mhartington/formatter.nvim", - -- event = { "BufReadPre", "BufNewFile" }, - -- config = function() - -- local formatter = require("formatter") - -- formatter.setup({ - -- filetype = { - -- lua = { - -- require("formatter.filetypes.lua").stylua, -- requires stylua to be installed - -- }, - -- rust = { - -- require("formatter.filetypes.rust").rustfmt, -- requires rustfmt to be installed - -- }, - -- python = { - -- require("formatter.filetypes.python").black, -- requires black to be installed - -- }, - -- sh = { - -- require("formatter.filetypes.sh").shfmt, -- requires shfmt to be installed - -- }, - -- fish = { - -- require("formatter.filetypes.fish").fishindent, -- requires fish to be installed - -- }, - -- html = { - -- require("formatter.filetypes.html").prettierd, -- requires prettierd to be installed - -- }, - -- css = { - -- require("formatter.filetypes.css").prettierd, -- requires prettierd to be installed - -- }, - -- markdown = { - -- require("formatter.filetypes.markdown").prettierd, -- requires prettierd to be installed - -- }, - -- }, - -- }) - -- end, - -- }, - -- { - -- "mfussenegger/nvim-lint", - -- config = function() - -- local lint = require("lint") - -- lint.linters_by_ft = { - -- python = { "ruff" }, -- requires ruff to be installed - -- lua = { "luacheck" }, -- requires luacheck to be installed - -- sh = { "shellcheck" }, -- requires shellcheck to be installed - -- markdown = { "markdownlint" }, -- requires markdownlint to be installed - -- } - -- vim.api.nvim_create_autocmd({ "InsertLeave", "BufWritePost" }, { - -- callback = function() - -- lint.try_lint() - -- end, - -- }) - -- end, - -- }, - { - "nvim-treesitter/nvim-treesitter", - event = { "BufReadPost", "BufNewFile" }, - build = ":TSUpdate", - config = function() - require("nvim-treesitter.configs").setup({ - ensure_installed = { - "bash", - "c", - "css", - "cpp", - "html", - "javascript", - "jsdoc", - "json", - "lua", - "luadoc", - "luap", - "markdown", - "markdown_inline", - "python", - "query", - "regex", - "rust", - "tsx", - "typescript", - "toml", - "vim", - "vimdoc", - "yaml", - }, - auto_install = true, - highlight = { enable = true }, - indent = { enable = true, disable = { "python" } }, - incremental_selection = { - enable = true, - keymaps = { - init_selection = "", - node_incremental = "", - scope_incremental = "", - node_decremental = "", - }, - }, - textobjects = { - select = { - enable = true, - lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim - keymaps = { - -- You can use the capture groups defined in textobjects.scm - ["aa"] = "@parameter.outer", - ["ia"] = "@parameter.inner", - ["af"] = "@function.outer", - ["if"] = "@function.inner", - ["ac"] = "@class.outer", - ["ic"] = "@class.inner", - }, - }, - move = { - enable = true, - set_jumps = true, -- whether to set jumps in the jumplist - goto_next_start = { - ["]m"] = "@function.outer", - ["]]"] = "@class.outer", - }, - goto_next_end = { - ["]M"] = "@function.outer", - ["]["] = "@class.outer", - }, - goto_previous_start = { - ["[m"] = "@function.outer", - ["[["] = "@class.outer", - }, - goto_previous_end = { - ["[M"] = "@function.outer", - ["[]"] = "@class.outer", - }, - }, - swap = { - enable = true, - swap_next = { ["a"] = "@parameter.inner" }, - swap_previous = { ["A"] = "@parameter.inner" }, - }, - }, - extensions = { - fzf = { - fuzzy = true, -- false will only do exact matching - override_generic_sorter = true, -- override the generic sorter - override_file_sorter = true, -- override the file sorter - case_mode = "smart_case", -- or "ignore_case" or "respect_case" - -- the default case_mode is "smart_case" - }, - }, - }) - require("telescope").load_extension("fzf") - end, - }, - -- Fuzzy Finder Algorithm which requires local dependencies to be built. Only load if `make` is available - { - "nvim-telescope/telescope-fzf-native.nvim", - build = "make", - cond = vim.fn.executable("make") == 1, - dependencies = { "nvim-treesitter/nvim-treesitter" }, - config = function() - require("telescope").load_extension("fzf") - end, - }, - -- Undotree - { - "mbbill/undotree", - evenvt = "VeryLazy", - config = true, - keys = { { "u", "UndotreeToggle", desc = "[U]ndo Tree" } }, - }, - -- Git related plugins - { - "lewis6991/gitsigns.nvim", - event = { "BufReadPre", "BufNewFile" }, - config = function() - require("gitsigns").setup({ - signs = { - add = { text = "+" }, - change = { text = "~" }, - delete = { text = "_" }, - topdelete = { text = "‾" }, - changedelete = { text = "~" }, - }, - on_attach = function(bufnr) - local gs = package.loaded.gitsigns - -- Navigation - vim.keymap.set("n", "]h", function() - if vim.wo.diff then - return "]c" - end - vim.schedule(function() - gs.next_hunk() - end) - return "" - end, { expr = true, buffer = bufnr, desc = "Next Hunk" }) - vim.keymap.set("n", "[h", function() - if vim.wo.diff then - return "[c" - end - vim.schedule(function() - gs.prev_hunk() - end) - return "" - end, { expr = true, buffer = bufnr, desc = "Previous Hunk" }) - -- Actions - vim.keymap.set({ "n", "v" }, "hs", "Gitsigns stage_hunk", {buffer = bufnr, desc = "Hunk: [S]tage"}) - vim.keymap.set({ "n", "v" }, "hr", "Gitsigns reset_hunk", {buffer = bufnr, desc = "Hunk: [R]eset"}) - vim.keymap.set("n", "hS", gs.stage_buffer, {buffer = bufnr, desc = "Hunk: [S]tage File"}) - vim.keymap.set("n", "hu", gs.undo_stage_hunk, {buffer = bufnr, desc = "Hunk: [U]ndo"}) - vim.keymap.set("n", "hR", gs.reset_buffer, {buffer = bufnr, desc = "Hunk: [R]eset File"}) - vim.keymap.set("n", "hp", gs.preview_hunk, {buffer = bufnr, desc = "Hunk: [P]review"}) - vim.keymap.set("n", "hb", function() - gs.blame_line({ full = true }) - end, - {buffer = bufnr, desc = "Hunk: [B]lame line"}) - vim.keymap.set("n", "hB", gs.toggle_current_line_blame, {buffer = bufnr, desc = "Hunk: Toggle [B]lame Line"}) - vim.keymap.set("n", "hd", gs.diffthis, {buffer = bufnr, desc = "Hunk: [D]iff This"}) - vim.keymap.set("n", "hD", function() - gs.diffthis("~") - end, - {buffer = bufnr, desc = "Hunk: [D]iff This ~"}) - vim.keymap.set("n", "ht", gs.toggle_deleted, {buffer = bufnr, desc = "Hunk: [T]oggle Deleted"}) - -- Text object - vim.keymap.set({ "o", "x" }, "ih", "Gitsigns select_hunk", {buffer = bufnr, desc = "GitSigns Select Hunk"}) - end, - }) - end, - }, - { - "tpope/vim-fugitive", - event = "VeryLazy", - keys = { - { "gi", "Git", desc = "Fugitive - [Gi]t" }, - -- It allows me to easily set the branch I am pushing and any tracking - { "gt", "Git push -u origin ", desc = "Fugitive - [G]it Push [T]agging" }, - }, - }, - { - "tpope/vim-rhubarb", -- Fugitive-companion to interact with github - event = "VeryLazy", - }, - -- Miscellaneous - "tpope/vim-sleuth", -- Detect tabstop and shiftwidth automatically - { - "folke/which-key.nvim", -- popup with possible key bindings of the command you started typing - event = "VeryLazy", - opts = { - plugins = { spelling = true }, - defaults = { - mode = { "n", "v" }, - ["g"] = { name = "+goto" }, - ["]"] = { name = "+next" }, - ["["] = { name = "+prev" }, - ["c"] = { name = "+code" }, - ["g"] = { name = "+git" }, - ["h"] = { name = "+hunks" }, - ["s"] = { name = "+search" }, - }, - }, - config = function(_, opts) - local wk = require("which-key") - wk.setup(opts) - wk.register(opts.defaults) - end, - }, - { "numToStr/Comment.nvim", config = true, event = "VeryLazy" }, -- 'gc' to comment visual regions/lines - { "windwp/nvim-autopairs", config = true }, -- Autopair stuff like ({["' - { - "kylechui/nvim-surround", -- Surround selections - dependencies = { "nvim-treesitter/nvim-treesitter" }, - version = "*", - config = true, - }, + }, + { + "nvim-lualine/lualine.nvim", -- Fancier statusline + event = "VeryLazy", + dependencies = { "folke/tokyonight.nvim" }, + config = function() + require("lualine").setup({ + options = { + icons_enabled = false, + theme = "tokyonight", + component_separators = "|", + section_separators = "", + }, + }) + end, + }, + { + "nvim-telescope/telescope.nvim", -- Telescope + branch = "0.1.x", + dependencies = "nvim-lua/plenary.nvim", + keys = { + { "?", "Telescope oldfiles", desc = "[?] Find recently opened files" }, + { "", "Telescope buffers", desc = "[ ] Find existing buffers" }, + { + "/", + "Telescope current_buffer_fuzzy_find", + desc = "[/] Fuzzily search in current buffer]", + }, + + { "sf", "Telescope find_files", desc = "[F]iles" }, + { "sh", "Telescope help_tags", desc = "[H]elp" }, + { "sw", "Telescope grep_string", desc = "Current [W]ord" }, + { "sg", "Telescope live_grep", desc = "[G]rep" }, + { "sd", "Telescope diagnostics", desc = "[D]iagnostics" }, + }, + config = function() + -- See `:help telescope` and `:help telescope.setup()` + require("telescope").setup({ + defaults = { + mappings = { + i = { + [""] = false, + [""] = false, + [""] = "move_selection_next", + [""] = "move_selection_previous", + [""] = function(...) + return require("telescope.actions").cycle_history_next(...) + end, + [""] = function(...) + return require("telescope.actions").cycle_history_prev(...) + end, + [""] = function(...) + return require("telescope.actions").preview_scrolling_down(...) + end, + [""] = function(...) + return require("telescope.actions").preview_scrolling_up(...) + end, + }, + n = { + ["q"] = function(...) + return require("telescope.actions").close(...) + end, + }, + }, + }, + }) + end, + }, + { + -- LSP Configuration & Plugins + "neovim/nvim-lspconfig", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { + "hrsh7th/cmp-nvim-lsp", -- LSP source for nvim-cmp + "hrsh7th/nvim-cmp", -- Autocompletion plugin + "hrsh7th/cmp-buffer", -- nvim-cmp source for buffer words + "hrsh7th/cmp-path", -- nvim-cmp source for filesystem paths + "hrsh7th/cmp-nvim-lua", -- nvim-cmp source for neovim Lua API + "saadparwaiz1/cmp_luasnip", -- Snippets source for nvim-cmp + "L3MON4D3/LuaSnip", -- Snippets plugin + "folke/neodev.nvim", -- Neovim development Lua utils + -- Copilot + { + "zbirenbaum/copilot-cmp", + dependencies = { + "zbirenbaum/copilot.lua", + cmd = "Copilot", + build = ":Copilot auth", + opts = { + suggestion = { enabled = false }, + panel = { enabled = false }, + filetypes = { + markdown = true, + help = true, + }, + }, + }, + }, + }, + config = function() + -- IMPORTANT: make sure to setup neodev BEFORE lspconfig + require("neodev").setup() + local lsp = require("lspconfig") + -- Global mappings. + -- See `:help vim.diagnostic.*` for documentation on any of the below functions + vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, { desc = "[D]iagnostics: Goto Previous" }) + vim.keymap.set("n", "]d", vim.diagnostic.goto_next, { desc = "[D]iagnostics: Goto Next" }) + vim.keymap.set("n", "e", vim.diagnostic.open_float, { desc = "[D]iagnostics: Op[e]n Float" }) + vim.keymap.set("n", "k", vim.diagnostic.setloclist, { desc = "[D]iagnostics: Set" }) + -- Use LspAttach autocommand to only map the following keys + -- after the language server attaches to the current buffer + vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('UserLspConfig', {}), + callback = function(ev) + -- Enable completion triggered by + vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc' + -- Buffer local mappings. + -- See `:help vim.lsp.*` for documentation on any of the below functions + -- Code Actions + vim.keymap.set("n", "cr", vim.lsp.buf.rename, { desc = "[R]ename" }) + vim.keymap.set( + "n", + "ca", + vim.lsp.buf.code_action, + { desc = "Code [A]ction" } + ) + -- Definitions + vim.keymap.set("n", "gd", vim.lsp.buf.definition, { desc = "[G]oto [D]efinition" }) + vim.keymap.set( + "n", + "gi", + vim.lsp.buf.implementation, + { desc = "[G]oto [I]mplementation" } + ) + vim.keymap.set("n", "gr", require("telescope.builtin").lsp_references) + vim.keymap.set( + "n", + "sD", + require("telescope.builtin").lsp_document_symbols, + { desc = "[D]ocument [S]ymbols" } + ) + vim.keymap.set( + "n", + "ss", + require("telescope.builtin").lsp_dynamic_workspace_symbols, + { desc = "[S]ymbols" } + ) + -- See `:help K` for why this keymap + vim.keymap.set("n", "K", vim.lsp.buf.hover, { desc = "Hover Documentation" }) + vim.keymap.set( + "n", + "", + vim.lsp.buf.signature_help, + { desc = "Signature Documentation" } + ) + -- Lesser used LSP functionality + vim.keymap.set( + "n", + "gD", + vim.lsp.buf.declaration, + { desc = "[G]oto [D]eclaration" } + ) + vim.keymap.set( + "n", + "D", + vim.lsp.buf.type_definition, + { desc = "Type [D]efinition" } + ) + vim.keymap.set( + "n", + "cwa", + vim.lsp.buf.add_workspace_folder, + { desc = "[A]dd Folder" } + ) + vim.keymap.set( + "n", + "cwr", + vim.lsp.buf.remove_workspace_folder, + { desc = "[R]emove Folder" } + ) + vim.keymap.set("n", "cwl", function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, { desc = "[L]ist Folders" }) + -- Format + vim.keymap.set("n", "f", function() + vim.lsp.buf.format({ async = true }) + end, + { desc = "[F]ormat current buffer with LSP" }) + -- Autoformat on save + vim.api.nvim_create_autocmd("BufWritePre", { + callback = function() + vim.lsp.buf.format({ async = false }) + end, + }) + end, + }) + -- nvim-cmp supports additional completion capabilities, so broadcast that to servers + -- Add additional capabilities supported by nvim-cmp + local capabilities = require("cmp_nvim_lsp").default_capabilities() + -- nvim-cmp setup + local cmp = require("cmp") + -- luasnip setup + local luasnip = require("luasnip") + require("luasnip.loaders.from_vscode").lazy_load() + luasnip.config.setup({}) + -- tab fix for copilot + local has_words_before = function() + if vim.api.nvim_buf_get_option(0, "buftype") == "prompt" then + return false + end + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 + and vim.api.nvim_buf_get_text(0, line - 1, 0, line - 1, col, {})[1]:match("^%s*$") == nil + end + cmp.setup({ + completion = { + completeopt = "menu,menuone,noinsert", + }, + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + enabled = function() + -- disable completion in comments + local context = require 'cmp.config.context' + -- keep command mode completion enabled when cursor is in a comment + if vim.api.nvim_get_mode().mode == 'c' then + return true + else + return not context.in_treesitter_capture("comment") + and not context.in_syntax_group("Comment") + end + end, + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.scroll_docs(-4), -- Up + [""] = cmp.mapping.scroll_docs(4), -- Down + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.confirm({ + behavior = cmp.ConfirmBehavior.Replace, + select = true, + }), + [""] = cmp.mapping.abort(), + [""] = vim.schedule_wrap(function(fallback) + if cmp.visible() and has_words_before() then + cmp.select_next_item({ behavior = cmp.SelectBehavior.Select }) + 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({ behavior = cmp.SelectBehavior.Select }) + elseif luasnip.jumpable() then + luasnip.expand_or_jump() + else + fallback() + end + end, { 'i', 's' }), + }), + sources = { + { name = "copilot", group_index = 2 }, + { name = "nvim_lsp", group_index = 2 }, + { name = "luasnip", group_index = 2 }, + -- { name = "buffer", group_index = 2 }, + { name = "path", group_index = 2 }, + }, + sorting = { -- copilot_cmp suggestion + priority_weight = 2, + comparators = { + require("copilot_cmp.comparators").prioritize, + + -- Below is the default comparator list and order for nvim-cmp + cmp.config.compare.offset, + -- cmp.config.compare.scopes, --this is commented in nvim-cmp too + cmp.config.compare.exact, + cmp.config.compare.score, + cmp.config.compare.recently_used, + cmp.config.compare.locality, + cmp.config.compare.kind, + cmp.config.compare.sort_text, + cmp.config.compare.length, + cmp.config.compare.order, + }, + }, + }) + -- If you want insert `(` after select function or method item + local cmp_autopairs = require('nvim-autopairs.completion.cmp') + cmp.event:on( + 'confirm_done', + cmp_autopairs.on_confirm_done() + ) + -- Enable some language servers with the additional completion capabilities offered by nvim-cmp + lsp.pyright.setup({ capabilities = capabilities }) -- requires pyright to be installed + lsp.tsserver.setup({ capabilities = capabilities }) -- requires typescript-language-server to be installed + lsp.bashls.setup({ capabilities = capabilities }) -- requires bash-language-server to be installed + lsp.html.setup({ capabilities = capabilities }) -- requires vscode-langservers-extracted to be installed + lsp.cssls.setup({ capabilities = capabilities }) -- requires vscode-langservers-extracted to be installed + lsp.jsonls.setup({ capabilities = capabilities }) -- requires vscode-langservers-extracted to be installed + lsp.eslint.setup({ capabilities = capabilities }) -- requires vscode-langservers-extracted to be installed + lsp.lua_ls.setup({ -- requires lua-language-server to be installed + capabilities = capabilities, + settings = { + Lua = { + telemetry = { enable = false }, + }, + }, + }) + lsp.rust_analyzer.setup({ -- requires rust-analyzer to be installed + capabilities = capabilities, + settings = { + ["rust-analyzer"] = { + cargo = { + allFeatures = true, + loadOutDirsFromCheck = true, + runBuildScripts = true, + }, + -- Add clippy lints for Rust + checkOnSave = { + allFeatures = true, + command = "clippy", + extraArgs = { "--no-deps" }, + }, + }, + }, + }) + end, + }, + -- LSP Formatters and Linters + -- null-ls is archived + -- { + -- "mhartington/formatter.nvim", + -- event = { "BufReadPre", "BufNewFile" }, + -- config = function() + -- local formatter = require("formatter") + -- formatter.setup({ + -- filetype = { + -- lua = { + -- require("formatter.filetypes.lua").stylua, -- requires stylua to be installed + -- }, + -- rust = { + -- require("formatter.filetypes.rust").rustfmt, -- requires rustfmt to be installed + -- }, + -- python = { + -- require("formatter.filetypes.python").black, -- requires black to be installed + -- }, + -- sh = { + -- require("formatter.filetypes.sh").shfmt, -- requires shfmt to be installed + -- }, + -- fish = { + -- require("formatter.filetypes.fish").fishindent, -- requires fish to be installed + -- }, + -- html = { + -- require("formatter.filetypes.html").prettierd, -- requires prettierd to be installed + -- }, + -- css = { + -- require("formatter.filetypes.css").prettierd, -- requires prettierd to be installed + -- }, + -- markdown = { + -- require("formatter.filetypes.markdown").prettierd, -- requires prettierd to be installed + -- }, + -- }, + -- }) + -- end, + -- }, + -- { + -- "mfussenegger/nvim-lint", + -- config = function() + -- local lint = require("lint") + -- lint.linters_by_ft = { + -- python = { "ruff" }, -- requires ruff to be installed + -- lua = { "luacheck" }, -- requires luacheck to be installed + -- sh = { "shellcheck" }, -- requires shellcheck to be installed + -- markdown = { "markdownlint" }, -- requires markdownlint to be installed + -- } + -- vim.api.nvim_create_autocmd({ "InsertLeave", "BufWritePost" }, { + -- callback = function() + -- lint.try_lint() + -- end, + -- }) + -- end, + -- }, + { + "nvim-treesitter/nvim-treesitter", + event = { "BufReadPost", "BufNewFile" }, + build = ":TSUpdate", + config = function() + require("nvim-treesitter.configs").setup({ + ensure_installed = { + "bash", + "c", + "css", + "cpp", + "html", + "javascript", + "jsdoc", + "json", + "lua", + "luadoc", + "luap", + "markdown", + "markdown_inline", + "python", + "query", + "regex", + "rust", + "tsx", + "typescript", + "toml", + "vim", + "vimdoc", + "yaml", + }, + auto_install = true, + highlight = { enable = true }, + indent = { enable = true, disable = { "python" } }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = "", + node_incremental = "", + scope_incremental = "", + node_decremental = "", + }, + }, + textobjects = { + select = { + enable = true, + lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim + keymaps = { + -- You can use the capture groups defined in textobjects.scm + ["aa"] = "@parameter.outer", + ["ia"] = "@parameter.inner", + ["af"] = "@function.outer", + ["if"] = "@function.inner", + ["ac"] = "@class.outer", + ["ic"] = "@class.inner", + }, + }, + move = { + enable = true, + set_jumps = true, -- whether to set jumps in the jumplist + goto_next_start = { + ["]m"] = "@function.outer", + ["]]"] = "@class.outer", + }, + goto_next_end = { + ["]M"] = "@function.outer", + ["]["] = "@class.outer", + }, + goto_previous_start = { + ["[m"] = "@function.outer", + ["[["] = "@class.outer", + }, + goto_previous_end = { + ["[M"] = "@function.outer", + ["[]"] = "@class.outer", + }, + }, + swap = { + enable = true, + swap_next = { ["a"] = "@parameter.inner" }, + swap_previous = { ["A"] = "@parameter.inner" }, + }, + }, + extensions = { + fzf = { + fuzzy = true, -- false will only do exact matching + override_generic_sorter = true, -- override the generic sorter + override_file_sorter = true, -- override the file sorter + case_mode = "smart_case", -- or "ignore_case" or "respect_case" + -- the default case_mode is "smart_case" + }, + }, + }) + require("telescope").load_extension("fzf") + end, + }, + -- Fuzzy Finder Algorithm which requires local dependencies to be built. Only load if `make` is available + { + "nvim-telescope/telescope-fzf-native.nvim", + build = "make", + cond = vim.fn.executable("make") == 1, + dependencies = { "nvim-treesitter/nvim-treesitter" }, + config = function() + require("telescope").load_extension("fzf") + end, + }, + -- Undotree + { + "mbbill/undotree", + evenvt = "VeryLazy", + config = true, + keys = { { "u", "UndotreeToggle", desc = "[U]ndo Tree" } }, + }, + -- Git related plugins + { + "lewis6991/gitsigns.nvim", + event = { "BufReadPre", "BufNewFile" }, + config = function() + require("gitsigns").setup({ + signs = { + add = { text = "+" }, + change = { text = "~" }, + delete = { text = "_" }, + topdelete = { text = "‾" }, + changedelete = { text = "~" }, + }, + on_attach = function(bufnr) + local gs = package.loaded.gitsigns + -- Navigation + vim.keymap.set("n", "]h", function() + if vim.wo.diff then + return "]c" + end + vim.schedule(function() + gs.next_hunk() + end) + return "" + end, { expr = true, buffer = bufnr, desc = "Next Hunk" }) + vim.keymap.set("n", "[h", function() + if vim.wo.diff then + return "[c" + end + vim.schedule(function() + gs.prev_hunk() + end) + return "" + end, { expr = true, buffer = bufnr, desc = "Previous Hunk" }) + -- Actions + vim.keymap.set({ "n", "v" }, "hs", "Gitsigns stage_hunk", + { buffer = bufnr, desc = "[S]tage" }) + vim.keymap.set({ "n", "v" }, "hr", "Gitsigns reset_hunk", + { buffer = bufnr, desc = "[R]eset" }) + vim.keymap.set("n", "hS", gs.stage_buffer, { buffer = bufnr, desc = "[S]tage File" }) + vim.keymap.set("n", "hu", gs.undo_stage_hunk, { buffer = bufnr, desc = "[U]ndo" }) + vim.keymap.set("n", "hR", gs.reset_buffer, { buffer = bufnr, desc = "[R]eset File" }) + vim.keymap.set("n", "hp", gs.preview_hunk, { buffer = bufnr, desc = "[P]review" }) + vim.keymap.set("n", "hb", function() + gs.blame_line({ full = true }) + end, + { buffer = bufnr, desc = "[B]lame line" }) + vim.keymap.set("n", "hB", gs.toggle_current_line_blame, + { buffer = bufnr, desc = "Toggle [B]lame Line" }) + vim.keymap.set("n", "hd", gs.diffthis, { buffer = bufnr, desc = "[D]iff This" }) + vim.keymap.set("n", "hD", function() + gs.diffthis("~") + end, + { buffer = bufnr, desc = "[D]iff This ~" }) + vim.keymap.set("n", "ht", gs.toggle_deleted, { buffer = bufnr, desc = "[T]oggle Deleted" }) + -- Text object + vim.keymap.set({ "o", "x" }, "ih", "Gitsigns select_hunk", + { buffer = bufnr, desc = "GitSigns Select Hunk" }) + end, + }) + end, + }, + { + "tpope/vim-fugitive", + event = "VeryLazy", + keys = { + { "gi", "Git", desc = "[Gi]t" }, + -- It allows me to easily set the branch I am pushing and any tracking + { "gt", "Git push -u origin ", desc = "[G]it Push [T]agging" }, + }, + }, + { + "tpope/vim-rhubarb", -- Fugitive-companion to interact with github + event = "VeryLazy", + }, + -- Miscellaneous + "tpope/vim-sleuth", -- Detect tabstop and shiftwidth automatically + { + "folke/which-key.nvim", -- popup with possible key bindings of the command you started typing + event = "VeryLazy", + opts = { + plugins = { spelling = true }, + defaults = { + mode = { "n", "v" }, + ["g"] = { name = "+goto" }, + ["]"] = { name = "+next" }, + ["["] = { name = "+prev" }, + ["c"] = { name = "+code" }, + ["cw"] = { name = "+workspace" }, + ["g"] = { name = "+git" }, + ["h"] = { name = "+hunks" }, + ["s"] = { name = "+search" }, + }, + }, + config = function(_, opts) + local wk = require("which-key") + wk.setup(opts) + wk.register(opts.defaults) + end, + }, + { "numToStr/Comment.nvim", config = true, event = "VeryLazy" }, -- 'gc' to comment visual regions/lines + { "windwp/nvim-autopairs", config = true }, -- Autopair stuff like ({["' + { + "kylechui/nvim-surround", -- Surround selections + dependencies = { "nvim-treesitter/nvim-treesitter" }, + version = "*", + config = true, + }, }) -- The line beneath this is called `modeline`. See `:help modeline`