]> src.twobees.de Git - dotfiles.git/blob - stow/nvim/.config/nvim/init.lua
c02802832b5f829ddc8c68d0395079fb313b65ef
[dotfiles.git] / stow / nvim / .config / nvim / init.lua
1 vim.g.mapleader = ' '
2 vim.g.maplocalleader = ' '
3
4 -- Install package manager
5 --    https://github.com/folke/lazy.nvim
6 --    `:help lazy.nvim.txt` for more info
7 local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim'
8 if not vim.loop.fs_stat(lazypath) then
9   vim.fn.system {
10     'git',
11     'clone',
12     '--filter=blob:none',
13     'https://github.com/folke/lazy.nvim.git',
14     '--branch=stable', -- latest stable release
15     lazypath,
16   }
17 end
18 vim.opt.rtp:prepend(lazypath)
19
20 require('lazy').setup({
21   -- NOTE: First, some plugins that don't require any configuration
22
23   'jose-elias-alvarez/null-ls.nvim',
24   'MunifTanjim/prettier.nvim',
25
26   '907th/vim-auto-save',
27
28   -- Git related plugins
29   'tpope/vim-fugitive',
30   'tpope/vim-rhubarb',
31
32   -- Detect tabstop and shiftwidth automatically
33   'tpope/vim-sleuth',
34
35
36   -- NOTE: This is where your plugins related to LSP can be installed.
37   --  The configuration is done below. Search for lspconfig to find it below.
38   {
39     -- LSP Configuration & Plugins
40     'neovim/nvim-lspconfig',
41     dependencies = {
42       -- Automatically install LSPs to stdpath for neovim
43       { 'williamboman/mason.nvim', config = true },
44       'williamboman/mason-lspconfig.nvim',
45
46       -- Useful status updates for LSP
47       -- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})`
48       { 'j-hui/fidget.nvim',       opts = {},    tag = 'legacy' },
49
50       -- Additional lua configuration, makes nvim stuff amazing!
51       'folke/neodev.nvim',
52     },
53   },
54
55   {
56     -- Autocompletion
57     'hrsh7th/nvim-cmp',
58     dependencies = {
59       'hrsh7th/cmp-nvim-lsp',
60       { 'L3MON4D3/LuaSnip', version = "2.*", build = "make install_jsregexp" },
61       'saadparwaiz1/cmp_luasnip',
62       'rafamadriz/friendly-snippets'
63     },
64   },
65
66   -- Useful plugin to show you pending keybinds.
67   { 'folke/which-key.nvim',     opts = {} },
68   {
69     -- Adds git releated signs to the gutter, as well as utilities for managing changes
70     'lewis6991/gitsigns.nvim',
71     opts = {
72       -- See `:help gitsigns.txt`
73       signs = {
74         add = { text = '+' },
75         change = { text = '~' },
76         delete = { text = '_' },
77         topdelete = { text = '‾' },
78         changedelete = { text = '~' },
79       },
80       on_attach = function(bufnr)
81         vim.keymap.set('n', '[c', require('gitsigns').prev_hunk, { buffer = bufnr, desc = 'Go to Previous Hunk' })
82         vim.keymap.set('n', ']c', require('gitsigns').next_hunk, { buffer = bufnr, desc = 'Go to Next Hunk' })
83         vim.keymap.set('n', '<leader>ph', require('gitsigns').preview_hunk, { buffer = bufnr, desc = '[P]review [H]unk' })
84       end,
85     },
86   },
87
88   { "ellisonleao/gruvbox.nvim", priority = 1000 },
89   {
90     -- Set lualine as statusline
91     'nvim-lualine/lualine.nvim',
92     -- See `:help lualine.txt`
93     opts = {
94       options = {
95         icons_enabled = false,
96         theme = 'gruvbox',
97         component_separators = '|',
98         section_separators = '',
99       },
100     },
101   },
102
103   {
104     -- Add indentation guides even on blank lines
105     'lukas-reineke/indent-blankline.nvim',
106     main = "ibl",
107     opts = { },
108   },
109
110   -- "gc" to comment visual regions/lines
111   { 'numToStr/Comment.nvim',         opts = {} },
112
113   -- Fuzzy Finder (files, lsp, etc)
114   { 'nvim-telescope/telescope.nvim', branch = '0.1.x', dependencies = { 'nvim-lua/plenary.nvim' } },
115
116   -- Fuzzy Finder Algorithm which requires local dependencies to be built.
117   -- Only load if `make` is available. Make sure you have the system
118   -- requirements installed.
119   {
120     'nvim-telescope/telescope-fzf-native.nvim',
121     -- NOTE: If you are having trouble with this installation,
122     --       refer to the README for telescope-fzf-native for more instructions.
123     build = 'make',
124     cond = function()
125       return vim.fn.executable 'make' == 1
126     end,
127   },
128
129   {
130     -- Highlight, edit, and navigate code
131     'nvim-treesitter/nvim-treesitter',
132     dependencies = {
133       'nvim-treesitter/nvim-treesitter-textobjects',
134     },
135     build = ':TSUpdate',
136   },
137
138   -- NOTE: Next Step on Your Neovim Journey: Add/Configure additional "plugins" for kickstart
139   --       These are some example plugins that I've included in the kickstart repository.
140   --       Uncomment any of the lines below to enable them.
141   -- require 'autoformat',
142   -- require 'kickstart.plugins.debug',
143
144   -- NOTE: The import below automatically adds your own plugins, configuration, etc from `lua/custom/plugins/*.lua`
145   --    You can use this folder to prevent any conflicts with this init.lua if you're interested in keeping
146   --    up-to-date with whatever is in the kickstart repo.
147   --
148   --    For additional information see: https://github.com/folke/lazy.nvim#-structuring-your-plugins
149   --
150   --    An additional note is that if you only copied in the `init.lua`, you can just comment this line
151   --    to get rid of the warning telling you that there are not plugins in `lua/custom/plugins/`.
152   -- { import = 'plugins' },
153 }, {})
154
155 -- [[ Setting options ]]
156 -- See `:help vim.o`
157
158 -- Set highlight on search
159 vim.o.hlsearch = false
160
161 -- Make line numbers default
162 vim.wo.relativenumber = true
163 vim.wo.number = true
164
165 -- Enable mouse mode
166 vim.o.mouse = 'a'
167
168 vim.opt.scrolloff = 8
169
170 -- Sync clipboard between OS and Neovim.
171 --  Remove this option if you want your OS clipboard to remain independent.
172 --  See `:help 'clipboard'`
173 vim.o.clipboard = 'unnamedplus'
174
175 -- Enable break indent
176 vim.o.breakindent = true
177
178 -- Save undo history
179 vim.o.undofile = true
180
181 -- Case insensitive searching UNLESS /C or capital in search
182 vim.o.ignorecase = true
183 vim.o.smartcase = true
184
185 -- Keep signcolumn on by default
186 vim.wo.signcolumn = 'yes'
187
188 -- Decrease update time
189 vim.o.updatetime = 250
190 vim.o.timeout = true
191 vim.o.timeoutlen = 300
192
193 -- Set completeopt to have a better completion experience
194 vim.o.completeopt = 'menuone,noselect'
195
196 -- NOTE: You should make sure your terminal supports this
197 vim.o.termguicolors = true
198
199 vim.o.background = "light" -- or "light" for light mode
200 vim.cmd([[colorscheme gruvbox]])
201
202 -- [[ Basic Keymaps ]]
203
204 -- Keymaps for better default experience
205 -- See `:help vim.keymap.set()`
206 vim.keymap.set({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
207
208 -- Remap for dealing with word wrap
209 vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true })
210 vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true })
211
212 -- [[ Highlight on yank ]]
213 -- See `:help vim.highlight.on_yank()`
214 local highlight_group = vim.api.nvim_create_augroup('YankHighlight', { clear = true })
215 vim.api.nvim_create_autocmd('TextYankPost', {
216   callback = function()
217     vim.highlight.on_yank()
218   end,
219   group = highlight_group,
220   pattern = '*',
221 })
222
223 -- [[ Configure Telescope ]]
224 -- See `:help telescope` and `:help telescope.setup()`
225 require('telescope').setup {
226   defaults = {
227     mappings = {
228       i = {
229         ['<C-u>'] = false,
230         ['<C-d>'] = false,
231       },
232     },
233   },
234 }
235
236 -- Enable telescope fzf native, if installed
237 pcall(require('telescope').load_extension, 'fzf')
238
239 -- See `:help telescope.builtin`
240 vim.keymap.set('n', '<leader>?', require('telescope.builtin').oldfiles, { desc = '[?] Find recently opened files' })
241 vim.keymap.set('n', '<leader><space>', require('telescope.builtin').buffers, { desc = '[ ] Find existing buffers' })
242 vim.keymap.set('n', '<leader>/', function()
243   -- You can pass additional configuration to telescope to change theme, layout, etc.
244   require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
245     winblend = 10,
246     previewer = false,
247   })
248 end, { desc = '[/] Fuzzily search in current buffer' })
249
250 vim.keymap.set('n', '<leader>gf', require('telescope.builtin').git_files, { desc = 'Search [G]it [F]iles' })
251 vim.keymap.set('n', '<leader>sf', require('telescope.builtin').find_files, { desc = '[S]earch [F]iles' })
252 vim.keymap.set('n', '<leader>sh', require('telescope.builtin').help_tags, { desc = '[S]earch [H]elp' })
253 vim.keymap.set('n', '<leader>sw', require('telescope.builtin').grep_string, { desc = '[S]earch current [W]ord' })
254 vim.keymap.set('n', '<leader>sg', require('telescope.builtin').live_grep, { desc = '[S]earch by [G]rep' })
255 vim.keymap.set('n', '<leader>sd', require('telescope.builtin').diagnostics, { desc = '[S]earch [D]iagnostics' })
256
257 vim.keymap.set('i', 'kj', '<Esc>')
258 vim.keymap.set("n", "<tab>", "<cmd>bn<CR>")
259 vim.keymap.set("n", "<S-tab>", "<cmd>bp<CR>")
260
261 vim.cmd [[
262 augroup jumplast
263     autocmd BufReadPost *
264           \ if line("'\"") >= 1 && line("'\"") <= line("$") && &ft !~# 'commit'
265           \ |   exe "normal! g`\""
266           \ | endif
267 augroup END
268 ]]
269
270 -- [[ Configure Treesitter ]]
271 -- See `:help nvim-treesitter`
272 require('nvim-treesitter.configs').setup {
273   -- Add languages to be installed here that you want installed for treesitter
274   ensure_installed = { 'c', 'cpp', 'go', 'lua', 'python', 'rust', 'tsx', 'typescript', 'vimdoc', 'vim', 'html',
275     'c_sharp', 'perl', 'python' },
276
277   -- Autoinstall languages that are not installed. Defaults to false (but you can change for yourself!)
278   auto_install = false,
279
280   highlight = { enable = true },
281   indent = { enable = true, disable = { 'python' } },
282   incremental_selection = {
283     enable = true,
284     keymaps = {
285       init_selection = '<c-space>',
286       node_incremental = '<c-space>',
287       scope_incremental = '<c-s>',
288       node_decremental = '<M-space>',
289     },
290   },
291   textobjects = {
292     select = {
293       enable = true,
294       lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim
295       keymaps = {
296         -- You can use the capture groups defined in textobjects.scm
297         ['aa'] = '@parameter.outer',
298         ['ia'] = '@parameter.inner',
299         ['af'] = '@function.outer',
300         ['if'] = '@function.inner',
301         ['ac'] = '@class.outer',
302         ['ic'] = '@class.inner',
303       },
304     },
305     move = {
306       enable = true,
307       set_jumps = true, -- whether to set jumps in the jumplist
308       goto_next_start = {
309         [']m'] = '@function.outer',
310         [']]'] = '@class.outer',
311       },
312       goto_next_end = {
313         [']M'] = '@function.outer',
314         [']['] = '@class.outer',
315       },
316       goto_previous_start = {
317         ['[m'] = '@function.outer',
318         ['[['] = '@class.outer',
319       },
320       goto_previous_end = {
321         ['[M'] = '@function.outer',
322         ['[]'] = '@class.outer',
323       },
324     },
325     swap = {
326       enable = true,
327       swap_previous = {
328         ['<leader>A'] = '@parameter.inner',
329       },
330       swap_next = {
331         ['<leader>a'] = '@parameter.inner',
332       },
333     },
334   },
335 }
336 -- Diagnostic keymaps
337 vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Go to previous diagnostic message' })
338 vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Go to next diagnostic message' })
339 vim.keymap.set('n', '<S-F8>', vim.diagnostic.goto_prev, { desc = 'Go to previous diagnostic message' })
340 vim.keymap.set('n', '<F8>', vim.diagnostic.goto_next, { desc = 'Go to next diagnostic message' })
341 vim.keymap.set('n', '<leader>e', vim.diagnostic.open_float, { desc = 'Open floating diagnostic message' })
342 vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostics list' })
343
344 vim.keymap.set("n", "<Leader>f", function()
345   vim.lsp.buf.format({ timeout = 10000, bufnr = vim.api.nvim_get_current_buf() })
346 end)
347 -- LSP settings.
348 --  This function gets run when an LSP connects to a particular buffer.
349 local on_attach = function(client, bufnr)
350   -- NOTE: Remember that lua is a real programming language, and as such it is possible
351   -- to define small helper and utility functions so you don't have to repeat yourself
352   -- many times.
353   -- for LSP related items. It sets the mode, buffer and description for us each time.
354   local nmap = function(keys, func, desc)
355     if desc then
356       desc = 'LSP: ' .. desc
357       vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc })
358     else
359       vim.keymap.set('n', keys, func, { buffer = bufnr })
360     end
361   end
362
363   nmap('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
364   nmap('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction')
365
366   nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition')
367   nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
368   nmap('gI', vim.lsp.buf.implementation, '[G]oto [I]mplementation')
369   nmap('<leader>D', vim.lsp.buf.type_definition, 'Type [D]efinition')
370   nmap('<leader>ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols')
371   nmap('<leader>ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols')
372
373
374
375   -- See `:help K` for why this keymap
376   nmap('K', vim.lsp.buf.hover, 'Hover Documentation')
377   nmap('<C-k>', vim.lsp.buf.signature_help, 'Signature Documentation')
378
379   -- Lesser used LSP functionality
380   nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
381   nmap('<leader>wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder')
382   nmap('<leader>wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder')
383   nmap('<leader>wl', function()
384     print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
385   end, '[W]orkspace [L]ist Folders')
386
387   -- Create a command `:Format` local to the LSP buffer
388   vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_)
389     vim.lsp.buf.format()
390   end, { desc = 'Format current buffer with LSP' })
391 end
392
393 -- Enable the following language servers
394 --  Feel free to add/remove any LSPs that you want here. They will automatically be installed.
395 --
396 --  Add any additional override configuration in the following tables. They will be passed to
397 --  the `settings` field of the server config. You must look up that documentation yourself.
398 local servers = {
399   -- clangd = {},
400   -- gopls = {},
401   -- pyright = {},
402   -- rust_analyzer = {},
403   tsserver = {},
404   eslint = {},
405   tailwindcss = {},
406   lua_ls = {
407     Lua = {
408       workspace = { checkThirdParty = false },
409       telemetry = { enable = false },
410     },
411   },
412 }
413
414 -- Setup neovim lua configuration
415 require('neodev').setup()
416
417 -- nvim-cmp supports additional completion capabilities, so broadcast that to servers
418 local capabilities = vim.lsp.protocol.make_client_capabilities()
419 capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
420
421 -- Ensure the servers above are installed
422 local mason_lspconfig = require 'mason-lspconfig'
423
424 mason_lspconfig.setup {
425   ensure_installed = vim.tbl_keys(servers),
426 }
427
428 mason_lspconfig.setup_handlers {
429   function(server_name)
430     require('lspconfig')[server_name].setup {
431       capabilities = capabilities,
432       on_attach = on_attach,
433       settings = servers[server_name],
434     }
435   end,
436 }
437
438 -- nvim-cmp setup
439 local cmp = require 'cmp'
440 local luasnip = require 'luasnip'
441 require('luasnip.loaders.from_vscode').lazy_load()
442 luasnip.config.setup {}
443
444 cmp.setup {
445   snippet = {
446     expand = function(args)
447       luasnip.lsp_expand(args.body)
448     end,
449   },
450   mapping = cmp.mapping.preset.insert {
451     ['<C-n>'] = cmp.mapping.select_next_item(),
452     ['<C-p>'] = cmp.mapping.select_prev_item(),
453     ['<C-d>'] = cmp.mapping.scroll_docs(-4),
454     ['<C-f>'] = cmp.mapping.scroll_docs(4),
455     ['<C-Space>'] = cmp.mapping.complete {},
456     ['<CR>'] = cmp.mapping.confirm {
457       behavior = cmp.ConfirmBehavior.Replace,
458       select = true,
459     },
460     ['<Tab>'] = cmp.mapping(function(fallback)
461       if cmp.visible() then
462         cmp.select_next_item()
463       elseif luasnip.expand_or_locally_jumpable() then
464         luasnip.expand_or_jump()
465       else
466         fallback()
467       end
468     end, { 'i', 's' }),
469     ['<S-Tab>'] = cmp.mapping(function(fallback)
470       if cmp.visible() then
471         cmp.select_prev_item()
472       elseif luasnip.locally_jumpable(-1) then
473         luasnip.jump(-1)
474       else
475         fallback()
476       end
477     end, { 'i', 's' }),
478   },
479   sources = {
480     { name = 'nvim_lsp' },
481     { name = 'luasnip' },
482   },
483 }
484
485
486 local null_ls = require("null-ls")
487
488 local group = vim.api.nvim_create_augroup("lsp_format_on_save", { clear = false })
489 local event = "BufWritePre" -- or "BufWritePost"
490 local async = event == "BufWritePost"
491
492 null_ls.setup({
493   timeout = 2000,
494   on_attach = on_attach
495 })
496
497
498 local prettier = require("prettier")
499
500 prettier.setup({
501   bin = 'prettierd', -- or `'prettierd'` (v0.23.3+)
502   filetypes = {
503     "css",
504     "graphql",
505     "html",
506     "javascript",
507     "javascriptreact",
508     "json",
509     "less",
510     "markdown",
511     "scss",
512     "typescript",
513     "typescriptreact",
514     "yaml",
515   },
516 })
517
518 vim.opt.diffopt = vim.opt.diffopt + "vertical"
519 vim.opt.cursorline = true
520 vim.opt.hlsearch = true
521
522 -- The line beneath this is called `modeline`. See `:help modeline`
523 -- vim: ts=2 sts=2 sw=2 et