diff --git a/flake.lock b/flake.lock index c9c0a48..6920092 100644 --- a/flake.lock +++ b/flake.lock @@ -91,16 +91,16 @@ ] }, "locked": { - "lastModified": 1634544068, - "narHash": "sha256-RlRQBaAHfdWqfRyHdWuDPMkplBTYwuyDQqDcNbP/Sog=", - "owner": "nix-community", + "lastModified": 1635938902, + "narHash": "sha256-OBNfFnozDdpLrvQpjkpTvWhVzSHAhz1INALKyK7q2vk=", + "owner": "sbruder", "repo": "home-manager", - "rev": "ff2bed9dac84fb202bbb3c49fdcfe30c29d0b12f", + "rev": "d2d1f2f7f1bc53984f1d9932b4ad131a95032db2", "type": "github" }, "original": { - "owner": "nix-community", - "ref": "release-21.05", + "owner": "sbruder", + "ref": "release-21.05-neovim-lua", "repo": "home-manager", "type": "github" } diff --git a/flake.nix b/flake.nix index de03f54..c3975cb 100644 --- a/flake.nix +++ b/flake.nix @@ -7,7 +7,8 @@ nixpkgs.url = "github:nixos/nixpkgs/nixos-21.05"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; - home-manager.url = "github:nix-community/home-manager/release-21.05"; + # TODO 21.11: Switch to upstream + home-manager.url = "github:sbruder/home-manager/release-21.05-neovim-lua"; home-manager.inputs.nixpkgs.follows = "nixpkgs"; krops.url = "github:Mic92/krops"; diff --git a/users/simon/modules/neovim/UltiSnips/nix.snippets b/users/simon/modules/neovim/UltiSnips/nix.snippets deleted file mode 100644 index 5e9ad55..0000000 --- a/users/simon/modules/neovim/UltiSnips/nix.snippets +++ /dev/null @@ -1,35 +0,0 @@ -snippet sha256 "dummy sha256 hash" -sha256 = "0000000000000000000000000000000000000000000000000000"; -endsnippet - -snippet unpackPhase "unpackPhase template" -unpackPhase = '' - runHook preUnpack - $1 - runHook postUnpack -''; -endsnippet - -snippet configurePhase "configurePhase template" -configurePhase = '' - runHook preConfigure - $1 - runHook postConfigure -''; -endsnippet - -snippet buildPhase "buildPhase template" -buildPhase = '' - runHook preBuild - $1 - runHook postBuild -''; -endsnippet - -snippet installPhase "installPhase template" -installPhase = '' - runHook preInstall - $1 - runHook postInstall -''; -endsnippet diff --git a/users/simon/modules/neovim/UltiSnips/rust.snippets b/users/simon/modules/neovim/UltiSnips/rust.snippets deleted file mode 100644 index bd23a3b..0000000 --- a/users/simon/modules/neovim/UltiSnips/rust.snippets +++ /dev/null @@ -1,7 +0,0 @@ -snippet disp "Display trait implentation" -impl fmt::Display for ${1:Struct} { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "${2}", ${3}) - } -}${0} -endsnippet diff --git a/users/simon/modules/neovim/UltiSnips/tex.snippets b/users/simon/modules/neovim/UltiSnips/tex.snippets deleted file mode 100644 index 64359ba..0000000 --- a/users/simon/modules/neovim/UltiSnips/tex.snippets +++ /dev/null @@ -1,19 +0,0 @@ -extends tex - -snippet s "Section" b -\section{$1} - - -endsnippet - -snippet ss "Subsection" b -\subsection{$1} - - -endsnippet - -snippet sss "Subsubsection" b -\subsubsection{$1} - - -endsnippet diff --git a/users/simon/modules/neovim/UltiSnips/texmath.snippets b/users/simon/modules/neovim/UltiSnips/texmath.snippets deleted file mode 100644 index 13c76a1..0000000 --- a/users/simon/modules/neovim/UltiSnips/texmath.snippets +++ /dev/null @@ -1,23 +0,0 @@ -extends texmath - -snippet qf "Quadratic formula (user is responsible for parentheses)" w -\frac{-${2:b} \pm \sqrt{$2^2 - 4 \cdot ${1:a} \cdot ${3:c}}}{2 \cdot $1}$0 -endsnippet - -snippet aligned "aligned environment (in math mode)" w -\begin{aligned} - $1 &= $0 \\\\ -\end{aligned} -endsnippet - -snippet si "Insert SI unit (only works with simple numbers)" w -\SI{${1:amount}}{${2:unit}} -endsnippet - -snippet · "Insert multiplication sign" A -\cdot $0 -endsnippet - -snippet // "Fraction" iA -\frac{$1}{$2}$0 -endsnippet diff --git a/users/simon/modules/neovim/default.nix b/users/simon/modules/neovim/default.nix index ab1c29b..640a9f4 100644 --- a/users/simon/modules/neovim/default.nix +++ b/users/simon/modules/neovim/default.nix @@ -1,9 +1,6 @@ { config, lib, nixosConfig, pkgs, ... }: let - languageClientSettings = pkgs.writeText "LanguageClient.json" (lib.generators.toJSON { } { - rust.clippy_preference = "on"; - }); - rainbow_csv = pkgs.vimUtils.buildVimPluginFrom2Nix rec { + rainbow_csv = pkgs.unstable.vimUtils.buildVimPluginFrom2Nix rec { name = "rainbow_csv"; src = pkgs.fetchFromGitHub { owner = "mechatroner"; @@ -14,7 +11,7 @@ let meta.license = lib.licenses.mit; }; - vim-openscad = pkgs.vimUtils.buildVimPluginFrom2Nix rec { + vim-openscad = pkgs.unstable.vimUtils.buildVimPluginFrom2Nix rec { name = "vim-openscad"; src = pkgs.fetchFromGitHub { owner = "sirtaj"; @@ -25,7 +22,7 @@ let meta.license = lib.licenses.publicDomain; }; - Vim-Jinja2-Syntax = pkgs.vimUtils.buildVimPluginFrom2Nix rec { + Vim-Jinja2-Syntax = pkgs.unstable.vimUtils.buildVimPluginFrom2Nix rec { name = "Vim-Jinja2-Syntax"; src = pkgs.fetchFromGitHub { owner = "Glench"; @@ -36,279 +33,77 @@ let meta.license = lib.licenses.bsd3; }; - pyls-black = pkgs.python3Packages.buildPythonPackage rec { - pname = "pyls-black"; - version = "0.4.6"; - - src = pkgs.python3Packages.fetchPypi { - inherit pname version; - sha256 = "0qsnjrpqhws7ajwg5y01fcpn1y6jc89ql61rpaknwqq5srg0ww1k"; - }; - - propagatedBuildInputs = with pkgs.python3Packages; [ - black - toml - ]; - - # circular dependency - doCheck = false; - postPatch = '' - sed -i 's/python-language-server; //' setup.cfg - ''; - - meta.license = lib.licenses.mit; - }; - pyls = (pkgs.python3Packages.python-language-server.override { - providers = [ - # everything except autopep8 and yapf (conflicts with black) - "mccabe" - "pycodestyle" - "pydocstyle" - "pyflakes" - "pylint" - "rope" - ]; - }).overrideAttrs (oldAttrs: oldAttrs // { - propagatedBuildInputs = oldAttrs.propagatedBuildInputs ++ [ - pyls-black - ]; - }); in { programs.neovim = { enable = true; + package = pkgs.unstable.neovim-unwrapped; vimAlias = true; - extraConfig = /* vim */ '' - " Basic display - set number - set colorcolumn=80 - - " Persistent undo - set undofile - set undolevels=4096 - set undoreload=16384 - - " Search - set ignorecase - - " Hide search when enter is pressed - nnoremap :nohlsearch - - " Autoload settings from file - set modeline - - " Use system clipboard - set clipboard=unnamedplus - - " Support more file encodings - set fileencodings=ucs-bom,utf-8,default,sjis,latin1 - - " Scroll before reaching top/bottom - set scrolloff=5 - - " Conceal when line is not active - set conceallevel=1 - - " Just hide buffer instead of unloading - set hidden - - " Remap leader key - let mapleader = "," - - " Close terminal with double-Esc - tnoremap - - " Sort in visual mode - vnoremap s :sort - - " Jump to the last position - au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") - \| exe "normal! g`\"" | endif - - set background=dark - silent! colorscheme solarized - - " Set unknown filetypes - autocmd BufRead,BufNewFile *.vpy set filetype=python - - " Filetype specific properties - autocmd Filetype arduino setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype bib setlocal ts=1 sw=1 sts=1 expandtab - autocmd Filetype c setlocal ts=4 sw=4 sts=4 expandtab - autocmd Filetype cpp setlocal ts=4 sw=4 sts=4 expandtab - autocmd Filetype css setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype dockerfile setlocal ts=4 sw=4 sts=4 expandtab - autocmd Filetype dot setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype gitcommit setlocal colorcolumn=72 - autocmd Filetype go setlocal ts=4 sw=4 sts=4 - autocmd Filetype haskell setlocal ts=4 sw=4 sts=4 expandtab - autocmd Filetype html setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype jinja.html setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype javascript setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype jinja setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype json setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype lua setlocal ts=4 sw=4 sts=4 expandtab - autocmd Filetype markdown setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype openscad setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype python setlocal ts=4 sw=4 sts=4 expandtab - autocmd Filetype sass setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype scss setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype sh setlocal ts=4 sw=4 sts=4 - autocmd Filetype tex setlocal ts=1 sw=1 sts=1 expandtab - autocmd Filetype toml setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype vim setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype vue setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype xml setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype yaml setlocal ts=2 sw=2 sts=2 expandtab - autocmd Filetype zsh setlocal ts=4 sw=4 sts=4 expandtab - - " Markdown syntax highlighting in code blocks - let g:markdown_fenced_languages = [ - \'bash=sh', - \'c', - \'cpp', - \'css', - \'haskell', - \'html', - \'javascript', - \'json', - \'nix', - \'python', - \'rust', - \'sh', - \'tex', - \] + extraConfig = '' + lua require('init') ''; - plugins = (with pkgs.vimPlugins; [ - { - plugin = deoplete-nvim; - config = /* vim */ '' - let g:deoplete#enable_at_startup = 1 - ''; - } - editorconfig-vim - fzf-vim - { - plugin = nerdtree; - config = /* vim */ '' - map N :NERDTreeTabsToggle - map n :NERDTreeFocusToggle - ''; - } - nerdtree-git-plugin - { - plugin = rust-vim; - config = /* vim */ '' - let g:rustfmt_autosave_if_config_present = 1 - let g:rust_fold = 1 - map rt :RustTest - ''; - } - { - plugin = tagbar; - config = /* vim */ '' - nmap :TagbarToggle - ''; - } - { - plugin = ultisnips; - config = /* vim */ '' - let g:UltiSnipsSnippetDirectories = [ '${./UltiSnips}' ] - let g:UltiSnipsExpandTrigger = '' - let g:UltiSnipsJumpForwardTrigger = '' - let g:UltiSnipsJumpBackwardTrigger = '' - ''; - } - { - plugin = vim-airline; - config = /* vim */ '' - let g:airline_powerline_fonts = 1 - let g:airline_solarized_bg='dark' - let g:airline_theme='solarized' - ''; - } - vim-airline-themes - vim-better-whitespace - vim-colors-solarized - vim-devicons + extraPackages = with pkgs; [ + unzip # zip.vim + ] ++ (lib.optionals nixosConfig.sbruder.full [ + gopls + haskell-language-server + rnix-lsp + rust-analyzer + # very ugly, but required to make non-yapf/autopep8 formatters work + ((unstable.python3.override { + packageOverrides = _: prev: { + python-lsp-server = prev.python-lsp-server.override { + withAutopep8 = false; + withYapf = false; + }; + }; + }).withPackages (ps: with ps; [ + pyls-isort + pylsp-mypy + python-lsp-black + python-lsp-server + ])) + ]); + plugins = with pkgs.unstable.vimPlugins; [ + Vim-Jinja2-Syntax + cmp-buffer + cmp-nvim-lsp + cmp-path + cmp_luasnip + diffview-nvim + editorconfig-nvim + friendly-snippets + gitsigns-nvim + lspkind-nvim + lualine-lsp-progress + lualine-nvim + luasnip + neogit + nvim-cmp + nvim-lspconfig + nvim-solarized-lua + nvim-web-devicons + plenary-nvim + rainbow_csv + rust-vim + tagbar + telescope-nvim + trouble-nvim vim-fugitive - vim-nerdtree-tabs + vim-markdown vim-nix + vim-openscad vim-snippets vim-toml - { - plugin = vimtex; - config = /* vim */ '' - let g:tex_flavor='latex' - let g:vimtex_view_method='zathura' - let g:tex_conceal='abdmg' - " this disables some helful warnings that often have a reason why I ignore them - let g:vimtex_quickfix_ignore_filters = [ - \'Underfull \\hbox (badness [0-9]*) in ', - \'Overfull \\hbox ([0-9]*.[0-9]*pt too wide) in ', - \'Overfull \\vbox ([0-9]*.[0-9]*pt too high) detected ', - \'Package hyperref Warning: Token not allowed in a PDF string', - \'Package typearea Warning: Bad type area settings!', - \] - " When using math environments vim does not know if if it currently is in one - " or outside of one unless it parses the file from the start. Parsing the - " file from the start each time fixes this but leads to a performance drop - " (depending on the number of lines). - " Also, somehow using FileType tex does not work, so this will enable slow - " syntax highlighting everywhere once a *.tex file is opened. - autocmd BufEnter *.tex syntax sync fromstart - ''; - } - ] ++ (lib.optionals nixosConfig.sbruder.full [ - { - plugin = LanguageClient-neovim; - config = /* vim */ '' - let g:LanguageClient_serverCommands = { - \ 'rust': ['${pkgs.rust-analyzer}/bin/rust-analyzer'], - \ 'go': ['${pkgs.gopls}/bin/gopls'], - \ 'python': ['${pyls}/bin/pyls'], - \ 'typescript': ['${pkgs.nodePackages.javascript-typescript-langserver}/bin/javascript-typescript-stdio'], - \ 'javascript': ['${pkgs.nodePackages.javascript-typescript-langserver}/bin/javascript-typescript-stdio'], - \ 'haskell': ['${pkgs.haskellPackages.haskell-language-server}/bin/haskell-language-server', '--lsp'], - \ 'nix': ['${pkgs.rnix-lsp}/bin/rnix-lsp'], - \ } - - let g:LanguageClient_loggingFile = '${config.xdg.dataHome}/nvim/LanguageClient.log' - let g:LanguageClient_settingsPath = [ - \'${languageClientSettings}', - \'.vim/coc-settings.json', - \'.vscode/settings.json', - \'.vim/settings.json', - \] - - let g:LanguageClient_selectionUI='fzf' - - function LC_maps() - if has_key(g:LanguageClient_serverCommands, &filetype) - nnoremap :call LanguageClient_contextMenu() - nnoremap K :call LanguageClient#textDocument_hover() - nnoremap gd :call LanguageClient#textDocument_definition() - nnoremap :call LanguageClient#textDocument_rename() - nnoremap f :call LanguageClient#textDocument_formatting() - nnoremap ca :call LanguageClient#textDocument_codeAction() - " disable since it breaks most code - "set formatexpr=LanguageClient#textDocument_rangeFormatting_sync() - endif - endfunction - - autocmd FileType * call LC_maps() - ''; - } - ])) ++ [ - Vim-Jinja2-Syntax - rainbow_csv - vim-openscad + vimtex + which-key-nvim ]; }; - home.sessionVariables.EDITOR = "nvim"; + xdg.configFile = { + "nvim/lua/init.lua".source = ./init.lua; + "nvim/lua/snippets.lua".source = pkgs.callPackage ./snippets.nix { }; + }; - home.packages = with pkgs; [ - unzip # required for zip.vim - ]; + home.sessionVariables.EDITOR = "nvim"; } diff --git a/users/simon/modules/neovim/init.lua b/users/simon/modules/neovim/init.lua new file mode 100644 index 0000000..9124ebb --- /dev/null +++ b/users/simon/modules/neovim/init.lua @@ -0,0 +1,290 @@ +-- Aliases +local cmd = vim.cmd +local fn = vim.fn +local g = vim.g +local opt = vim.opt +local map = vim.api.nvim_set_keymap + +-- Helpers +local function noremap(mode, lhs, rhs, opts) + local options = { noremap = true } + if opts then options = vim.tbl_extend('force', options, opts) end + vim.api.nvim_set_keymap(mode, lhs, rhs, options) +end + +local function associate_filetype(glob, ft) + cmd('autocmd BufRead,BufNewFile ' .. glob .. ' set filetype=' .. ft) +end +local function setup_filetype(ft, tab, expandtab, opts) + local cmdline = 'autocmd Filetype ' .. ft .. ' setlocal' + if tab then cmdline = cmdline .. ' ts=' .. tab .. ' sw=' .. tab .. ' sts=' .. tab end + if opts then cmdline = cmdline .. ' ' .. opts end -- FIXME: opts should be a table + cmd(cmdline) +end + +local has_words_before = function() + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match('%s') == nil +end + +-- Display +opt.number = true -- line numbers +opt.colorcolumn = { '80' } -- line at 80 characters +opt.scrolloff = 5 -- context at top/bottom +opt.sidescrolloff = 8 -- context on the left/right side +opt.conceallevel = 1 -- conceal inactive lines + +opt.termguicolors = true +cmd('colorscheme solarized') + +-- Undo +opt.undofile = true +opt.undolevels = 4096 +opt.undoreload = 16384 + +-- Behaviour +opt.hidden = true -- background buffers +opt.expandtab = true -- spaces instead of tabs by default +opt.smartindent = true -- automatic indentation +opt.tabstop = 2 -- tabs have width of 2 by default +opt.shiftwidth = 0 -- shift width = tab width +opt.joinspaces = false -- no double spaces when joining +opt.clipboard = 'unnamedplus' -- use system clipboard +opt.modeline = true + +cmd([[ +autocmd BufReadPost * if line("'\"") >= 1 && line("'\"") <= line("$") && &ft !~# 'commit' | exe "normal! g`\"" | endif +]]) -- see :h last-position-jump + +-- Search +opt.ignorecase = true -- ignore case +opt.smartcase = true -- but only with all-lowercase searches + +-- Highlight trailing spaces +cmd([[autocmd BufWinEnter * match errorMsg /\s\+$\| \+\ze\t/]]) + +-- Mappings +g.mapleader = ',' + +noremap('n', '', ':nohlsearch', { silent = true }) -- hide highlights on enter +noremap('v', 's', ':sort') -- sort in visual mode +noremap('t', '', [[]]) + +-- Filetypes +associate_filetype('*.vpy', 'python') -- vapoursynth scripts + +setup_filetype('bib', 1) +setup_filetype('c', 4) +setup_filetype('cpp', 4) +setup_filetype('dockerfile', 4) +setup_filetype('gitcommit', nil, 'colorcolumn=72') +setup_filetype('go', 4, 'noexpandtab') +setup_filetype('haskell', 4) +setup_filetype('lua', 4) +setup_filetype('python', 4) +setup_filetype('sh', 4, 'noexpandtab') +setup_filetype('tex', 1) +setup_filetype('zsh', 4) + +-- Plugins + +-- Status line +local custom_solarized_lualine = require('lualine.themes.solarized') +-- default colours are very hard to read +custom_solarized_lualine.normal.b = { fg = '#eee8d5', bg = '#586e75' } +require('lualine').setup { + options = { + theme = custom_solarized_lualine, + }, + sections = { + lualine_c = { + 'filename', + 'lsp_progress', + }, + }, +} + +-- Tagbar +noremap('n', '', ':TagbarToggle') + +-- Keymap popup +require('which-key').setup {} + +-- Icons +require('nvim-web-devicons').setup { default = true } + +-- Git +require('plenary') -- otherwise neogit SIGABRTs +require('neogit').setup { + disable_commit_confirmation = true, + integrations = { + diffview = true, + }, +} +cmd([[ +hi NeogitNotificationInfo guifg=#268bd2 +hi NeogitNotificationWarning guifg=#cb4b16 +hi NeogitNotificationError guifg=#dc322f +]]) +require('gitsigns').setup() +require('diffview').setup {} + +-- Fuzzy finder/option picker +require('telescope').setup {} + +-- Completion/Snippets +local cmp = require('cmp') +local lspkind = require('lspkind') +local luasnip = require('luasnip') +luasnip.config.set_config { + enable_autosnippets = true, +} + +require('snippets') + +cmp.setup { + snippet = { + expand = function(args) 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' }), + [''] = cmp.mapping({ i = cmp.mapping.abort(), c = cmp.mapping.close() }), + [''] = cmp.mapping.confirm({ select = false }), + + [''] = cmp.mapping(function(fallback) + if luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + elseif cmp.visible() then + cmp.select_next_item() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { 'i', 's' }), + + [''] = cmp.mapping(function(fallback) + if luasnip.jumpable(-1) then + luasnip.jump(-1) + elseif cmp.visible() then + cmp.select_prev_item() + else + fallback() + end + end, { 'i', 's' }), + }, + sources = cmp.config.sources({ + { name = 'nvim_lsp' }, + { name = 'luasnip' }, + { name = 'path' } + }, { + { + name = 'buffer', + opts = { + keyword_pattern = [[\k\+]], -- allow unicode multibyte characters + }, + } + }), + formatting = { + format = lspkind.cmp_format({ + with_text = false, + maxwidth = 50, + }) + }, +} + +-- LSP +local lsp = require('lspconfig') + +vim.lsp.handlers['textDocument/publishDiagnostics'] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + update_in_insert = true, -- update suggestions in insert mode +}) + +for type, icon in pairs({ Error = ' ', Warning = ' ', Hint = ' ', Information = ' ' }) do + local hl = 'LspDiagnosticsSign' .. type + fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl }) +end + +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 + + buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc') + + local opts = { noremap = true, silent = true } + + buf_set_keymap('n', 'gD', 'lua vim.lsp.buf.declaration()', opts) + buf_set_keymap('n', 'gd', 'lua require("telescope.builtin").lsp_definitions()', opts) + buf_set_keymap('n', 'K', 'lua vim.lsp.buf.hover()', opts) + buf_set_keymap('n', 'gi', 'lua require("telescope.builtin").lsp_implementations()', 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 require("telescope.builtin").lsp_type_definitions()', opts) + buf_set_keymap('n', 'rn', 'lua vim.lsp.buf.rename()', opts) + buf_set_keymap('n', 'ca', 'lua require("telescope.builtin").lsp_code_actions()', opts) + buf_set_keymap('n', 'gr', 'lua vim.lsp.buf.references()', opts) + buf_set_keymap('n', 'd', '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 + +lsp.gopls.setup { + on_attach = on_attach, +} +lsp.hls.setup { + on_attach = on_attach, + root_dir = lsp.util.root_pattern('*.cabal', 'stack.yaml', 'cabal.project', 'package.yaml', 'hie.yaml', '.git'), +} +lsp.pylsp.setup { + on_attach = on_attach, +} +lsp.rnix.setup { + on_attach = on_attach, +} +lsp.rust_analyzer.setup { + on_attach = on_attach, + settings = { + ['rust-analyzer'] = { + checkOnSave = { + command = 'clippy', + }, + }, + }, +} + +require('trouble').setup {} + +-- VimTeX +g.tex_flavor = 'latex' +g.vimtex_view_method = 'zathura' +g.tex_conceal = 'abdmg' + +-- this disables some helful warnings that often have a reason why I ignore them +g.vimtex_quickfix_ignore_filters = { + [[Underfull \\hbox (badness [0-9]*) in ]], + [[Overfull \\hbox ([0-9]*.[0-9]*pt too wide) in ]], + [[Overfull \\vbox ([0-9]*.[0-9]*pt too high) detected ]], + [[Package hyperref Warning: Token not allowed in a PDF string]], + [[Package typearea Warning: Bad type area settings!]], +} + +-- When using math environments vim does not know if if it currently is in one or outside of one +-- unless it parses the file from the start. +-- Parsing the file from the start each time fixes this +-- but leads to a performance drop (depending on the number of lines). +-- Also, somehow using FileType tex does not work, so this will enable slow syntax highlighting +-- everywhere once a *.tex file is opened. +cmd([[autocmd BufEnter *.tex syntax sync fromstart]]) + +-- rust.vim +g.rustfmt_autosave_if_config_present = 1 +g.rust_fold = 1 +noremap('n', 'rt', ':RustTest') + +-- Markdown +g.vim_markdown_folding_disabled = 1 diff --git a/users/simon/modules/neovim/snippets.nix b/users/simon/modules/neovim/snippets.nix new file mode 100644 index 0000000..f07b3a0 --- /dev/null +++ b/users/simon/modules/neovim/snippets.nix @@ -0,0 +1,88 @@ +{ lib, pkgs }: +let + mkSnippet = prefix: description: body: mkSnippet' prefix description body { }; + mkSnippet' = prefix: description: body: { autotrigger ? false }: { + inherit prefix description body; + luasnip = { + inherit autotrigger; + }; + }; + + snippets = { + nix = { + Sha256Dummy = mkSnippet "sha256" "Dummy SHA256 hash" "sha256 = \"0000000000000000000000000000000000000000000000000000\";"; + } // (lib.mapAttrs + (name: _: + let + upperName = (lib.toUpper (builtins.substring 0 1 name)) + + (builtins.substring 1 (builtins.stringLength name - 1) name); + in + mkSnippet "${name}Phase" "${name}Phase skeleton" '' + runHook pre${upperName} + $1 + runHook post${upperName}'') + (builtins.listToAttrs + (map + (name: lib.nameValuePair name { }) + [ "unpack" "configure" "build" "install" ]))); + rust = { + DisplayTrait = mkSnippet "disp" "Display trait implentation" '' + impl fmt::Display for ''${1:Struct} { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "$2", $3) + } + }$0''; + }; + tex = { + Section = mkSnippet "s" "Section" '' + \section{$1} + + ''; + SubSection = mkSnippet "ss" "Subsection" '' + \subsection{$1} + + ''; + SubSubSection = mkSnippet "sss" "Subsubsection" '' + \subsubsection{$1} + + ''; + # Math + QuadraticFormula = mkSnippet + "qf" + "Quadratic formula (user is responsible for parentheses)" + ''\frac{-''${2:b} \pm \sqrt{$2^2 - 4 \cdot ''${1:a} \cdot ''${3:c}}}{2 \cdot $1}$0''; + AlignedEnv = mkSnippet "aligned" "aligned environment (in math mode)" '' + \begin{aligned} + $1 &= $0 \\\\ + \end{aligned}''; + SiUnit = mkSnippet + "si" + "Insert SI unit (only works with simple numbers)" + ''\SI{''${1:amount}}{''${2:unit}}''; + MultiplicationSign = mkSnippet' "·" "Insert multiplication sign" ''\cdot $0'' { autotrigger = true; }; + Fraction = mkSnippet' "//" "Fraction" ''\frac{$1}{$2}$0'' { autotrigger = true; }; + }; + }; + + snippetsIndex = pkgs.writeTextDir "package.json" (builtins.toJSON { + contributes.snippets = lib.mapAttrs + (id: language: { inherit language; path = "./snippets/${id}.json"; }) + { + nix = [ "nix" ]; + rust = [ "rust" ]; + tex = [ "tex" ]; + }; + }); + + snippetsDir = pkgs.symlinkJoin { + name = "luasnip-snippets"; + paths = (lib.mapAttrsToList + (ft: content: pkgs.writeTextDir "snippets/${ft}.json" (builtins.toJSON content)) + snippets) ++ (lib.singleton snippetsIndex); + }; +in +pkgs.writeText "snippets.lua" '' + require("luasnip/loaders/from_vscode").load({ paths = { '${snippetsDir}' } }) + + require("luasnip/loaders/from_vscode").lazy_load() -- other snippets +''