summaryrefslogtreecommitdiff
path: root/shared/home-manager/neovim
diff options
context:
space:
mode:
authorLinnnus <[email protected]>2024-12-21 15:47:33 +0100
committerLinnnus <[email protected]>2024-12-21 16:19:04 +0100
commit8353554315564b89dfe27d5130080ed04a0a65ad (patch)
tree896de88b6ea2701692b3ffe977c23947a786318e /shared/home-manager/neovim
parent9b7ed17b27157a25e57a6e38be3bcfeaa70ec9e8 (diff)
Move to a profile-based configuration where common
This patch makes it so common configuration is now located in shared/ and each host basically just becomes a bunch of import statements. The exception here is host-specific configuration like the `*.linus.onl` that live inside `hosts/ahmed/`. Specifically I have: - moved common configuration `shared/{nixos,home-manager,nix-darwin}`. - moved `hosts/common.nix` to `shared/nixos/common-{nix,shell}-settings.nix`. - split `hosts/muhammed/{dev-utils,neovim}` into per-language configuration. This patch was done in preparation for the arrival of a new host, which will need to share a lot of configuration with Muhammed.
Diffstat (limited to 'shared/home-manager/neovim')
-rw-r--r--shared/home-manager/neovim/completion.nix47
-rw-r--r--shared/home-manager/neovim/default.nix28
-rw-r--r--shared/home-manager/neovim/editing-plugins.nix26
-rw-r--r--shared/home-manager/neovim/init.vim274
-rw-r--r--shared/home-manager/neovim/lsp.nix59
5 files changed, 434 insertions, 0 deletions
diff --git a/shared/home-manager/neovim/completion.nix b/shared/home-manager/neovim/completion.nix
new file mode 100644
index 0000000..3776674
--- /dev/null
+++ b/shared/home-manager/neovim/completion.nix
@@ -0,0 +1,47 @@
+# This module sets up auto completion for Neovim.
+{pkgs, ...}: {
+ programs.neovim.plugins = with pkgs.vimPlugins; [
+ # This is the actual completion engine.
+ {
+ plugin = nvim-cmp;
+ type = "lua";
+ config = ''
+ local cmp = require("cmp")
+
+ cmp.setup({
+ mapping = cmp.mapping.preset.insert({
+ ["<C-b>"] = cmp.mapping.scroll_docs(-4),
+ ["<C-f>"] = cmp.mapping.scroll_docs(4),
+ ["<C-j>"] = cmp.mapping.select_next_item(),
+ ["<C-k>"] = cmp.mapping.select_prev_item(),
+ ["<C-Space>"] = cmp.mapping.complete(),
+ ["<C-e>"] = cmp.mapping.abort(),
+ ["<Tab>"] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
+ }),
+ sources = cmp.config.sources({
+ { name = "nvim_lsp" },
+ { name = "calc" },
+ { name = "path" },
+ { name = "buffer" },
+ }),
+ -- disable completion in comments
+ enabled = function()
+ 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
+ })
+ '';
+ }
+ # The following are plugins for the... completion plugin.
+ cmp-nvim-lsp
+ cmp-calc
+ cmp-buffer
+ cmp-path
+ ];
+}
diff --git a/shared/home-manager/neovim/default.nix b/shared/home-manager/neovim/default.nix
new file mode 100644
index 0000000..63a7564
--- /dev/null
+++ b/shared/home-manager/neovim/default.nix
@@ -0,0 +1,28 @@
+# This file contains the HM configuration options for Neovim.
+{...}: {
+ imports = [
+ ./completion.nix
+ ./editing-plugins.nix
+ ./lsp.nix
+ ];
+
+ programs.neovim = {
+ enable = true;
+
+ # Import my existing config. I've been working on this for years and when
+ # my enthusiasm for Nix eventually dies off, I want to take it with me.
+ extraConfig = builtins.readFile ./init.vim;
+
+ # Typing `vi`, `vim`, or `vimdiff` will also run neovim.
+ viAlias = true;
+ vimAlias = true;
+ vimdiffAlias = true;
+ };
+
+ # Set Neovim as the default editor.
+ home.sessionVariables.EDITOR = "nvim";
+ home.sessionVariables.VISUAL = "nvim";
+
+ # Use neovim as man pager.
+ home.sessionVariables.MANPAGER = "nvim +Man!";
+}
diff --git a/shared/home-manager/neovim/editing-plugins.nix b/shared/home-manager/neovim/editing-plugins.nix
new file mode 100644
index 0000000..23c7d63
--- /dev/null
+++ b/shared/home-manager/neovim/editing-plugins.nix
@@ -0,0 +1,26 @@
+# This module sets up and configures various miscellaneous plugins.
+# TODO: I fear this file will become the utils.lua of my Neovim configuration. Remove it!
+{pkgs, ...}: {
+ programs.neovim.plugins = [
+ {
+ plugin = pkgs.vimPlugins.vim-localvimrc;
+ type = "viml";
+ config = ''
+ let g:localvimrc_persistent = 1
+ let g:localvimrc_name = [ "local.vim", "editors/local.vim" ]
+ '';
+ }
+ {
+ plugin = pkgs.vimPlugins.vim-sneak;
+ type = "viml";
+ config = ''
+ let g:sneak#s_next = 1
+ let g:sneak#use_ic_scs = 1
+ map f <Plug>Sneak_f
+ map F <Plug>Sneak_F
+ map t <Plug>Sneak_t
+ map T <Plug>Sneak_T
+ '';
+ }
+ ];
+}
diff --git a/shared/home-manager/neovim/init.vim b/shared/home-manager/neovim/init.vim
new file mode 100644
index 0000000..eeb6920
--- /dev/null
+++ b/shared/home-manager/neovim/init.vim
@@ -0,0 +1,274 @@
+" Settings
+"""""""""""""""""""""""""""
+
+" Leave boomer mode
+set nocompatible
+
+set history=1000
+
+" Backspace in insert mode
+set backspace=indent,eol,start
+
+" Hide buffer when abandoned (you can gd away, etc)
+set hid
+
+" Searching
+" NOTE: ignorecase and smartcase must be used together (see :h 'smartcase')
+set incsearch gdefault ignorecase smartcase nohlsearch
+
+" Only auto-continue comments when i_<cr> is pressed (not n_o)
+" Must be set after :filetype-plugin-on
+filetype plugin indent on
+au FileType * setlocal fo-=o fo+=r
+
+" Enable syntax highlighting
+syn on
+
+" Colorscheme
+" au VimEnter * ++nested colorscheme ansi_linus
+
+" Persistent undo
+set undofile
+
+" Give me some thinking time, jesus!
+set timeout timeoutlen=2000
+
+" Line numbers
+set number relativenumber
+
+" Improve macro performance
+set lazyredraw
+
+" Show matching brackets
+set showmatch
+set matchtime=2
+
+set listchars=tab:>-,eol:$,space:.,trail:@,nbsp:%
+
+" Enable mouse input for all modes but visual.
+"
+" I disable mouse in visual mode so I can select text in the terminal using
+" the mouse. This is useful when copying text from a remote instance of vim
+" SSH session where "* doesn't work.
+set mouse=nicr
+
+" sussy sus the sussy sus
+set nowrap
+
+" Mappings
+"""""""""""""""""""""""""""
+
+let g:mapleader = "\<space>"
+let g:maplocalleader = "\<space>"
+
+" Some keys are hard to press with the Danish layout. Luckily, we have some
+" spare keys! Note that ctrl and esc are swapped at the OS level.
+nnoremap æ $
+nnoremap Æ 0
+
+" Switching windows
+" TODO: make this work with iTerm2 panes
+" nnoremap <c-h> <c-w><c-h>
+" nnoremap <c-j> <c-w><c-j>
+" nnoremap <c-k> <c-w><c-k>
+" nnoremap <c-l> <c-w><c-l>
+" tnoremap <c-h> <c-\><c-n><c-w><c-h>
+" tnoremap <c-j> <c-\><c-n><c-w><c-j>
+" tnoremap <c-k> <c-\><c-n><c-w><c-k>
+" tnoremap <c-l> <c-\><c-n><c-w><c-l>
+
+" Resize windows
+nnoremap + <c-w>+
+nnoremap - <c-w>-
+
+" Switching tabs
+nnoremap <silent> <leader>tt :tabnext<CR>
+nnoremap <silent> <leader>tn :tabnew<CR>
+nnoremap <silent> <leader>to :tabonly<CR>
+nnoremap <silent> <leader>tc :tabclose<CR>
+nnoremap <silent> <leader>tm :tabmove
+" Just use gt and gT
+" nnoremap <silent> <leader>tl :tabn<CR>
+" nnoremap <silent> <leader>th :tabN<CR>
+nnoremap <silent> <leader>t<S-L> :tabl<CR>
+nnoremap <silent> <leader>t<S-H> :tabr<CR>
+
+" Fast macros (qq to record)
+nnoremap Q @q
+vnoremap Q :norm! @q<cr>
+
+" Make Y act like C and D
+nnoremap <s-y> y$
+vnoremap <s-y> $y
+
+" Indent using tab key
+nnoremap <Tab> >l
+nnoremap <S-Tab> <l
+vnoremap <Tab> >gv
+vnoremap <S-Tab> <gv
+
+noremap! <C-j> <down>
+noremap! <C-k> <up>
+noremap! <C-h> <left>
+noremap! <C-l> <right>
+
+" Toggle showing 'listchars'
+nnoremap <silent> <leader>l :set list!<cr>
+
+" Escape in terminal mode
+tnoremap <esc><esc> <c-\><c-n>
+
+" Seamlessly enter/leave terminal buffer.
+tnoremap <c-w> <c-\><c-n><c-w>
+au BufEnter term://* norm! i
+
+" Join to end of line below
+" This is already used by the window switching mappings
+nnoremap <c-j> ddpkJ
+
+" Move window to the left and switch to the eastern window.
+" I do this move pretty frequently.
+nnoremap <c-w><c-w> <c-w>L<c-w>h
+
+" If the fzf executable is available, assume that the fzf plugin is going to
+" be loaded. In that case we want an easy way to load a file.
+if executable("fzf")
+ nnoremap <leader><leader> <CMD>FZF<CR>
+else
+ nnoremap <leader><leader> <CMD>echo "FZF not found!"<CR>
+endif
+
+" Define go-to-definition help pages, otherwise see the mappings in the hook
+" for LSP configuration.
+autocmd Filetype help nnoremap <buffer> gd <C-]>
+
+" Commands
+"""""""""""""""""""""""""""
+
+" Create a temporary buffer
+" NOTE: relied on by other commands
+command Temp new | setlocal buftype=nofile bufhidden=wipe noswapfile nomodified nobuflisted
+command TempTab tabnew | setlocal buftype=nofile bufhidden=wipe noswapfile nomodified nobuflisted
+
+" Reverse lines
+command! -bar -range=% Reverse <line1>,<line2>g/^/m<line1>-1|nohl
+
+" Redraw screen
+" CTRL-L mapping is used in other thing
+command Redraw norm!
+
+" Run buffer contents as vimscript
+command! -bar -range=% Run execute 'silent!' . <line1> . ',' . <line2> . 'y|@"'
+
+" Output the result of a command to the buf
+command! -nargs=+ -complete=command Output
+ \ redir => output |
+ \ silent execute <q-args> |
+ \ redir END |
+ \ tabnew |
+ \ setlocal buftype=nofile bufhidden=wipe noswapfile nobuflisted nomodified |
+ \ silent put=output |
+ \ if <q-args> =~ ':!' |
+ \ silent 1,2delete _ |
+ \ else |
+ \ silent 1,4delete _ |
+ \ endif
+
+" Copy buffer to system clipboard
+command! Copy silent w !pbcopy
+
+" Copy the location of the current file
+command! CopyDir !echo %:r | pbcopy
+
+" View in-memory changes before writing to disk
+command! DiffOnDisk
+ \ let orig_filetype=&ft |
+ \ vert new |
+ \ read ++edit # | 0d_ |
+ \ setlocal bt=nofile bh=wipe nobl noswf ro |
+ \ let &l:filetype = orig_filetype |
+ \ diffthis |
+ \ wincmd p |
+ \ diffthis
+
+command WrapItUp setlocal wrap
+ \| nnoremap <buffer> j gj
+ \| nnoremap <buffer> k gk
+ \| nnoremap <buffer> 0 g0
+ \| nnoremap <buffer> $ g$
+
+" Miscellaneous
+"""""""""""""""""""""""""""
+
+" Show the color column only if insert mode (and only if cc is set)
+augroup ShowCCInInsertMode
+ au!
+ au InsertEnter * if &tw != 0 | let &cc = &tw + 1 | endif
+ au InsertLeave * let &cc = 0
+augroup END
+
+" Auto-refresh vim config
+" au BufWritePost $XDG_CONFIG_HOME/*.{vim,lua} so %
+
+" Jump to last editing location when opening files
+au BufReadPost *
+ \ if line("'\"") > 0 && line("'\"") <= line("$") |
+ \ exe "normal! g'\"" |
+ \ endif
+
+augroup Sus
+ au!
+
+ " Add syntax groups if relevant. This conditional is compensating for
+ " the lack of negative matches in :au.
+ "
+ " See: https://vim.fandom.com/wiki/Highlight_unwanted_spaces
+ " See: https://stackoverflow.com/questions/6496778/vim-run-autocmd-on-all-filetypes-except
+ fun! s:AddSyntax()
+ if bufname() !~ 'term://\|man://'
+ " Any trailing whitespace at the end of lines.
+ syn match SusWhitespace /\s\+$/ containedin=ALL
+
+ " Any non-breaking spaces. These are generated by
+ " CMD+SPACE and deeply annoying.
+ syn match SusWhitespace /\%u00A0/ containedin=ALL
+
+ " Any characters beyond the maximum width of the text.
+ if &tw > 0
+ let reg = '\%' . (&tw + 1) . 'v.\+'
+ exe 'syn match SusWhitespace /'.reg.'/ containedin=ALL'
+ endif
+ endif
+ endfun
+
+ " Remove highligt group.
+ "
+ " Note that we have to do abit more work since the the syntax rules
+ " have changed under Vim's nose. Hopefully the perfomance
+ " characteristics don't come back to haunt us.
+ fun! s:RemoveSyntax()
+ syn clear SusWhitespace
+ syn sync fromstart
+ endfun
+
+ " Add a persistent highligt group, which matches are going to use.
+ au VimEnter,ColorScheme * hi SusWhitespace ctermbg=red guibg=red
+
+ " Create some persistent syntax highlighting groups.
+ au Syntax * call s:AddSyntax()
+
+ " When 'textwidth' changes, we may need to recalculate.
+ au OptionSet textwidth call s:RemoveSyntax()
+ \ | call s:AddSyntax()
+
+ " Temporarily remove the groups when in insert mode.
+ au InsertEnter * call s:RemoveSyntax()
+ au InsertLeave * call s:AddSyntax()
+augroup END
+
+" Allow for quick prototyping outside of NixOS/Home-Manager by loading some
+" extra configuration if relevant.
+let extra_vimrc = expand("~/extra-temporary.vimrc")
+if filereadable(extra_vimrc)
+ execute "source " . extra_vimrc
+endif
diff --git a/shared/home-manager/neovim/lsp.nix b/shared/home-manager/neovim/lsp.nix
new file mode 100644
index 0000000..bc10487
--- /dev/null
+++ b/shared/home-manager/neovim/lsp.nix
@@ -0,0 +1,59 @@
+# Installs and configures lspconfig. The actual LSPs are added in the per-language profiles.
+{pkgs, ...}: {
+ programs.neovim.plugins = [
+ {
+ plugin = pkgs.vimPlugins.nvim-lspconfig;
+ type = "lua";
+ config = ''
+ local lspconfig = require("lspconfig")
+ local util = require("lspconfig.util")
+
+ -- Mappings.
+ -- See `:help vim.diagnostic.*` for documentation on any of the below functions
+ local opts = { noremap=true, silent=true }
+ vim.keymap.set('n', '<leader>e', vim.diagnostic.open_float, opts)
+ vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts)
+ vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts)
+ vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, opts)
+
+ -- Use an on_attach function to only map the following keys
+ -- after the language server attaches to the current buffer
+ vim.api.nvim_create_autocmd("LspAttach", {
+ callback = function(args)
+ local bufnr = args.buf
+ local client = vim.lsp.get_client_by_id(args.data.client_id)
+
+ -- Enable completion triggered by <c-x><c-o>
+ if client.server_capabilities.completionProvider then
+ vim.bo[bufnr].omnifunc = "v:lua.vim.lsp.omnifunc"
+ end
+
+ -- XXX: What does this do?
+ if client.server_capabilities.definitionProvider then
+ vim.bo[bufnr].tagfunc = "v:lua.vim.lsp.tagfunc"
+ end
+
+ -- Mappings.
+ -- See `:help vim.lsp.*` for documentation on any of the below functions
+ local bufopts = { noremap=true, silent=true, buffer=bufnr }
+ vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts)
+ vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts)
+ vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts)
+ vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, bufopts)
+ vim.keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, bufopts)
+ vim.keymap.set('n', '<leader>wa', vim.lsp.buf.add_workspace_folder, bufopts)
+ vim.keymap.set('n', '<leader>wr', vim.lsp.buf.remove_workspace_folder, bufopts)
+ vim.keymap.set('n', '<leader>wl', function()
+ print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
+ end, bufopts)
+ vim.keymap.set('n', '<leader>D', vim.lsp.buf.type_definition, bufopts)
+ vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, bufopts)
+ vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, bufopts)
+ vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts)
+ vim.keymap.set('n', '<leader>f', function() vim.lsp.buf.format { async = true } end, bufopts)
+ end,
+ })
+ '';
+ }
+ ];
+}