-- Bootstrap the Packer plugin manager local fn = vim.fn local install_path = fn.stdpath('data')..'/site/pack/packer/start/packer.nvim' if fn.empty(fn.glob(install_path)) > 0 then packer_bootstrap = fn.system( { 'git', 'clone', '--depth', '1', 'https://github.com/wbthomason/packer.nvim', install_path } ) end -- Packer plugin installations require('packer').startup(function(use) -- Maintain plugin manager use 'wbthomason/packer.nvim' -- Startup speed hacks use { 'lewis6991/impatient.nvim', config = function() require('impatient') end } -- Important tweaks use 'tpope/vim-surround' --- Manipulate parentheses use 'tpope/vim-commentary' --- Use gc or gcc to add comments -- Convenience tweaks use 'tpope/vim-eunuch' --- File manipulation in Vim use 'tpope/vim-vinegar' --- Fixes netrw file explorer use 'tpope/vim-fugitive' --- Git commands and syntax use 'tpope/vim-repeat' --- Actually repeat using . use 'christoomey/vim-tmux-navigator' --- Hotkeys for tmux panes use 'airblade/vim-rooter' --- Change directory to git route -- Colorscheme use { 'morhetz/gruvbox', config = function() vim.cmd[[colorscheme gruvbox]] end } -- Git next to line numbers use { 'lewis6991/gitsigns.nvim', branch = 'main', requires = {'nvim-lua/plenary.nvim'}, config = function() require('gitsigns').setup() end } -- Status bar use { 'hoob3rt/lualine.nvim', requires = { 'kyazdani42/nvim-web-devicons', opt = true }, config = function() require('lualine').setup({ options = { theme = 'gruvbox', icons_enabled = true } }) end } -- Improve speed and filetype detection use { 'nathom/filetype.nvim', config = function() -- Filetype for .env files local envfiletype = function() vim.bo.filetype = 'text' vim.bo.syntax = 'sh' end -- Force filetype patterns that Vim doesn't know about require('filetype').setup({ overrides = { extensions = { Brewfile = 'brewfile', muttrc = 'muttrc', hcl = 'terraform', }, literal = { Caskfile = 'brewfile', [".gitignore"] = 'gitignore', }, complex = { [".*git/config"] = "gitconfig", ["tmux.conf%..*link"] = "tmux", ["gitconfig%..*link"] = "gitconfig", [".*ignore%..*link"] = "gitignore", [".*%.toml%..*link"] = "toml", }, function_extensions = {}, function_literal = { [".envrc"] = envfiletype, [".env"] = envfiletype, [".env.dev"] = envfiletype, [".env.prod"] = envfiletype, [".env.example"] = envfiletype, }, } }) end } -- Alignment tool use 'godlygeek/tabular' -- Markdown renderer / wiki notes use 'vimwiki/vimwiki' -- Snippet engine use 'L3MON4D3/LuaSnip' -- ======================================================================= -- Language Server -- ======================================================================= -- Language server completion plugin use 'hrsh7th/cmp-nvim-lsp' -- Language server engine use { 'neovim/nvim-lspconfig', requires = { 'hrsh7th/cmp-nvim-lsp' }, config = function() local capabilities = require('cmp_nvim_lsp').update_capabilities( vim.lsp.protocol.make_client_capabilities() ) require('lspconfig').rust_analyzer.setup{ capabilities = capabilities } require('lspconfig').tflint.setup{ capabilities = capabilities } require('lspconfig').terraformls.setup{ capabilities = capabilities } require('lspconfig').pyright.setup{ cmd = { "poetry", "run", "pyright-langserver", "--stdio" }, capabilities = capabilities, } if require('lspconfig/util').has_bins('diagnostic-languageserver') then require('lspconfig').diagnosticls.setup{ cmd = { "diagnostic-languageserver", "--stdio" }, filetypes = { "sh" }, on_attach = on_attach, init_options = { filetypes = { sh = "shellcheck" }, linters = { shellcheck = { sourceName = "shellcheck", command = "shellcheck", debounce = 100, args = { "--format=gcc", "-" }, offsetLine = 0, offsetColumn = 0, formatLines = 1, formatPattern = { "^[^:]+:(\\d+):(\\d+):\\s+([^:]+):\\s+(.*)$", { line = 1, column = 2, message = 4, security = 3 } }, securities = { error = "error", warning = "warning", } }, } } } end end } -- Pretty highlights use 'folke/lsp-colors.nvim' -- ======================================================================= -- Completion System -- ======================================================================= -- Completion sources use 'hrsh7th/cmp-buffer' --- Generic text completion use 'hrsh7th/cmp-path' --- Local file completion use 'hrsh7th/cmp-cmdline' --- Command line completion use 'hrsh7th/cmp-nvim-lua' --- Nvim lua api completion use 'saadparwaiz1/cmp_luasnip' --- Luasnip completion -- Completion engine use { 'hrsh7th/nvim-cmp', requires = { 'L3MON4D3/LuaSnip', }, config = function() local cmp = require('cmp') cmp.setup({ snippet = { expand = function(args) require('luasnip').lsp_expand(args.body) end, }, mapping = { [''] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }), [''] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }), [''] = function(fallback) cmp.mapping({ i = cmp.mapping.abort(), c = cmp.mapping.close(), }) vim.cmd('stopinsert') --- Abort and leave insert mode end, -- [''] = cmp.mapping(cmp.mapping.select_next_item(), { 'i', 's' }), -- [''] = cmp.mapping(cmp.mapping.select_prev_item(), { 'i', 's' }), [''] = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Insert, select = true, }) }, sources = { { name = 'nvim_lua' }, { name = 'nvim_lsp' }, { name = 'path' }, { name = 'luasnip' }, { name = 'buffer', keyword_length = 5, max_item_count = 10 }, }, experimental = { native_menu = false, --- Use cmp menu instead of Vim menu ghost_text = true, --- Show preview auto-completion }, }) -- Use buffer source for `/` cmp.setup.cmdline('/', { sources = { { name = 'buffer', keyword_length = 5 } } }) -- Use cmdline & path source for ':' cmp.setup.cmdline(':', { sources = cmp.config.sources({ { name = 'path' } }, { { name = 'cmdline' } }) }) end } -- ======================================================================= -- Syntax -- ======================================================================= -- Syntax engine use { 'nvim-treesitter/nvim-treesitter', run = ':TSUpdate', config = function() require('nvim-treesitter.configs').setup { highlight = { enable = true }, indent = { enable = true }, } end } -- Additional syntax sources use 'bfontaine/Brewfile.vim' -- Brewfile syntax use 'chr4/nginx.vim' -- Nginx syntax use 'hashivim/vim-terraform' -- Terraform formatting use 'towolf/vim-helm' -- Helm syntax use 'rodjek/vim-puppet' -- Puppet syntax -- ======================================================================= -- Fuzzy Launcher -- ======================================================================= use { 'nvim-telescope/telescope.nvim', requires = { 'nvim-lua/plenary.nvim' }, config = function() -- Telescope: quit instantly with escape local actions = require("telescope.actions") require("telescope").setup({ defaults = { mappings = { i = { [""] = actions.close, [""] = "which_key", }, }, }, pickers = { find_files = { theme = "dropdown" }, oldfiles = { theme = "dropdown" }, buffers = { theme = "dropdown" }, }, extensions = { fzy_native = {}, tmux = {}, zoxide = {}, neoclip = {}, }, }) end } -- Faster sorting use 'nvim-telescope/telescope-fzy-native.nvim' -- Jump around tmux sessions use 'camgraff/telescope-tmux.nvim' -- Jump directories use { 'jvgrootveld/telescope-zoxide', requires = {'nvim-lua/popup.nvim'}, } -- Clipboard history use { "AckslD/nvim-neoclip.lua", branch = 'main', requires = { {'tami5/sqlite.lua', module = 'sqlite'}, {'nvim-telescope/telescope.nvim'}, }, config = function() require('neoclip').setup({ enable_persistant_history = true, }) require('telescope').load_extension('neoclip') end } -- ======================================================================= -- Install on initial bootstrap if packer_bootstrap then require('packer').sync() end end) -- =========================================================================== -- Settings -- =========================================================================== vim.o.termguicolors = true --- Set to truecolor vim.o.hidden = true --- Don't unload buffers when leaving them vim.wo.number = true --- Show line numbers vim.wo.relativenumber = true --- Relative numbers instead of absolute vim.o.list = true --- Reveal whitespace with dashes vim.o.expandtab = true --- Tabs into spaces vim.o.shiftwidth = 4 --- Amount to shift with > key vim.o.softtabstop = 4 --- Amount to shift with key vim.o.ignorecase = true --- Ignore case when searching vim.o.smartcase = true --- Check case when using capitals in search vim.o.infercase = true --- Don't match cases when completing suggestions vim.o.incsearch = true --- Search while typing vim.o.visualbell = true --- No sounds vim.o.scrolljump = 1 --- Number of lines to scroll vim.o.scrolloff = 3 --- Margin of lines to see while scrolling vim.o.splitright = true --- Vertical splits on the right side vim.o.splitbelow = true --- Horizontal splits on the bottom side vim.o.pastetoggle = "" --- Use F3 to enter raw paste mode vim.o.clipboard = "unnamedplus" --- Uses system clipboard for yanking vim.o.updatetime = 300 --- Faster diagnostics vim.o.mouse = "nv" --- Mouse interaction / scrolling -- Neovim features vim.o.inccommand = "split" --- Live preview search and replace vim.o.completeopt = "menu,menuone,noselect" --- Required for nvim-cmp completion -- Required until 0.6.0: do not source the default filetype.vim vim.g.did_load_filetypes = 1 -- Remember last position when reopening file vim.api.nvim_exec([[ au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal! g`\"" | endif ]], false) -- Better backup, swap and undo storage vim.o.backup = true --- Easier to recover and more secure vim.bo.swapfile = false --- Instead of swaps, create backups vim.bo.undofile = true --- Keeps undos after quit -- Create backup directories if they don't exist -- Should be fixed in 0.6 by https://github.com/neovim/neovim/pull/15433 vim.o.backupdir = vim.fn.stdpath('cache') .. '/backup' vim.api.nvim_exec([[ if !isdirectory(&backupdir) call mkdir(&backupdir, "p") endif ]], false) -- LaTeX options vim.api.nvim_exec([[ au FileType tex inoremap ;bf \textbf{}i au BufWritePost *.tex silent! execute "!pdflatex -output-directory=%:p:h % >/dev/null 2>&1" | redraw! ]], false) -- Highlight when yanking vim.api.nvim_exec([[ au TextYankPost * silent! lua vim.highlight.on_yank { timeout = 250 } ]], false) -- Auto-pairs vim.g.AutoPairsFlyMode = 0 -- Netrw vim.g.netrw_liststyle = 3 -- Change style to 'tree' view vim.g.netrw_banner = 0 -- Remove useless banner vim.g.netrw_winsize = 15 -- Explore window takes % of page vim.g.netrw_browse_split = 4 -- Open in previous window vim.g.netrw_altv = 1 -- Always split left -- Formatting vim.g.terraform_fmt_on_save = 1 -- Formats with terraform plugin vim.g.rustfmt_autosave = 1 -- Formats with rust plugin -- VimWiki vim.g.vimwiki_list = { { ["path"] = "$NOTES_PATH", ["syntax"] = "markdown", ["index"] = "home", ["ext"] = ".md" } } vim.g.vimwiki_key_mappings = { ["all_maps"] = 1, ["mouse"] = 1, } vim.g.vimwiki_auto_chdir = 1 -- Set local dir to Wiki when open vim.g.vimwiki_create_link = 0 -- Don't automatically create new links vim.g.vimwiki_listsyms = " x" -- Set checkbox symbol progression vim.g.vimwiki_table_mappings = 0 -- VimWiki table keybinds interfere with tab completion vim.api.nvim_exec([[ au FileType markdown inoremap ;tt :AddTag function! PInsert(item) let @z=a:item norm "zpx endfunction command! AddTag call fzf#run({'source': 'rg "#[A-Za-z/]+[ |\$]" -o --no-filename --no-line-number | sort | uniq', 'sink': function('PInsert')}) ]], false) -- =========================================================================== -- Key Mapping -- =========================================================================== -- Remap space as leader key vim.api.nvim_set_keymap("", "", "", {noremap=true, silent=true}) vim.g.mapleader = " " vim.g.maplocalleader = " " -- Keep selection when changing indentation vim.api.nvim_set_keymap("v", "<", "", ">gv", {noremap=true}) -- Unset search pattern register vim.api.nvim_set_keymap("n", "", ":noh", {noremap=true, silent=true}) -- Shuffle lines around vim.api.nvim_set_keymap("n", "", ":m .+1==", {noremap=true}) vim.api.nvim_set_keymap("n", "", ":m .-2==", {noremap=true}) vim.api.nvim_set_keymap("i", "", ":m .+1==gi", {noremap=true}) vim.api.nvim_set_keymap("i", "", ":m .-2==gi", {noremap=true}) vim.api.nvim_set_keymap("v", "", ":m '>+1gv=gv", {noremap=true}) vim.api.nvim_set_keymap("v", "", ":m '<-2gv=gv", {noremap=true}) -- Telescope (fuzzy finder) vim.api.nvim_set_keymap("n", "/", ":Telescope live_grep", {noremap=true}) vim.api.nvim_set_keymap("n", "ff", ":Telescope find_files", {noremap=true}) vim.api.nvim_set_keymap("n", "fa", ":Telescope file_browser", {noremap=true}) vim.api.nvim_set_keymap("n", "wt", ":Telescope tmux sessions", {noremap=true}) vim.api.nvim_set_keymap("n", "ww", ":Telescope tmux windows", {noremap=true}) vim.api.nvim_set_keymap("n", "w/", ":Telescope tmux pane_contents", {noremap=true}) vim.api.nvim_set_keymap("n", "fz", ":Telescope zoxide list", {noremap=true}) vim.api.nvim_set_keymap("n", "b", ":Telescope buffers", {noremap=true}) vim.api.nvim_set_keymap("n", "hh", ":Telescope help_tags", {noremap=true}) vim.api.nvim_set_keymap("n", "fr", ":Telescope oldfiles", {noremap=true}) vim.api.nvim_set_keymap("n", "cc", ":Telescope commands", {noremap=true}) vim.api.nvim_set_keymap("n", "cr", ":Telescope command_history", {noremap=true}) vim.api.nvim_set_keymap("n", "y", ":Telescope neoclip", {noremap=true}) vim.api.nvim_set_keymap("n", "s", ":Telescope current_buffer_fuzzy_find", {noremap=true}) vim.api.nvim_set_keymap("n", "gc", ":Telescope git_commits", {noremap=true}) vim.api.nvim_set_keymap("n", "gf", ":Telescope git_bcommits", {noremap=true}) vim.api.nvim_set_keymap("n", "gb", ":Telescope git_branches", {noremap=true}) vim.api.nvim_set_keymap("n", "gs", ":Telescope git_status", {noremap=true}) -- LSP vim.api.nvim_set_keymap("n", "gd", "lua vim.lsp.buf.definition()", {silent=true, noremap=true}) vim.api.nvim_set_keymap("n", "gi", "lua vim.lsp.buf.implementation()", {silent=true, noremap=true}) vim.api.nvim_set_keymap("n", "gh", "lua vim.lsp.buf.hover()", {silent=true, noremap=true}) vim.api.nvim_set_keymap("n", "]e", "lua vim.lsp.diagnostic.goto_next()", {silent=true, noremap=true}) vim.api.nvim_set_keymap("n", "[e", "lua vim.lsp.diagnostic.goto_prev()", {silent=true, noremap=true}) vim.api.nvim_set_keymap("n", "e", "lua vim.lsp.diagnostic.show_line_diagnostics()", {silent=true, noremap=true}) -- File commands vim.api.nvim_set_keymap("n", "q", ":quit", {noremap=true}) vim.api.nvim_set_keymap("n", "Q", ":quitall", {noremap=true}) vim.api.nvim_set_keymap("n", "fs", ":write", {noremap=true}) vim.api.nvim_set_keymap("n", "fe", ":!chmod 755 %", {noremap=true}) vim.api.nvim_set_keymap("n", "fn", ":!chmod 644 %", {noremap=true}) vim.api.nvim_set_keymap("n", "fd", ":lcd %:p:h", {silent=true, noremap=true}) vim.api.nvim_set_keymap("n", "fu", ":lcd ..", {silent=true, noremap=true}) vim.api.nvim_set_keymap("n", "", ":b#", {silent=true, noremap=true}) vim.api.nvim_set_keymap("n", "gr", ":!gh repo view -w", {silent=true, noremap=true}) vim.api.nvim_set_keymap("n", "tt", [[exe 'edit ~/notes/journal/'.strftime("%Y-%m-%d_%a").'.md']], {noremap=true} ) -- Window commands vim.api.nvim_set_keymap("n", "wv", ":vsplit", {noremap=true}) vim.api.nvim_set_keymap("n", "wh", ":split", {noremap=true}) vim.api.nvim_set_keymap("n", "wm", ":only", {noremap=true}) -- Tabularize vim.api.nvim_set_keymap("", "ta", ":Tabularize /", {noremap=true}) vim.api.nvim_set_keymap("", "t#", ":Tabularize /#", {noremap=true}) vim.api.nvim_set_keymap("", "t\"", ":Tabularize /\"", {noremap=true}) vim.api.nvim_set_keymap("", "tl", ":Tabularize /--", {noremap=true}) vim.api.nvim_set_keymap("", "tL", ":Tabularize /---", {noremap=true}) -- Vimrc editing vim.api.nvim_set_keymap("n", "fv", ":edit $MYVIMRC", {noremap=true}) vim.api.nvim_set_keymap("n", "rr", ":luafile $MYVIMRC", {noremap=true}) vim.api.nvim_set_keymap("n", "rp", ":luafile $MYVIMRC:PackerInstall:PackerCompile", {noremap=true}) vim.api.nvim_set_keymap("n", "rc", ":luafile $MYVIMRC:PackerCompile", {noremap=true}) -- Keep cursor in place vim.api.nvim_set_keymap("n", 'n', "nzz", {noremap=true}) vim.api.nvim_set_keymap("n", 'N', "Nzz", {noremap=true}) vim.api.nvim_set_keymap("n", 'J', "mzJ`z", {noremap=true}) --- Mark and jump back to it -- Add undo breakpoints vim.api.nvim_set_keymap("i", ',', ",u", {noremap=true}) vim.api.nvim_set_keymap("i", '.', ".u", {noremap=true}) vim.api.nvim_set_keymap("i", '!', "!u", {noremap=true}) vim.api.nvim_set_keymap("i", '?', "?u", {noremap=true}) -- Other vim.api.nvim_set_keymap("t", "", "", {noremap=true}) --- Exit terminal mode vim.api.nvim_set_keymap("n", "", ":noh", {noremap=true, silent=true}) --- Clear search vim.api.nvim_set_keymap('n', 'Y', 'y$', { noremap = true}) --- Copy to end of line