-- Managed by Nix -- -- 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')]]) -- 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.cmd [[ autocmd Filetype nix setlocal ts=2 sw=2 sts=0 expandtab autocmd Filetype terraform setlocal ts=2 sw=2 sts=0 expandtab autocmd Filetype hcl setlocal ts=2 sw=2 sts=0 expandtab autocmd Filetype html setlocal ts=2 sw=2 sts=0 expandtab autocmd Filetype htmldjango setlocal ts=2 sw=2 sts=0 expandtab autocmd BufNewFile,BufRead *.nomad setfiletype hcl autocmd BufNewFile,BufRead *.yaml setfiletype yaml.ansible autocmd BufNewFile,BufRead *.yml setfiletype yaml.ansible ]] 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 -- If a filetype has folding enabled, make sure all folds are opened vim.o.foldlevel=99 -- My Highlights vim.cmd [[ au VimEnter * hi Search ctermfg=166 au VimEnter * hi DiffAdd cterm=BOLD ctermfg=NONE ctermbg=22 au VimEnter * hi DiffDelete cterm=BOLD ctermfg=NONE ctermbg=52 au VimEnter * hi DiffChange cterm=BOLD ctermfg=NONE ctermbg=23 au VimEnter * hi DiffText cterm=BOLD ctermfg=NONE ctermbg=23 au VimEnter * hi Normal guibg=NONE ctermbg=NONE au VimEnter * hi Search ctermbg=None ctermfg=166 au VimEnter * hi PrimaryBlock ctermfg=06 ctermbg=NONE au VimEnter * hi SecondaryBlock ctermfg=06 ctermbg=NONE au VimEnter * hi Blanks ctermfg=07 ctermbg=NONE au VimEnter * hi ColorColumn ctermbg=cyan au VimEnter * hi IndentBlanklineIndent1 ctermbg=234 ctermfg=NONE au VimEnter * hi IndentBlanklineIndent2 ctermbg=235 ctermfg=NONE function! s:goyo_leave() hi NonText ctermbg=none hi Normal guibg=NONE ctermbg=NONE endfunction autocmd! User GoyoLeave call goyo_leave() ]] -- 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 }) vim.api.nvim_set_keymap('n', 'lo', "lopen", { noremap = true }) vim.api.nvim_set_keymap('n', 'lc', "lclose", { noremap = true }) -- Shorcut to insert pudb statements for python vim.api.nvim_set_keymap('n', 'epu', 'ofrom pudb import set_trace; set_trace()', { noremap = true }) -- Shorcut to embed ipython vim.api.nvim_set_keymap('n', 'epi', 'ofrom IPython import embedfrom traitlets.config import get_configc = get_config()c.InteractiveShellEmbed.colors = "Linux"embed(config=c)', { noremap = true }) -- yank current word and make print statement on next line vim.api.nvim_set_keymap('n', 'epp', 'yiwoprint("pa: ", pa)V=', { 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', '', 'qa!', { 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', 'ef', 'ALEFix', { noremap = true }) vim.api.nvim_set_keymap('n', 'el', 'ALELint', { noremap = true }) vim.api.nvim_set_keymap('n', 'et', 'lua toggle_ale_linting()', { noremap = true }) -- Markdown functions vim.api.nvim_set_keymap('n', 'po', 'AngryReviewerkALELintlopenk', { noremap = true }) vim.api.nvim_set_keymap('n', 'pse', 'LanguageToolSetUp', { noremap = true }) vim.api.nvim_set_keymap('n', 'psc', 'LanguageToolCheck', { noremap = true }) vim.api.nvim_set_keymap('n', 'psu', 'LanguageToolSummary', { noremap = true }) vim.api.nvim_set_keymap('n', 'psl', 'LanguageToolClear', { noremap = true }) vim.api.nvim_set_keymap('n', 'pc', 'ccloselclose', { noremap = true }) vim.api.nvim_set_keymap('n', 'pg', 'Goyo', { noremap = true }) vim.api.nvim_set_keymap('n', 'pp', 'vipJVgq', { noremap = true }) -- Add "il" text object to mean "in line" vim.api.nvim_set_keymap('x', 'il', 'g_o^', { noremap = true }) vim.api.nvim_set_keymap('o', 'il', 'normal vil', { noremap = true }) vim.api.nvim_set_keymap('n', 'v', '^vg_o^', { 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) -- Options for all my plugins. Plugins are already installed via nix. -- nord-vim vim.cmd [[ colorscheme gruvbox ]] -- nvim-ts-rainbow -- nvim-treesitter require('nvim-treesitter.configs').setup { highlight = { enable = true, }, indent = { enable = true, }, rainbow = { enable = true, -- I use termcolors but this errors if left blank } } -- nvim-lspconfig -- nvim-cmp -- cmp-nvim-lsp 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', 'ansiblels' } -- Add additional capabilities supported by nvim-cmp local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = require('cmp_nvim_lsp').default_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' }, }, } -- nvim-fzf vim.api.nvim_set_keymap('n', 'fb', "let g:fzf_buffers_jump = 0Buffers", { 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/*" ']]) vim.cmd([[ nnoremap ff :call FilesDefault() function! FilesDefault() if exists('g:fzf_action') " I don't set fzf_action except for the FilesNew thing so unset it for " default behaviour in files unlet g:fzf_action endif execute 'Files' endfunction nnoremap fn :let g:fzf_action = { 'enter': 'tab split' }:Files nnoremap fo :call BufferTabJump() function! BufferTabJump() let g:fzf_buffers_jump = 1 execute 'Buffers' endfunction ]]) -- vim-argwrap vim.api.nvim_set_keymap('n', 'ew', 'ArgWrap', { noremap = true }) -- vim-fugitive 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 }) -- indent-blankline-nvim require("indent_blankline").setup { char = " ", char_highlight_list = { "IndentBlanklineIndent1", "IndentBlanklineIndent2", }, show_trailing_blankline_indent = false, } -- lf-vim -- vim-floaterm vim.g.floaterm_opener = "edit" vim.g.floaterm_width = 0.99 vim.g.floaterm_height = 0.99 vim.api.nvim_set_keymap('n', 'm', 'Lf', { noremap = true }); vim.api.nvim_set_keymap('n', 'n', 'LfWorkingDirectory', { noremap = true}); --hop-nvim vim.api.nvim_set_keymap('', 's', 'HopChar2', { noremap = true }) require'hop'.setup { keys = 'etovxqpdygfblzhckisuran' } -- ale vim.g.ale_lint_on_enter = 1 vim.g.ale_lint_on_save = 1 vim.g.ale_lint_on_insert_leave = 1 vim.g.ale_lint_on_text_changed = 1 vim.g.ale_fix_on_save = 1 -- Custom function for completely toggling ale linting function _G.toggle_ale_linting() if (vim.g.ale_lint_on_insert_leave == 0) then vim.api.nvim_command("ALEEnable") vim.g.ale_lint_on_enter = 1 vim.g.ale_lint_on_save = 1 vim.g.ale_lint_on_insert_leave = 1 vim.g.ale_lint_on_text_changed = 1 vim.g.ale_fix_on_save = 1 else vim.api.nvim_command("ALEDisable") vim.g.ale_lint_on_enter = 0 vim.g.ale_lint_on_save = 0 vim.g.ale_lint_on_insert_leave = 0 vim.g.ale_lint_on_text_changed = 0 vim.g.ale_fix_on_save = 0 end end vim.g.ale_linters = { sh = { "shellcheck", }, python = { "flake8" }, dockerfile = { "hadolint" }, terraform = { "terraform_ls" }, markdown = { "vale" }, nix = { "nix" }, ansible = { "ansible-lint" }, } vim.g.ale_fixers = { sh = { "shfmt", }, python = { "isort", "black" }, terraform = { "terraform" }, nix = { "nixfmt" }, } -- osc-yank vim.api.nvim_set_keymap('n', 'y', 'OSCYankRegister 0', { noremap = true }) -- vim-angry-reviewer vim.g.AngryReviewerEnglish = 'american' -- ack.vim 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" ]]) -- camelcasemotion vim.g.camelcasemotion_key = ',' -- vim-oscyank -- https://github.com/ojroques/vim-oscyank/issues/26#issuecomment-1145673058 -- Fixing issues with tmux vim.cmd([[ let g:oscyank_term = 'default' ]]) -- vim-bufkill vim.api.nvim_set_keymap('n', 'bd', 'BD', { noremap = true }) -- vim-markdown vim.g.vim_markdown_auto_insert_bullets = 0 vim.g.vim_markdown_new_list_item_indent = 0