-- Managed by Nix -- To install everything run `:PackerSync` -- https://dev.to/voyeg3r/writing-useful-lua-functions-to-my-neovim-14ki -- function to remove whitespace and preserve spot on save function _G.preserve(cmd) cmd = string.format('keepjumps keeppatterns execute %q', cmd) local original_cursor = vim.fn.winsaveview() vim.api.nvim_command(cmd) vim.fn.winrestview(original_cursor) end vim.cmd([[autocmd BufWritePre,FileWritePre,FileAppendPre,FilterWritePre * :lua preserve('%s/\\s\\+$//ge')]]) -- Bootstrap packer if not installed 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 fn.system({'git', 'clone', '--depth', '1', 'https://github.com/wbthomason/packer.nvim', install_path}) vim.cmd 'packadd packer.nvim' end -- Debug function for printing lua tables function _G.print_table(mytable) for k,v in pairs(mytable) do if (type(v) == "table") then print(k) print_table(v) else print(k, v) end end end -- Set up spacebar as leader -- https://icyphox.sh/blog/nvim-lua/ vim.api.nvim_set_keymap('n', '', '', {}) vim.g.mapleader = ' ' -- Set spaces > tabs, 4 as default vim.o.expandtab = true vim.o.tabstop = 4 vim.o.shiftwidth = 0 vim.o.relativenumber = true -- Distable word wrap vim.o.wrap = false vim.o.history = 1000 -- Wildmode show list, complete to first result vim.o.wildignore = "*/app/cache,*/vendor,*/env,*.pyc,*/venv,*/__pycache__,*/venv" -- Default split directions vim.o.splitright = true vim.o.splitbelow = true -- set spelling language vim.o.spelllang = "en_ca" -- Allow hidden buffers, no complain about saved work when switching vim.o.hidden = true -- Ask confirm on exit instead of error vim.o.confirm = true local highlights = { "Search ctermfg=166", "DiffAdd cterm=BOLD ctermfg=NONE ctermbg=22", "DiffDelete cterm=BOLD ctermfg=NONE ctermbg=52", "DiffChange cterm=BOLD ctermfg=NONE ctermbg=23", "DiffText cterm=BOLD ctermfg=NONE ctermbg=23", "Normal guibg=NONE ctermbg=NONE", "Search ctermbg=None ctermfg=166", "PrimaryBlock ctermfg=06 ctermbg=NONE", "SecondaryBlock ctermfg=06 ctermbg=NONE", "Blanks ctermfg=07 ctermbg=NONE", "ColorColumn ctermbg=cyan", "IndentBlanklineIndent1 ctermbg=234 ctermfg=NONE", "IndentBlanklineIndent2 ctermbg=235 ctermfg=NONE", } for i, highlight in ipairs(highlights) do vim.cmd('au VimEnter * hi ' .. highlight) end -- Along with the highlight definition for ColorColumn above, these options -- will set colored marks at certain line lengths vim.cmd [[ au BufEnter *.py let w:m1=matchadd('ColorColumn', '\%81v', 100) au BufEnter *.py let w:m2=matchadd('Error', '\%121v', 100) au BufLeave *.py call clearmatches() ]] -- Custom commands vim.cmd [[ command! MakeTagsPython !ctags --exclude=venv --exclude=.venv --languages=python --python-kinds=-i -R . ]] -- Keymaps --noh gets rid of highlighted search results vim.api.nvim_set_keymap('n', '', ':noh', { noremap = true }) -- `jj` maps to escape vim.api.nvim_set_keymap('i', 'jj', '', { noremap = true }) -- Visually select last copied text vim.api.nvim_set_keymap('n', 'gp', "`[v`]", { noremap = true }) -- Changelist navigation vim.api.nvim_set_keymap('n', 'co', 'copen', { noremap = true }) vim.api.nvim_set_keymap('n', 'cc', 'cclose', { noremap = true }) vim.api.nvim_set_keymap('n', 'cp', "cprev", { noremap = true }) vim.api.nvim_set_keymap('n', 'cn', "cnext", { noremap = true }) vim.api.nvim_set_keymap('n', 'lp', "lprev", { noremap = true }) vim.api.nvim_set_keymap('n', 'ln', "lnext", { noremap = true }) -- Visually select line without ending vim.api.nvim_set_keymap('n', 'v', '^v$h', { noremap = true }) -- Ledger Shortcuts -- Copy the last entry vim.api.nvim_set_keymap('n', 'll', 'G{jV}y}p10l', { noremap = true }) -- Copy the current entry to the bottom, copy date from last entry vim.api.nvim_set_keymap('n', 'lb', '{jV}yGp10l{{jvEy}jvEpl', { noremap = true }) -- Copy the current entry to the next position --vim.api.nvim_set_keymap('n', 'ln', '{jV}y}p10l', { noremap = true }) -- Jump down from line to replace dollar ammount vim.api.nvim_set_keymap('n', 'ld', 'j^f$lC', { noremap = true }) -- After searching pull entry to current position vim.api.nvim_set_keymap('n', 'ly', 'vapyp{{jvEy}jvEpl', { noremap = true }) -- Shorcut to insert pudb statements for python vim.api.nvim_set_keymap('n', 'ep', 'ofrom pudb import set_trace; set_trace()', { noremap = true }) -- Easy new tab creation vim.api.nvim_set_keymap('n', 't', "tabnew", { noremap = true }) vim.api.nvim_set_keymap('n', '', 'fT', { noremap = true }) vim.api.nvim_set_keymap('n', '', 'vT', { noremap = true }) vim.api.nvim_set_keymap('n', '', 'vT', { noremap = true }) vim.api.nvim_set_keymap('n', '', 'w', { noremap = true }) vim.api.nvim_set_keymap('n', '', 'wa', { noremap = true }) vim.api.nvim_set_keymap('n', 'ee', 'e!', { noremap = true }) vim.api.nvim_set_keymap('n', ' k', [[(v:count > 1 ? "m'" . v:count : '') . 'k']], { noremap = true }) vim.api.nvim_set_keymap('n', ' j', [[(v:count > 1 ? "m'" . v:count : '') . 'j']], { noremap = true }) -- Call Ale Fix vim.api.nvim_set_keymap('n', 'ei', 'ALEFix', { noremap = true }) -- Build a custom status line local status_line = { '%#PrimaryBlock#', '%#SecondaryBlock#', '%#Blanks#', '%f', '%m', '%=', '%#SecondaryBlock#', '%l,%c ', '%#PrimaryBlock#', '%{&filetype}', } vim.o.statusline = table.concat(status_line) -- Packer package manage return require('packer').startup(function() use { 'wbthomason/packer.nvim', config = function() vim.api.nvim_set_keymap('n', 'ps', 'source ~/.config/nvim/init.luaPackerSync', { noremap = true }) end } use { 'arcticicestudio/nord-vim', config = function() vim.cmd [[ colorscheme nord ]] end } use 'p00f/nvim-ts-rainbow' use { 'nvim-treesitter/nvim-treesitter', run = ':TSUpdate', config = function() require('nvim-treesitter.configs').setup { ensure_installed = { "python", "lua", "nix", "json", "bash", "html", "toml", }, highlight = { enable = true, }, indent = { enable = true, }, rainbow = { enable = true, -- I use termcolors but this errors if left blank colors = { "#000000", "#000000", "#000000", "#000000", }, termcolors = { 'darkblue', 'magenta', 'yellow', 'darkcyan', } } } end, } use { "neovim/nvim-lspconfig", requires = { {'hrsh7th/nvim-cmp'}, {'hrsh7th/cmp-nvim-lsp'}, }, config = function() nvim_lsp = require('lspconfig') -- Use an on_attach function to only map the following keys -- after the language server attaches to the current buffer local on_attach = function(client, bufnr) local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end -- Enable completion triggered by buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc') -- Mappings. local opts = { noremap=true, silent=true } -- See `:help vim.lsp.*` for documentation on any of the below functions buf_set_keymap('n', 'gD', 'lua vim.lsp.buf.declaration()', opts) buf_set_keymap('n', 'gd', 'lua vim.lsp.buf.definition()', opts) buf_set_keymap('n', 'K', 'lua vim.lsp.buf.hover()', opts) buf_set_keymap('n', 'gi', 'lua vim.lsp.buf.implementation()', opts) buf_set_keymap('n', '', 'lua vim.lsp.buf.signature_help()', opts) buf_set_keymap('n', 'wa', 'lua vim.lsp.buf.add_workspace_folder()', opts) buf_set_keymap('n', 'wr', 'lua vim.lsp.buf.remove_workspace_folder()', opts) buf_set_keymap('n', 'wl', 'lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))', opts) buf_set_keymap('n', 'D', 'lua vim.lsp.buf.type_definition()', opts) buf_set_keymap('n', 'rn', 'lua vim.lsp.buf.rename()', opts) buf_set_keymap('n', 'ca', 'lua vim.lsp.buf.code_action()', opts) buf_set_keymap('n', 'gr', 'lua vim.lsp.buf.references()', opts) buf_set_keymap('n', 'e', 'lua vim.lsp.diagnostic.show_line_diagnostics()', opts) buf_set_keymap('n', '[d', 'lua vim.lsp.diagnostic.goto_prev()', opts) buf_set_keymap('n', ']d', 'lua vim.lsp.diagnostic.goto_next()', opts) buf_set_keymap('n', 'q', 'lua vim.lsp.diagnostic.set_loclist()', opts) buf_set_keymap('n', 'f', 'lua vim.lsp.buf.formatting()', opts) end -- Use a loop to conveniently call 'setup' on multiple servers and -- map buffer local keybindings when the language server attaches -- local servers = { 'pyls', 'rust_analyzer', 'tsserver' } local servers = { 'jedi_language_server', 'bashls', 'terraformls' } -- Add additional capabilities supported by nvim-cmp local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = require('cmp_nvim_lsp').update_capabilities(capabilities) -- Setup language servers for _, lsp in ipairs(servers) do nvim_lsp[lsp].setup { on_attach = on_attach, flags = { debounce_text_changes = 150, }, capabilities = capabilities, } end -- Set completeopt to have a better completion experience vim.o.completeopt = 'menuone,noselect' -- nvim-cmp setup local cmp = require 'cmp' cmp.setup { mapping = { [''] = cmp.mapping.select_prev_item(), [''] = cmp.mapping.select_next_item(), [''] = cmp.mapping.scroll_docs(-4), [''] = cmp.mapping.scroll_docs(4), [''] = cmp.mapping.complete(), [''] = cmp.mapping.close(), [''] = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = true, }, [''] = function(fallback) if cmp.visible() then cmp.select_next_item() else fallback() end end, [''] = function(fallback) if cmp.visible() then cmp.select_prev_item() else fallback() end end, }, sources = { { name = 'nvim_lsp' }, }, } end, } use 'nvim-treesitter/playground' use 'nvim-lua/completion-nvim' use 'tpope/vim-commentary' use 'tpope/vim-surround' use 'tpope/vim-repeat' use { 'junegunn/fzf.vim', requires = { {'junegunn/fzf'} }, config = function() vim.api.nvim_set_keymap('n', 'ff', "Files", { noremap = true }) vim.api.nvim_set_keymap('n', 'fb', "Buffers", { noremap = true }) vim.api.nvim_set_keymap('n', 'ft', "Tags", { noremap = true }) vim.api.nvim_set_keymap('n', 'fm', "Marks", { noremap = true }) vim.api.nvim_set_keymap('n', 'fg', "GF?", { noremap = true }) vim.cmd([[let $FZF_DEFAULT_COMMAND = 'find . -type f -not -path "*/\.git/*" -not -path "*/\.mypy_cache/*" -not -path "*/\.venv/*" -not -path "*/\node_modules/*" ']]) end, } use { 'FooSoft/vim-argwrap', config = function() vim.api.nvim_set_keymap('n', 'ew', 'ArgWrap', { noremap = true }) end } use { 'Thornycrackers-Forks/vim-fugitive', config = function() vim.api.nvim_set_keymap('n', 'du', 'diffupdate', { noremap = true }) vim.api.nvim_set_keymap('n', 'dd', 'diffget', { noremap = true }) vim.api.nvim_set_keymap('n', 'df', 'diffput', { noremap = true }) vim.api.nvim_set_keymap('n', 'dc', ']c', { noremap = true }) vim.api.nvim_set_keymap('n', 'de', '[c', { noremap = true }) -- vim.api.nvim_set_keymap('n', 'gs', 'Git', { noremap = true }) vim.cmd([[ function! ToggleGStatus() if buflisted(bufname('.git/index')) bd .git/index else G res 15 endif endfunction nnoremap gs :call ToggleGStatus() ]]) vim.api.nvim_set_keymap('n', 'gb', 'Git blame', { noremap = true }) vim.api.nvim_set_keymap('n', 'gd', 'Gdiffsplit', { noremap = true }) end } use { 'lukas-reineke/indent-blankline.nvim', config = function() require("indent_blankline").setup { char = " ", char_highlight_list = { "IndentBlanklineIndent1", "IndentBlanklineIndent2", }, show_trailing_blankline_indent = false, } end, } use { 'francoiscabrol/ranger.vim', -- bclose gets rid of "[Process exited 0]" annoyance requires = { {'rbgrouleff/bclose.vim'} }, } use { 'ptzz/lf.vim', -- Adds a floating window requires = { {'voldikss/vim-floaterm'} }, config = function() vim.g.floaterm_opener = "edit" vim.g.floaterm_width = 0.99 vim.g.floaterm_height = 0.99 -- vim.g.lf_replace_netrw = 1; vim.api.nvim_set_keymap('n', 'm', 'Lf', { noremap = true }); vim.api.nvim_set_keymap('n', 'n', 'LfWorkingDirectory', { noremap = true}); end } use 'bkad/CamelCaseMotion' use { 'phaazon/hop.nvim', as = 'hop', config = function() -- you can configure Hop the way you like here; see :h hop-config vim.api.nvim_set_keymap('', 's', 'HopChar2', { noremap = true }) require'hop'.setup { keys = 'etovxqpdygfblzhckisuran' } end } -- The treesitter for nix doesn't do indents use 'LnL7/vim-nix' use { 'dense-analysis/ale', config = function() vim.g.ale_linters = { sh = { "shellcheck", }, python = { "flake8" }, dockerfile = { "hadolint" }, terraform = { "terraform_ls" }, } vim.g.ale_fixers = { sh = { "shfmt", }, python = { "isort", "black" }, terraform = { "terraform" }, } vim.cmd([[ autocmd BufRead *.py :ALEFix ]]) end } use 'junegunn/goyo.vim' use { 'ojroques/vim-oscyank', config = function() vim.api.nvim_set_keymap('n', 'y', 'OSCYankReg 0', { noremap = true }) end } use 'hashivim/vim-terraform' use { 'mileszs/ack.vim', config = function() vim.cmd([[ nnoremap / :call AckSearch() function! AckSearch() call inputsave() let term = input('Search: ') call inputrestore() if !empty(term) execute "Ack! " . term endif endfunction " Setting better default settings let g:ackprg = \ "ack -s -H --nocolor --nogroup --column --ignore-dir=.venv/ --ignore-dir=.vimcache/ --ignore-dir=migrations/ --ignore-dir=.mypy_cache/ --ignore-file=is:tags --nojs --nocss --nosass" ]]) end } end)