diff --git a/nvim/init.lua b/nvim/init.lua index 88c6826..9380f49 100644 --- a/nvim/init.lua +++ b/nvim/init.lua @@ -1,72 +1,135 @@ --- Install packer +-- Leader keymaps +vim.g.mapleader = ' ' +vim.g.maplocalleader = ' ' -local install_path = vim.fn.stdpath 'data' .. '/site/pack/packer/start/packer.nvim' -local is_bootstrap = false -if vim.fn.empty(vim.fn.glob(install_path)) > 0 then - is_bootstrap = true - vim.fn.execute('!git clone https://github.com/wbthomason/packer.nvim ' .. install_path) - vim.cmd [[packadd packer.nvim]] +-- Install package manager +-- https://github.com/folke/lazy.nvim +-- `:help lazy.nvim.txt` for more info +local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim' +if not vim.loop.fs_stat(lazypath) then + vim.fn.system { + 'git', + 'clone', + '--filter=blob:none', + 'https://github.com/folke/lazy.nvim.git', + '--branch=stable', -- latest stable release + lazypath, + } end +vim.opt.rtp:prepend(lazypath) --- stylua: ignore start -require('packer').startup(function(use) - use 'wbthomason/packer.nvim' -- Package manager - - use 'tpope/vim-sleuth' -- Detect tabstop and shiftwidth automatically - use 'numToStr/Comment.nvim' -- "gc" to comment visual regions/lines - use { 'lewis6991/gitsigns.nvim', requires = { 'nvim-lua/plenary.nvim' } } -- Add git related info in the signs columns and popups - use { 'L3MON4D3/LuaSnip', requires = { 'saadparwaiz1/cmp_luasnip' } } -- Snippet Engine and Snippet Expansion - - use 'nvim-treesitter/nvim-treesitter' -- Highlight, edit, and navigate code - - use 'neovim/nvim-lspconfig' -- Collection of configurations for built-in LSP client - use 'williamboman/mason.nvim' -- Automatically install language servers to stdpath - use 'williamboman/mason-lspconfig.nvim' - use { 'hrsh7th/nvim-cmp', requires = { 'hrsh7th/cmp-nvim-lsp' } } -- Autocompletion - - use 'ggandor/leap.nvim' -- Motion plugin - use 'tpope/vim-repeat' -- Fixup dot-repeat - - use 'ibhagwan/fzf-lua' -- Performant and lightweight fzf client - use { 'junegunn/fzf', run = "./install --bin" } - - use 'nvim-lualine/lualine.nvim' -- Fancier statusline - - use 'mjlbach/onedark.nvim' -- Theme inspired by Atom - use { 'He4eT/desolate.nvim', requires = { 'rktjmp/lush.nvim' } } - - if is_bootstrap then - require('packer').sync() - end -end) --- stylua: ignore end - --- When we are bootstrapping a configuration, it doesn't --- make sense to execute the rest of the init.lua. --- --- You'll need to restart nvim, and then it will work. -if is_bootstrap then - print '==================================' - print ' Plugins are being installed' - print ' Wait until Packer completes,' - print ' then restart nvim' - print '==================================' - return -end - --- Automatically source and re-compile packer whenever you save this init.lua -local packer_group = vim.api.nvim_create_augroup('Packer', { clear = true }) -vim.api.nvim_create_autocmd('BufWritePost', { - command = 'source | PackerCompile', - group = packer_group, - pattern = vim.fn.expand '$MYVIMRC', +require('lazy').setup({ + -- Detect tabstop and shiftwidth automatically + 'tpope/vim-sleuth', + -- Backup mainstream colorscheme inspired by Atom + 'navarasu/onedark.nvim', + { -- Main colorscheme + 'He4eT/desolate.nvim', + dependencies = { + 'rktjmp/lush.nvim', + } + }, + { -- `gc` to comment visual regions/lines + 'numToStr/Comment.nvim', + opts = {}, + }, + { -- Leap motion plugin + 'ggandor/leap.nvim', + dependencies = { + 'tpope/vim-repeat', + } + }, + { -- FZF + 'ibhagwan/fzf-lua', + dependencies = { + { + 'junegunn/fzf', + build = './install --bin', + }, + }, + }, + { -- LSP Configuration & Plugins + 'neovim/nvim-lspconfig', + dependencies = { + -- Automatically install LSPs to stdpath for neovim + { + 'williamboman/mason.nvim', + config = true + }, + 'williamboman/mason-lspconfig.nvim', + -- Additional lua configuration, makes nvim stuff amazing! + 'folke/neodev.nvim', + }, + }, + { -- Autocompletion + 'hrsh7th/nvim-cmp', + dependencies = { + 'hrsh7th/cmp-nvim-lsp', + 'L3MON4D3/LuaSnip', + 'saadparwaiz1/cmp_luasnip', + }, + }, + { -- Adds git releated signs to the gutter, as well as utilities for managing changes + 'lewis6991/gitsigns.nvim', + opts = { + -- See `:help gitsigns.txt` + signs = { + add = { text = '│' }, + change = { text = '│' }, + delete = { text = '_' }, + topdelete = { text = '‾' }, + changedelete = { text = '│' }, + }, + }, + }, + { -- Set lualine as statusline + 'nvim-lualine/lualine.nvim', + -- See `:help lualine.txt` + opts = { + options = { + icons_enabled = false, + component_separators = '|', + section_separators = '', + globalstatus = true, + }, + }, + }, + { -- Highlight, edit, and navigate code + 'nvim-treesitter/nvim-treesitter', + dependencies = { + 'nvim-treesitter/nvim-treesitter-textobjects', + }, + build = ':TSUpdate', + }, +}, { + ui = { + size = { width = 0.85, height = 0.7 }, + border = 'solid', + icons = { + cmd = '[cmd]', + config = '[cfg]', + event = '[e]', + ft = '[ft]', + init = '[init]', + keys = '[key]', + plugin = '[plugin]', + runtime = '[rt]', + source = '[src]', + start = '[active]', + task = '[task]', + lazy = '[lazy]', + }, + }, }) -- [[ Setting options ]] -- See `:help vim.o` +-- Set window title vim.o.title = true vim.o.titlestring = '%F' + +-- Hide mode in cmd vim.o.showmode = false -- Set highlight on search @@ -80,8 +143,17 @@ vim.o.mouse = 'a' -- Enable break indent vim.o.breakindent = false + +-- Disable line wrapping vim.o.wrap = false + +-- Show cursorline vim.o.cursorline = true + +-- Keep signcolumn on by default +vim.wo.signcolumn = 'yes' + +-- Hide tildes on unused lines vim.o.fillchars = 'eob: ' -- Save undo history @@ -93,12 +165,20 @@ vim.o.smartcase = true -- Decrease update time vim.o.updatetime = 250 -vim.wo.signcolumn = 'yes' +vim.o.timeout = false --- Set colorscheme +-- Set completeopt to have a better completion experience +vim.o.completeopt = 'menuone,noselect' + +-- [[ Appearance ]] + +-- NOTE: You should make sure your terminal supports this vim.o.termguicolors = true + +-- Set dark background vim.o.background = 'dark' +-- Set colorscheme options vim.g.desolate_h = 0 vim.g.desolate_s = 0 vim.g.desolate_l = 70 @@ -116,20 +196,17 @@ vim.g.desolate_warning = '#ffad29' vim.g.desolate_success = '#74af68' vim.g.desolate_info = '#ffffff' -vim.cmd [[colorscheme desolate]] +-- Set colorscheme +vim.cmd.colorscheme 'desolate' --- Set completeopt to have a better completion experience -vim.o.completeopt = 'menuone,noselect' +-- Tune diagnostic signs +local signs = { Error = '■ ', Warn = '■ ', Hint = '■ ', Info = '■ ' } +for type, icon in pairs(signs) do + local hl = 'DiagnosticSign' .. type + vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl }) +end -- [[ Basic Keymaps ]] --- Set as the leader key --- See `:help mapleader` --- NOTE: Must happen before plugins are required (otherwise wrong leader will be used) -vim.g.mapleader = ' ' -vim.g.maplocalleader = ' ' - --- Escaping Terminal mode -vim.keymap.set({ 't' }, ';;', '', { silent = true }) -- Keymaps for better default experience -- See `:help vim.keymap.set()` @@ -139,6 +216,21 @@ vim.keymap.set({ 'n', 'v' }, '', '', { silent = true }) vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true }) vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true }) +-- Escaping Terminal mode +vim.keymap.set({ 't' }, ';;', '', { silent = true }) + +-- Window managment +vim.keymap.set('n', 'w', '', { remap = true }) +vim.keymap.set('n', 'k', 'w', { remap = true }) +vim.keymap.set('n', 'K', ':vs') +vim.keymap.set('n', 'q', ':b#|bd#') +vim.keymap.set('n', 'h', '') +vim.keymap.set('n', 'l', '') + +-- Copy'n'Paste +vim.keymap.set('n', 'y', ':call system("xclip -i -selection clipboard", @@)') +vim.keymap.set('v', 'y', '"+y') + -- [[ Highlight on yank ]] -- See `:help vim.highlight.on_yank()` local highlight_group = vim.api.nvim_create_augroup('YankHighlight', { clear = true }) @@ -150,229 +242,12 @@ vim.api.nvim_create_autocmd('TextYankPost', { pattern = '*', }) --- Set lualine as statusline --- See `:help lualine.txt` -require('lualine').setup { - options = { - icons_enabled = false, - component_separators = '|', - section_separators = '', - globalstatus = true, - }, -} - --- Enable Comment.nvim -require('Comment').setup() - --- Gitsigns --- See `:help gitsigns.txt` -require('gitsigns').setup { - signs = { - add = { text = '│' }, - change = { text = '│' }, - delete = { text = '_' }, - topdelete = { text = '‾' }, - changedelete = { text = '│' }, - }, -} - --- [[ Configure Treesitter ]] --- See `:help nvim-treesitter` -require('nvim-treesitter.configs').setup { - -- Add languages to be installed here that you want installed for treesitter - ensure_installed = { 'help', 'lua', 'typescript', 'tsx', 'javascript', 'vue', 'html', 'css', 'scss' }, - - highlight = { enable = true }, - indent = { enable = true }, - incremental_selection = { - enable = true, - keymaps = { - init_selection = '', - node_incremental = '', - }, - }, - rainbow = { - enable = false, - extended_mode = true, -- Highlight also non-parentheses delimiters, boolean or table: lang -> boolean - max_file_lines = 1000, -- Do not enable for files with more than 1000 lines, int - } -} - --- Window managment - -vim.keymap.set('n', 'w', '', { remap = true }) -vim.keymap.set('n', 'k', 'w', { remap = true }) -vim.keymap.set('n', 'K', ':vs') -vim.keymap.set('n', 'q', ':b#|bd#') -vim.keymap.set('n', 'h', '') -vim.keymap.set('n', 'l', '') - --- Copy'n'Paste - -vim.keymap.set('n', 'y', ':call system("xclip -i -selection clipboard", @@)') -vim.keymap.set('v', 'y', '"+y') - --- Diagnostic keymaps - -vim.keymap.set('n', '[d', vim.diagnostic.goto_prev) -vim.keymap.set('n', ']d', vim.diagnostic.goto_next) -vim.keymap.set('n', 'e', vim.diagnostic.open_float) -vim.keymap.set('n', 'E', vim.diagnostic.setloclist) - --- LSP settings. --- This function gets run when an LSP connects to a particular buffer. -local on_attach = function(_, bufnr) - -- NOTE: Remember that lua is a real programming language, and as such it is possible - -- to define small helper and utility functions so you don't have to repeat yourself - -- many times. - -- - -- In this case, we create a function that lets us more easily define mappings specific - -- for LSP related items. It sets the mode, buffer and description for us each time. - local nmap = function(keys, func, desc) - if desc then - desc = 'LSP: ' .. desc - end - - vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc }) - end - - nmap('rn', vim.lsp.buf.rename, '[R]e[n]ame') - nmap('ca', vim.lsp.buf.code_action, '[C]ode [A]tion') - nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition') - - -- See `:help K` for why this keymap - nmap('K', vim.lsp.buf.hover, 'Hover Documentation') - nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') - - -- Lesser used LSP functionality - nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') - nmap('D', vim.lsp.buf.type_definition, 'Type Definition') - nmap('ea', vim.lsp.buf.add_workspace_folder, 'Workspac[e] [A]dd Folder') - nmap('er', vim.lsp.buf.remove_workspace_folder, 'Workspac[e] [R]emove Folder') - nmap('el', function() - print(vim.inspect(vim.lsp.buf.list_workspace_folders())) - end, 'Workspac[e] [L]ist Folders') - - -- Create a command `:Format` local to the LSP buffer - vim.api.nvim_buf_create_user_command(bufnr, 'Format', vim.lsp.buf.format or vim.lsp.buf.formatting, - { desc = 'Format current buffer with LSP' }) -end - --- nvim-cmp supports additional completion capabilities -local capabilities = require('cmp_nvim_lsp').default_capabilities(vim.lsp.protocol.make_client_capabilities()) - --- Enable the following language servers -local servers = { 'tsserver', 'lua_ls' } - --- Ensure the servers above are installed -require("mason").setup {} -require("mason-lspconfig").setup { - ensure_installed = servers, -} - -for _, lsp in ipairs(servers) do - require('lspconfig')[lsp].setup { - on_attach = on_attach, - capabilities = capabilities, - } -end - -vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { - border = "solid", -}) - -local signs = { Error = "■ ", Warn = "■ ", Hint = "■ ", Info = "■ " } -for type, icon in pairs(signs) do - local hl = "DiagnosticSign" .. type - vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl }) -end - --- Example custom configuration for lua --- --- Make runtime files discoverable to the server -local runtime_path = vim.split(package.path, ';') -table.insert(runtime_path, 'lua/?.lua') -table.insert(runtime_path, 'lua/?/init.lua') - -require('lspconfig').lua_ls.setup { - on_attach = on_attach, - capabilities = capabilities, - settings = { - Lua = { - runtime = { - -- Tell the language server which version of Lua you're using (most likely LuaJIT) - version = 'LuaJIT', - -- Setup your lua path - path = runtime_path, - }, - diagnostics = { - globals = { 'vim' }, - }, - workspace = { library = vim.api.nvim_get_runtime_file('', true) }, - }, - }, -} - -require('lspconfig').tsserver.setup { - on_attach = on_attach, - capabilities = capabilities, - handlers = { - -- https://github.com/holoiii/nvim/commit/73a4db74fe463f5064346ba63870557fedd134ad - ["textDocument/definition"] = function(err, result, ...) - result = vim.tbl_islist(result) and result[1] or result - vim.lsp.handlers["textDocument/definition"](err, result, ...) - end, - } -} - --- nvim-cmp setup - -local cmp = require 'cmp' -local luasnip = require 'luasnip' - -if cmp ~= nil then - cmp.setup { - snippet = { - expand = function(args) - luasnip.lsp_expand(args.body) - end, - }, - mapping = cmp.mapping.preset.insert { - [''] = cmp.mapping.scroll_docs(-4), - [''] = cmp.mapping.scroll_docs(4), - [''] = cmp.mapping.complete({}), - [''] = cmp.mapping.confirm { - behavior = cmp.ConfirmBehavior.Replace, - select = true, - }, - [''] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_next_item() - elseif luasnip.expand_or_jumpable() then - luasnip.expand_or_jump() - else - fallback() - end - end, { 'i', 's' }), - [''] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif luasnip.jumpable(-1) then - luasnip.jump(-1) - else - fallback() - end - end, { 'i', 's' }), - }, - sources = { - { name = 'nvim_lsp' }, - { name = 'luasnip' }, - }, - } -end - --- FZF +-- [[ Configure Leap ]] +require('leap').add_default_mappings() +require('leap').opts.highlight_unlabeled_phase_one_targets = true +require('leap').opts.safe_labels = {} +-- [[ Configure fzf-lua ]] local fzf = require('fzf-lua') fzf.setup({ @@ -387,32 +262,32 @@ fzf.setup({ }, grep = { - rg_opts = "--vimgrep --smart-case --max-columns=512", + rg_opts = '--vimgrep --smart-case --max-columns=512', file_ignore_patterns = { - "^node_modules/", - "/node_modules/", - "^.git/", - "^.yarn/" + '^node_modules/', + '/node_modules/', + '^.git/', + '^.yarn/' }, }, fzf_opts = { - ['--border'] = 'none' + ['--border'] = 'none', }, fzf_colors = { - ["fg"] = { "fg", "CursorLine" }, - ["bg"] = { "bg", "Normal" }, - ["hl"] = { "fg", "Comment" }, - ["fg+"] = { "fg", "Normal" }, - ["bg+"] = { "bg", "CursorLine" }, - ["hl+"] = { "fg", "Statement" }, - ["info"] = { "fg", "PreProc" }, - ["prompt"] = { "fg", "Conditional" }, - ["pointer"] = { "fg", "Exception" }, - ["marker"] = { "fg", "Keyword" }, - ["spinner"] = { "fg", "Label" }, - ["header"] = { "fg", "Comment" }, - ["gutter"] = { "bg", "Normal" }, + ['fg'] = { 'fg', 'CursorLine' }, + ['bg'] = { 'bg', 'Normal' }, + ['hl'] = { 'fg', 'Comment' }, + ['fg+'] = { 'fg', 'Normal' }, + ['bg+'] = { 'bg', 'CursorLine' }, + ['hl+'] = { 'fg', 'Statement' }, + ['info'] = { 'fg', 'PreProc' }, + ['prompt'] = { 'fg', 'Conditional' }, + ['pointer'] = { 'fg', 'Exception' }, + ['marker'] = { 'fg', 'Keyword' }, + ['spinner'] = { 'fg', 'Label' }, + ['header'] = { 'fg', 'Comment' }, + ['gutter'] = { 'bg', 'Normal' }, }, }) @@ -420,31 +295,239 @@ local fzf_files = function() fzf.files({ fd_opts = '--no-ignore --hidden' }) end +-- fzf keymaps + vim.keymap.set({ 'n' }, 'gr', fzf.lsp_references) -vim.keymap.set({ 'n' }, 'ff', fzf.git_files) +vim.keymap.set({ 'n' }, 'fp', fzf.builtin) +vim.keymap.set({ 'n' }, 'f.', fzf.resume) + +vim.keymap.set({ 'n' }, 'b', fzf.buffers) + vim.keymap.set({ 'n' }, 'fF', fzf_files) -vim.keymap.set({ 'n' }, 'fg', fzf.live_grep) +vim.keymap.set({ 'n' }, 'ff', fzf.git_files) vim.keymap.set({ 'n' }, 'fd', fzf.git_status) -vim.keymap.set({ 'n' }, 'fp', fzf.builtin) -vim.keymap.set({ 'n' }, 'f:', fzf.command_history) -vim.keymap.set({ 'n' }, 'f/', fzf.search_history) -vim.keymap.set({ 'n' }, 'f?', fzf.keymaps) -vim.keymap.set({ 'n' }, 'f.', fzf.resume) +vim.keymap.set({ 'n' }, 'fg', fzf.live_grep) vim.keymap.set({ 'n' }, 'fw', fzf.grep_cword) vim.keymap.set({ 'n' }, 'fW', fzf.grep_cWORD) vim.keymap.set({ 'n' }, 'p', fzf.registers) - vim.keymap.set({ 'n' }, '/', fzf.blines) -vim.keymap.set({ 'n' }, 'b', fzf.buffers) +vim.keymap.set({ 'n' }, 'f?', fzf.keymaps) +vim.keymap.set({ 'n' }, 'f/', fzf.search_history) +vim.keymap.set({ 'n' }, 'f:', fzf.command_history) --- Leap Motion +-- [[ Configure Treesitter ]] +-- See `:help nvim-treesitter` +require('nvim-treesitter.configs').setup { + -- Add languages to be installed here that you want installed for treesitter + ensure_installed = { 'vim', 'vimdoc', 'lua', 'typescript', 'tsx', 'javascript', 'vue', 'html', 'css', 'scss' }, + auto_install = true, -require('leap').add_default_mappings() -require('leap').opts.highlight_unlabeled_phase_one_targets = true -require('leap').opts.safe_labels = {} + highlight = { enable = true }, + indent = { enable = true, disable = { 'python' } }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = '', + node_incremental = '', + scope_incremental = '', + node_decremental = '', + }, + }, + textobjects = { + select = { + enable = true, + lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim + keymaps = { + -- You can use the capture groups defined in textobjects.scm + ['aa'] = '@parameter.outer', + ['ia'] = '@parameter.inner', + ['af'] = '@function.outer', + ['if'] = '@function.inner', + ['ac'] = '@class.outer', + ['ic'] = '@class.inner', + }, + }, + move = { + enable = true, + set_jumps = true, -- whether to set jumps in the jumplist + goto_next_start = { + [']m'] = '@function.outer', + [']]'] = '@class.outer', + }, + goto_next_end = { + [']M'] = '@function.outer', + [']['] = '@class.outer', + }, + goto_previous_start = { + ['[m'] = '@function.outer', + ['[['] = '@class.outer', + }, + goto_previous_end = { + ['[M'] = '@function.outer', + ['[]'] = '@class.outer', + }, + }, + swap = { + enable = true, + swap_next = { + ['a'] = '@parameter.inner', + }, + swap_previous = { + ['A'] = '@parameter.inner', + }, + }, + }, +} + +-- Diagnostic keymaps +vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Go to previous diagnostic message' }) +vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Go to next diagnostic message' }) +vim.keymap.set('n', 'e', vim.diagnostic.open_float, { desc = 'Open floating diagnostic message' }) +vim.keymap.set('n', 'E', vim.diagnostic.setloclist, { desc = 'Open diagnostics list' }) + +-- [[ LSP settings ]] +-- This function gets run when an LSP connects to a particular buffer. +local on_attach = function(_, bufnr) + local nmap = function(keys, func, desc) + if desc then + desc = 'LSP: ' .. desc + end + + vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc }) + end + + -- LSP keymaps + + -- See `:help K` for why this keymap + nmap('K', vim.lsp.buf.hover, 'Hover Documentation') + nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') + + -- Basic LSP functionality + nmap('rn', vim.lsp.buf.rename, '[R]e[n]ame') + nmap('ca', vim.lsp.buf.code_action, '[C]ode [A]tion') + nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition') + + -- Lesser used LSP functionality + nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + nmap('D', vim.lsp.buf.type_definition, 'Type Definition') + + -- LSP workspace managment + nmap('ea', vim.lsp.buf.add_workspace_folder, 'Workspac[e] [A]dd Folder') + nmap('er', vim.lsp.buf.remove_workspace_folder, 'Workspac[e] [R]emove Folder') + nmap('el', function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, 'Workspac[e] [L]ist Folders') + + -- Create a command `:Format` local to the LSP buffer + vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_) + vim.lsp.buf.format() + end, { desc = 'Format current buffer with LSP' }) +end + +-- Enable the following language servers +-- Feel free to add/remove any LSPs that you want here. They will automatically be installed. +-- +-- Add any additional override configuration in the following tables. They will be passed to +-- the `settings` field of the server config. You must look up that documentation yourself. +local servers = { + tsserver = { + }, + lua_ls = { + Lua = { + workspace = { checkThirdParty = false }, + telemetry = { enable = false }, + }, + }, +} + +-- Setup neovim lua configuration +require('neodev').setup() + +-- nvim-cmp supports additional completion capabilities, so broadcast that to servers +local capabilities = vim.lsp.protocol.make_client_capabilities() +capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) + +-- Ensure the servers above are installed +local mason_lspconfig = require 'mason-lspconfig' + +mason_lspconfig.setup { + ensure_installed = vim.tbl_keys(servers), +} + +vim.lsp.handlers['textDocument/hover'] = vim.lsp.with(vim.lsp.handlers.hover, { + border = 'solid', +}) + +mason_lspconfig.setup_handlers { + function(server_name) + require('lspconfig')[server_name].setup { + capabilities = capabilities, + on_attach = on_attach, + settings = servers[server_name], + } + end, +} + +-- tsserver 'Go to definition' workaround +require('lspconfig').tsserver.setup { + on_attach = on_attach, + capabilities = capabilities, + handlers = { + -- https://github.com/holoiii/nvim/commit/73a4db74fe463f5064346ba63870557fedd134ad + ['textDocument/definition'] = function(err, result, ...) + result = vim.tbl_islist(result) and result[1] or result + vim.lsp.handlers['textDocument/definition'](err, result, ...) + end, + } +} + +-- nvim-cmp setup +local cmp = require 'cmp' +local luasnip = require 'luasnip' + +luasnip.config.setup {} + +cmp.setup { + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert { + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.complete {}, + [''] = cmp.mapping.confirm { + behavior = cmp.ConfirmBehavior.Insert, + select = true, + }, + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + else + fallback() + end + end, { 'i', 's' }), + [''] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { 'i', 's' }), + }, + sources = { + { name = 'nvim_lsp' }, + { name = 'luasnip' }, + }, +} -- The line beneath this is called `modeline`. See `:help modeline` -- vim: ts=2 sts=2 sw=2 et