-- Install packer local install_path = vim.fn.stdpath 'data' .. '/site/pack/packer/start/packer.nvim' local is_bootstrap = false if vim.fn.empty(vim.fn.glob(install_path)) > 0 then is_bootstrap = true vim.fn.system { 'git', 'clone', '--depth', '1', 'https://github.com/wbthomason/packer.nvim', install_path } vim.cmd [[packadd packer.nvim]] end require('packer').startup(function(use) -- Package manager use 'wbthomason/packer.nvim' use { -- LSP Configuration & Plugins 'neovim/nvim-lspconfig', requires = { -- Automatically install LSPs to stdpath for neovim 'williamboman/mason.nvim', 'williamboman/mason-lspconfig.nvim', -- Useful status updates for LSP 'j-hui/fidget.nvim', }, } use { -- Autocompletion 'hrsh7th/nvim-cmp', requires = { 'hrsh7th/cmp-nvim-lsp', 'L3MON4D3/LuaSnip', 'saadparwaiz1/cmp_luasnip' }, } use { -- Highlight, edit, and navigate code 'nvim-treesitter/nvim-treesitter', run = function() pcall(require('nvim-treesitter.install').update { with_sync = true }) end, } use { -- Additional text objects via treesitter 'nvim-treesitter/nvim-treesitter-textobjects', after = 'nvim-treesitter', } -- Git related plugins use 'tpope/vim-fugitive' use 'tpope/vim-rhubarb' use 'lewis6991/gitsigns.nvim' use 'drewtempelmeyer/palenight.vim' -- Theme based off the Material Pale Night use 'nvim-lualine/lualine.nvim' -- Fancier statusline use 'lukas-reineke/indent-blankline.nvim' -- Add indentation guides even on blank lines use 'numToStr/Comment.nvim' -- "gc" to comment visual regions/lines use 'tpope/vim-sleuth' -- Detect tabstop and shiftwidth automatically -- Fuzzy Finder (files, lsp, etc) use { 'nvim-telescope/telescope.nvim', branch = '0.1.x', requires = { 'nvim-lua/plenary.nvim' } } -- Fuzzy Finder Algorithm which requires local dependencies to be built. Only load if `make` is available use { 'nvim-telescope/telescope-fzf-native.nvim', run = 'make', cond = vim.fn.executable 'make' == 1 } -- Add custom plugins to packer from ~/.config/nvim/lua/custom/plugins.lua local has_plugins, plugins = pcall(require, 'custom.plugins') if has_plugins then plugins(use) end if is_bootstrap then require('packer').sync() end end) -- When we are bootstrapping a configuration, it doesn't -- make sense to execute the rest of the init.lua. -- -- You'll need to restart nvim, and then it will work. if is_bootstrap then print '==================================' print ' Plugins are being installed' print ' Wait until Packer completes,' print ' then restart nvim' print '==================================' return end -- Automatically source and re-compile packer whenever you save this init.lua local packer_group = vim.api.nvim_create_augroup('Packer', { clear = true }) vim.api.nvim_create_autocmd('BufWritePost', { command = 'source | PackerCompile', group = packer_group, pattern = vim.fn.expand '$MYVIMRC', }) -- [[ Setting options ]] -- See `:help vim.o` -- Set highlight on search vim.o.hlsearch = false -- Make line numbers default, enabled relative linenumbers vim.wo.number = true vim.opt.relativenumber = true -- Enable mouse mode vim.o.mouse = 'a' -- Enable break indent vim.o.breakindent = true -- Save undo history vim.o.undofile = true -- Case insensitive searching UNLESS /C or capital in search vim.o.ignorecase = true vim.o.smartcase = true -- Decrease update time vim.o.updatetime = 250 vim.wo.signcolumn = 'yes' -- Set colorscheme vim.o.termguicolors = true -- vim.cmd.colorscheme('palenight') -- Set completeopt to have a better completion experience vim.o.completeopt = 'menuone,noselect' -- Configure and disable providers. vim.g.python3_host_prog = '/opt/homebrew/bin/python3' vim.g.loaded_ruby_provider = 0 -- [[ Basic Keymaps ]] -- Set as the leader key -- See `:help mapleader` -- NOTE: Must happen before plugins are required (otherwise wrong leader will be used) vim.g.mapleader = ' ' vim.g.maplocalleader = ' ' -- Keymaps for better default experience -- See `:help vim.keymap.set()` vim.keymap.set({ 'n', 'v' }, '', '', { silent = true }) -- Remap for dealing with word wrap vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true }) vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true }) 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 = '*', }) -- Set lualine as statusline -- See `:help lualine.txt` require('lualine').setup { options = { icons_enabled = true, theme = 'auto', component_separators = '|', section_separators = '', }, } -- Enable Comment.nvim require('Comment').setup() -- Enable `lukas-reineke/indent-blankline.nvim` -- See `:help indent_blankline.txt` require('indent_blankline').setup { -- char = '┊', show_trailing_blankline_indent = true, space_char_blankline = " ", show_current_context = true, show_current_context_start = true, } -- Gitsigns -- See `:help gitsigns.txt` require('gitsigns').setup { signs = { add = { text = '+' }, change = { text = '~' }, delete = { text = '_' }, topdelete = { text = '‾' }, changedelete = { text = '~' }, }, } -- [[ Configure Telescope ]] -- See `:help telescope` and `:help telescope.setup()` require('telescope').setup { defaults = { mappings = { i = { [''] = false, [''] = false, }, }, }, } -- Enable telescope fzf native, if installed pcall(require('telescope').load_extension, 'fzf') -- See `:help telescope.builtin` vim.keymap.set('n', '?', require('telescope.builtin').oldfiles, { desc = '[?] Find recently opened files' }) vim.keymap.set('n', '', require('telescope.builtin').buffers, { desc = '[ ] Find existing buffers' }) vim.keymap.set('n', '/', function() -- You can pass additional configuration to telescope to change theme, layout, etc. require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { winblend = 10, previewer = false, }) end, { desc = '[/] Fuzzily search in current buffer]' }) vim.keymap.set('n', 'sf', require('telescope.builtin').find_files, { desc = '[S]earch [F]iles' }) vim.keymap.set('n', 'sh', require('telescope.builtin').help_tags, { desc = '[S]earch [H]elp' }) vim.keymap.set('n', 'sw', require('telescope.builtin').grep_string, { desc = '[S]earch current [W]ord' }) vim.keymap.set('n', 'sg', require('telescope.builtin').live_grep, { desc = '[S]earch by [G]rep' }) vim.keymap.set('n', 'sd', require('telescope.builtin').diagnostics, { desc = '[S]earch [D]iagnostics' }) -- [[ Configure Treesitter ]] -- See `:help nvim-treesitter` require('nvim-treesitter.configs').setup { -- Add languages to be installed here that you want installed for treesitter ensure_installed = { 'c', 'cpp', 'go', 'lua', 'php', 'python', 'rust', 'typescript', 'help' }, 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', }, }, }, } -- Diagnostic keymaps vim.keymap.set('n', '[d', vim.diagnostic.goto_prev) vim.keymap.set('n', ']d', vim.diagnostic.goto_next) vim.keymap.set('n', 'e', vim.diagnostic.open_float) vim.keymap.set('n', 'q', vim.diagnostic.setloclist) -- LSP settings. -- This function gets run when an LSP connects to a particular buffer. local on_attach = function(_, bufnr) -- NOTE: Remember that lua is a real programming language, and as such it is possible -- to define small helper and utility functions so you don't have to repeat yourself -- many times. -- -- In this case, we create a function that lets us more easily define mappings specific -- for LSP related items. It sets the mode, buffer and description for us each time. local nmap = function(keys, func, desc) if desc then desc = 'LSP: ' .. desc end vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc }) end nmap('rn', vim.lsp.buf.rename, '[R]e[n]ame') nmap('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition') nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') nmap('gI', vim.lsp.buf.implementation, '[G]oto [I]mplementation') nmap('D', vim.lsp.buf.type_definition, 'Type [D]efinition') nmap('ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') nmap('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') -- See `:help K` for why this keymap nmap('K', vim.lsp.buf.hover, 'Hover Documentation') nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') -- Lesser used LSP functionality nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') nmap('wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder') nmap('wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder') nmap('wl', function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, '[W]orkspace [L]ist Folders') -- Create a command `:Format` local to the LSP buffer vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_) if vim.lsp.buf.format then vim.lsp.buf.format() elseif vim.lsp.buf.formatting then vim.lsp.buf.formatting() end end, { desc = 'Format current buffer with LSP' }) end -- Setup mason so it can manage external tooling require('mason').setup() -- Enable the following language servers -- Feel free to add/remove any LSPs that you want here. They will automatically be installed local servers = { 'clangd', 'rust_analyzer', 'pyright', 'tsserver', 'sumneko_lua', 'gopls' } -- Ensure the servers above are installed require('mason-lspconfig').setup { ensure_installed = servers, } -- nvim-cmp supports additional completion capabilities local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) for _, lsp in ipairs(servers) do require('lspconfig')[lsp].setup { on_attach = on_attach, capabilities = capabilities, } end -- Turn on lsp status information require('fidget').setup() -- Example custom configuration for lua -- -- Make runtime files discoverable to the server local runtime_path = vim.split(package.path, ';') table.insert(runtime_path, 'lua/?.lua') table.insert(runtime_path, 'lua/?/init.lua') require('lspconfig').sumneko_lua.setup { on_attach = on_attach, capabilities = capabilities, settings = { Lua = { runtime = { -- Tell the language server which version of Lua you're using (most likely LuaJIT) version = 'LuaJIT', -- Setup your lua path path = runtime_path, }, diagnostics = { globals = { 'vim' }, }, workspace = { library = vim.api.nvim_get_runtime_file('', true), checkThirdParty = false, }, -- Do not send telemetry data containing a randomized but unique identifier telemetry = { enable = false }, }, }, } -- nvim-cmp setup local cmp = require 'cmp' local luasnip = require 'luasnip' cmp.setup { snippet = { expand = function(args) luasnip.lsp_expand(args.body) end, }, mapping = cmp.mapping.preset.insert { [''] = cmp.mapping.scroll_docs(-4), [''] = cmp.mapping.scroll_docs(4), [''] = cmp.mapping.complete(), [''] = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = true, }, [''] = 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 = { { name = 'nvim_lsp' }, { name = 'luasnip' }, }, } -- barbar keymaps local map = vim.api.nvim_set_keymap local opts = { noremap = true, silent = true } -- Move to previous/next map('n', '', 'BufferPrevious', opts) map('n', '', 'BufferNext', opts) -- Re-order to previous/next map('n', '', 'BufferMovePrevious', opts) map('n', '>', 'BufferMoveNext', opts) -- Goto buffer in position... map('n', '', 'BufferGoto 1', opts) map('n', '', 'BufferGoto 2', opts) map('n', '', 'BufferGoto 3', opts) map('n', '', 'BufferGoto 4', opts) map('n', '', 'BufferGoto 5', opts) map('n', '', 'BufferGoto 6', opts) map('n', '', 'BufferGoto 7', opts) map('n', '', 'BufferGoto 8', opts) map('n', '', 'BufferGoto 9', opts) map('n', '', 'BufferLast', opts) -- Pin/unpin buffer map('n', '', 'BufferPin', opts) -- Close buffer map('n', '', 'BufferClose', opts) -- Wipeout buffer -- :BufferWipeout -- Close commands -- :BufferCloseAllButCurrent -- :BufferCloseAllButPinned -- :BufferCloseAllButCurrentOrPinned -- :BufferCloseBuffersLeft -- :BufferCloseBuffersRight -- Magic buffer-picking mode map('n', '', 'BufferPick', opts) -- Sort automatically by... map('n', 'bb', 'BufferOrderByBufferNumber', opts) map('n', 'bd', 'BufferOrderByDirectory', opts) map('n', 'bl', 'BufferOrderByLanguage', opts) map('n', 'bw', 'BufferOrderByWindowNumber', opts) -- Other: -- :BarbarEnable - enables barbar (enabled by default) -- :BarbarDisable - very bad command, should never be used vim.api.nvim_create_autocmd("BufWritePost", { pattern = "plugins.lua", command = "source | PackerSync" }) vim.api.nvim_create_autocmd("BufRead", { pattern = "*/node_modules/*", command = "lua vim.diagnostic.disable(0)" }) vim.api.nvim_create_autocmd("BufNewFile", { pattern = "*/node_modules/*", command = "lua vim.diagnostic.disable(0)" }) -- Enable spell checking for certain file types vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, { pattern = { "*.txt", "*.md", "*.tex" }, command = "setlocal spell" }) -- The line beneath this is called `modeline`. See `:help modeline` -- vim: ts=2 sts=2 sw=2 et