diff --git a/init.lua b/init.lua index 78f03e0..56cd268 100644 --- a/init.lua +++ b/init.lua @@ -2,7 +2,7 @@ vim.loader.enable() ---- Built in settings ---- --- Create a convenient aliases +-- Create convenient aliases local o = vim.o local g = vim.g local fn = vim.fn @@ -29,7 +29,7 @@ o.hidden = true -- Allow buffers to not be attached to a window o.linebreak = true -- Enable word-wrapping at the end of visual lines o.breakindent = true -- preserve indentention on lines continuing from a wrap opt.breakindentopt = { - sbr = true -- Line break character should appear before virtual indentention + 'sbr' -- 'showbreak' character should appear before virtual indentention } o.hlsearch = true -- Highlight search results o.scrolloff = 5 -- Margin between cursor and screen top/bottom @@ -43,6 +43,7 @@ o.foldlevel = 99 -- Keep all folds open o.foldlevelstart = 99 o.foldenable = true -- Don't disable folds o.conceallevel = 2 -- Hide concealed text, use replacement if defined +o.sbr = '┆' opt.listchars = { -- Symbols for whitespace chars when 'list' is enabled tab = '🭰 ', trail = '-', @@ -122,60 +123,58 @@ local function zoom_out() zoom(-1) end --- Convenience keybindings -do - -- which-key might not be available yet - local ok, which_key = pcall(require, 'which-key') - if ok then - which_key.register { - ['!'] = {'copen', 'Quickfix window'}, - [''] = {'set number! relativenumber!', 'Toggle relative numbers'}, - [''] = {'set number!', 'Toggle line numbers'}, - [''] = {'h', 'Go to the left window'}, - [''] = {'l', 'Go to the right window'}, - [''] = {'j', 'Go to the up window'}, - [''] = {'k', 'Go to the down window'}, - ['+'] = {zoom_in, "Zoom in"}, - ['-'] = {zoom_out, "Zoom out"}, - ['q'] = { - name = 'Quickfix', - q = {'copen', 'Quickfix list'}, - c = {'cclose', 'Close quickfix'}, - n = {'cnext', 'Next quickfix'}, - p = {'cprev', 'Previous quickfix'}, - }, - ['c'] = {'vert te', 'Terminal (vsplit)'}, - ['C'] = {'tab te', 'Terminal (tab)'}, - ['ZD'] = {'bdelete', 'Delete buffer'}, - } +vim.keymap.set('n', '!', 'copen', { desc = 'Quickfix window' }) +vim.keymap.set('n', '', 'set number! relativenumber!', { desc = 'Toggle relative numbers' }) +vim.keymap.set('n', '', 'set number!', { desc = 'Toggle line numbers' }) +vim.keymap.set('n', '', 'set list!', { desc = 'Annotate whitespace' }) +vim.keymap.set('n', '', 'h', { desc = 'Go to the left window' }) +vim.keymap.set('n', '', 'l', { desc = 'Go to the right window' }) +vim.keymap.set('n', '', 'j', { desc = 'Go to the up window' }) +vim.keymap.set('n', '', 'k', { desc = 'Go to the down window' }) +vim.keymap.set('n', '' , zoom_in, { desc = 'Zoom in' }) +vim.keymap.set('n', '' , zoom_out, { desc = 'Zoom out' }) +vim.keymap.set('n', '', function() + local ok, notify = pcall(require, 'notify') + if ok then notify.dismiss {} end + vim.lsp.buf.clear_references() + vim.cmd('nohlsearch|diffupdate|normal! ') +end, { desc = 'Clear' }) - which_key.register { [''] = {function() - local ok, notify = pcall(require, 'notify') - if ok then - notify.dismiss {} - end - vim.lsp.buf.clear_references() - vim.cmd('nohlsearch|diffupdate|normal! ') - end, 'Clear'} } - - if workman then - which_key.register { - j = {'n', 'Next search match'}, - k = {'e', 'End of word'}, - n = {'gj', 'Down'}, - e = {'gk', 'Up'}, - } - else - which_key.register { - j = {'gj', 'Down'}, - k = {'gk', 'Up'} - } +-- Quickfix mappings +local function quickfix_toggle() + for _, win in pairs(vim.fn.getwininfo()) do + if win.quickfix == 1 then + vim.cmd.cclose() + return end end + vim.cmd.copen() end -vim.cmd [[ -tnoremap -]] +vim.keymap.set('n', 'qq', quickfix_toggle, { desc = 'Open' }) +vim.keymap.set('n', 'qc', 'cclose', { desc = 'Close' }) +vim.keymap.set('n', 'qj', 'cnext', { desc = 'Next' }) +vim.keymap.set('n', 'qk', 'cprev', { desc = 'Previous' }) +vim.keymap.set('n', 'qh', 'colder', { desc = 'Older list' }) +vim.keymap.set('n', 'ql', 'cnewer', { desc = 'Newer list' }) +vim.keymap.set('n', 'c', 'vert te', { desc = 'Terminal (vsplit)' }) +vim.keymap.set('n', 'C', 'tab te', { desc = 'Terminal (tab)' }) + +-- Diagnostic mappings +vim.keymap.set('n', 'eo', vim.diagnostic.open_float, { desc = 'Open diagnostic' }) +vim.keymap.set('n', 'eq', vim.diagnostic.setqflist, { desc = 'Save to quickfix' }) +vim.keymap.set('n', 'e]', vim.diagnostic.goto_next, { desc = 'Next diagnostic' }) +vim.keymap.set('n', 'e[', vim.diagnostic.goto_prev, { desc = 'Previous diagnostic' }) +vim.keymap.set('n', 'ee', function() vim.diagnostic.goto_next { severity = vim.diagnostic.severity.E } end, { desc = 'Next error' }) +vim.keymap.set('n', 'eE', function() vim.diagnostic.goto_prev { severity = vim.diagnostic.severity.E } end, { desc = 'Previous error' }) +vim.keymap.set('n', 'ew', function() vim.diagnostic.goto_next { severity = vim.diagnostic.severity.W } end, { desc = 'Next warning' }) +vim.keymap.set('n', 'eW', function() vim.diagnostic.goto_prev { severity = vim.diagnostic.severity.W } end, { desc = 'Previous warning' }) +vim.keymap.set('n', ']e', function() vim.diagnostic.goto_next { severity = vim.diagnostic.severity.E } end, { desc = 'Next error' }) +vim.keymap.set('n', '[e', function() vim.diagnostic.goto_prev { severity = vim.diagnostic.severity.E } end, { desc = 'Previous error' }) +vim.keymap.set('n', ']w', function() vim.diagnostic.goto_next { severity = vim.diagnostic.severity.W } end, { desc = 'Next warning' }) +vim.keymap.set('n', '[w', function() vim.diagnostic.goto_prev { severity = vim.diagnostic.severity.W } end, { desc = 'Previous warning' }) +vim.keymap.set('n', 'eh', vim.diagnostic.hide, { desc = 'Hide diagnostics' }) +vim.keymap.set('n', 'es', vim.diagnostic.show, { desc = 'Show diagnostics' }) +vim.keymap.set('n', 'eC', vim.diagnostic.reset, { desc = 'Clear diagnostics' }) -- Commands vim.cmd [[ @@ -199,11 +198,6 @@ au('User', { end, desc = 'Override Startify mappings', }) -au('BufWritePost', { - pattern = '*/.config/nvim/init.lua', - command = 'source | PackerCompile', - desc = 'Reload config when it is saved, and compile packer cache', -}) au('TextYankPost', { callback = function() vim.highlight.on_yank() end, desc = 'Highlight when text is yanked', @@ -232,68 +226,86 @@ fn.sign_define('DiagnosticSignHint', { text = '', texthl = 'DiagnosticSignHin fn.sign_define('DiagnosticSignWarn', { text = '', texthl = 'DiagnosticSignWarn' }) fn.sign_define('DiagnosticSignError', { text = '', texthl = 'DiagnosticSignError' }) --- netrw --- Set special URL handler -g.netrw_browsex_viewer = 'xdg-open' +au('LspAttach', { callback = function(event) + require'which-key'.register({ + ['l'] = { + name = 'LSP', + D = {vim.lsp.buf.declaration, 'Declaration'}, + d = {'Telescope lsp_definitions', 'Definition'}, + i = {'Telescope lsp_implementations', 'Implementation'}, + I = {vim.lsp.buf.implementation, 'Implementation (quickfix)'}, + r = {vim.lsp.buf.rename, 'Rename'}, + h = {function() vim.lsp.inlay_hint.enable(0, not vim.lsp.inlay_hint.is_enabled()) end, 'Inlay hints'}, + l = {vim.lsp.codelens.refresh, 'Show codelenses'}, + L = {vim.lsp.codelens.run, 'Run codelens'}, + t = {'Telescope lsp_type_definitions', 'Type definition'}, + u = {'Telescope lsp_references', 'Usages/references'}, + U = {vim.lsp.buf.references, 'Usages/references (quickfix)'}, + }, + g = { + d = {vim.lsp.buf.definition, 'Goto definition'}, + D = {vim.lsp.buf.implementation, 'Goto implementation'}, + R = {vim.lsp.buf.rename, 'Rename'}, + y = {vim.lsp.buf.type_definition, 'Type definition'}, + }, + [''] = {vim.lsp.buf.document_highlight, 'Highlight object under cursor'}, + }, { buffer = event.buf }) +end }) ----- Plugins ---- --- Automatically download packer if not installed -local packer_path = fn.stdpath('data') .. '/site/pack/packer/start/packer.nvim' -local packer_bootstrap = nil -if fn.empty(fn.glob(packer_path)) > 0 then - if fn.executable('git') ~= 1 then - vim.notify('You must install git to manage plugins') - return - end - vim.notify('Downloading plugin manager with git') - packer_bootstrap = fn.system({'git', 'clone', '--depth', '1', 'https://github.com/wbthomason/packer.nvim', packer_path}) -end ---- @param package string -function mason_path(package) +function _G.mason_path(package) return vim.fn.stdpath('data') .. '/mason/packages/' .. package end -require'packer'.startup(function(use) - use 'wbthomason/packer.nvim' +-- Bootstrap plugin system +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.uv.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) + +require('lazy').setup({ -- Themes -- - use {'arcticicestudio/nord-vim', branch = 'main'} - use 'chriskempson/base16-vim' - use {'folke/tokyonight.nvim', config = function() - require'tokyonight'.setup { - style = 'night' + {'miikanissi/modus-themes.nvim', opts = {}}, + 'arcticicestudio/nord-vim', + 'folke/tokyonight.nvim', + {'catppuccin/nvim', name = 'catppuccin', opts = { + integrations = { + barbar = true, } - end} - use {'catppuccin/nvim', as = 'catppuccin', config = function() - vim.g.catppuccin_flavour = 'latte' - require'catppuccin'.setup { - integrations = { - barbar = true, - nvimtree = { - enabled = true, - show_root = true, - } - } - } - end} - use {'navarasu/onedark.nvim', config = function() - require'onedark'.setup {} - end} + }}, + 'navarasu/onedark.nvim', -- Filetype plugins -- - use 'rhysd/vim-crystal' - use 'bakpakin/fennel.vim' - use 'mboughaba/i3config.vim' - use 'plasticboy/vim-markdown' - use 'mracos/mermaid.vim' - use 'lifepillar/pgsql.vim' - use 'ajouellette/sway-vim-syntax' - use 'cespare/vim-toml' + 'rhysd/vim-crystal', + 'bakpakin/fennel.vim', + 'mboughaba/i3config.vim', + 'plasticboy/vim-markdown', + 'mracos/mermaid.vim', + 'lifepillar/pgsql.vim', + 'ajouellette/sway-vim-syntax', + 'cespare/vim-toml', - -- Editing -- - use 'LunarWatcher/auto-pairs' - use 'ojroques/nvim-bufdel' - use {'stevearc/conform.nvim', config = function() + -- Editing + {'LunarWatcher/auto-pairs', init = function() + vim.g.AutoPairsMultilineClose = 0 + vim.g.AutoPairsMapCR = 0 -- temp workaround + vim.g.AutoPairsMapBS = 1 + vim.g.AutoPairsCompatibleMaps = 1 + vim.g.AutoPairsShortcutToggleMultilineClose = '' + end}, + 'ojroques/nvim-bufdel', + {'stevearc/conform.nvim', config = function () require'conform'.setup { + formatters_by_ft = { + html = {"prettier"}, + }, format_on_save = { lsp_fallback = true, filter = function(client) @@ -312,54 +324,275 @@ require'packer'.startup(function(use) desc = 'Format buffer', } ) - end} - use {'jbyuki/instant.nvim', config = function() - vim.g.instant_username = 'agraven' - end} - use {'mizlan/iswap.nvim', config = function() - require'iswap'.setup{} - require'which-key'.register{['s'] = {'ISwapWith','Swap'}} - end} - use 'bfredl/nvim-luadev' -- lua scratchpad - use {'windwp/nvim-projectconfig', config = function() - require'nvim-projectconfig'.setup { - -- Load project configuration when changing directory - autocmd = true, - } - end} - use 'tpope/vim-repeat' - use 'tpope/vim-sleuth' - use 'tpope/vim-surround' - use {'vim-test/vim-test', config = function() + au('LspAttach', { callback = function() + vim.bo.formatexpr = "v:lua.require'conform'.formatexpr()" + end }) + end}, + 'direnv/direnv.vim', + 'jbyuki/instant.nvim', + {'mizlan/iswap.nvim', config = function() + require'iswap'.setup {} + vim.keymap.set('', 's', 'ISwapWith', { desc = 'Swap' }) + end}, + {'windwp/nvim-projectconfig', opts = { + -- Load project configuration when changing directory + autocmd = true, + }}, + 'tpope/vim-repeat', + 'tpope/vim-sleuth', + 'AndrewRadev/splitjoin.vim', + {'kylechui/nvim-surround', opts = {}}, + 'wellle/targets.vim', + {'vim-test/vim-test', init = function() vim.g['test#neovim#term_position'] = 'vert' vim.g['test#strategy'] = 'neovim' - end} - use {'julian/vim-textobj-variable-segment', requires = {'kana/vim-textobj-user'}, branch = 'main'} - use {'nvim-treesitter/nvim-treesitter', run = ':TSUpdate'} - use 'windwp/nvim-ts-autotag' - use {'kevinhwang91/nvim-ufo', requires = 'kevinhwang91/promise-async', config = function() - local ok, ufo = pcall(require, 'ufo') - if not ok then return end + end}, + {'julian/vim-textobj-variable-segment', dependencies = {'kana/vim-textobj-user'}}, + {'nvim-treesitter/nvim-treesitter', build = ':TSUpdate', opts = { + -- Configure the nvim-ts-autotag plugin + autotag = { + enable = true, + }, + ensure_installed = {'lua', 'html', 'c', 'cpp', 'nix', 'vim', 'vimdoc', 'rust', 'bash', 'markdown', 'java', 'markdown_inline'}, + highlight = { enable = true, disable = {'rust', 'bash'} }, + incremental_selection = { enable = true }, + }, config = function(_, opts) + require'nvim-treesitter.configs'.setup(opts) + end}, + 'windwp/nvim-ts-autotag', + {'kevinhwang91/nvim-ufo', dependencies = 'kevinhwang91/promise-async', config = function() + local ufo = require('ufo') vim.keymap.set('n', 'zR', ufo.openAllFolds) vim.keymap.set('n', 'zR', ufo.closeAllFolds) ufo.setup {} - end} - use 'hrsh7th/vim-vsnip' + end}, + 'hrsh7th/vim-vsnip', -- LSP -- - use 'neovim/nvim-lspconfig' - use 'hrsh7th/nvim-cmp' - use 'rcarriga/cmp-dap' - use 'hrsh7th/cmp-nvim-lua' - use 'hrsh7th/cmp-nvim-lsp' - use 'hrsh7th/cmp-buffer' - use 'hrsh7th/cmp-path' - use 'hrsh7th/cmp-cmdline' - use 'nanotee/sqls.nvim' - use 'mfussenegger/nvim-jdtls' - use 'simrat39/rust-tools.nvim' - use 'pmizio/typescript-tools.nvim' - use {'nvimtools/none-ls.nvim', requires = {'nvim-lua/plenary.nvim'}, config = function() + {'neovim/nvim-lspconfig', dependencies = {'hrsh7th/cmp-nvim-lsp', 'williamboman/mason-lspconfig.nvim'}, config = function() + local lspconfig = require'lspconfig' + -- Tweak the advertized LSP client capabilities + local capabilities = require'cmp_nvim_lsp'.default_capabilities() + -- Set options for nvim-ufo + capabilities.textDocument.foldingRange = { + dynamicRegistration = false, + lineFoldingOnly = true, + } + -- Update the default for all servers + lspconfig.util.default_config.capabilities = capabilities + + -- Set up language servers + lspconfig.bashls.setup {} + lspconfig.clangd.setup {} + lspconfig.eslint.setup { autostart = false } + lspconfig.lemminx.setup {} + lspconfig.lua_ls.setup { + settings = { + Lua = { + runtime = { + version = 'LuaJIT', + }, + diagnostics = { + globals = {'vim'}, + }, + workspace = { + library = vim.api.nvim_get_runtime_file('', true), + checkThirdParty = false, + }, + telemetry = { + enable = false, + }, + } + } + } + lspconfig.nil_ls.setup {} + lspconfig.pyright.setup {} + lspconfig.vimls.setup {} + + -- TODO decide what to do with autocmd + end}, + {'hrsh7th/nvim-cmp', dependencies = { + 'rcarriga/cmp-dap', + 'hrsh7th/cmp-nvim-lua', + 'hrsh7th/cmp-nvim-lsp', + 'hrsh7th/cmp-buffer', + 'hrsh7th/cmp-path', + 'hrsh7th/cmp-cmdline', + 'dcampos/nvim-snippy', + 'dcampos/cmp-snippy', + }, config = function() + local cmp = require'cmp' + local cmp_dap = require'cmp_dap' + local snippy = require'snippy' + vim.opt.completeopt:append({'menuone', 'noinsert', 'noselect'}) + local has_words_before = function() + unpack = unpack or table.unpack + 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 + cmp.setup { + enabled = function() + return vim.bo.buftype ~= 'prompt' or cmp_dap.is_dap_buffer() + end, + preselect = cmp.PreselectMode.None, + snippet = { + expand = function(args) + require('snippy').expand_snippet(args.body) + end, + }, + mapping = cmp.mapping.preset.insert { + -- Next item, or expand or jump snippet, or fallback + [''] = cmp.mapping( + function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif snippy.can_expand_or_advance() then + snippy.expand_or_advance() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, + {'i', 's'} + ), + -- Prev item, or jump snippet back, or fallback + [''] = cmp.mapping( + function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif snippy.can_jump(-1) then + snippy.previous() + else + fallback() + end + end, + {'i', 's'} + ), + -- Scroll documentation up + [''] = cmp.mapping(cmp.mapping.scroll_docs(4), {'i', 'c'}), + -- Scroll documentation down + [''] = cmp.mapping(cmp.mapping.scroll_docs(-4), {'i', 'c'}), + -- Complete common substring + [''] = cmp.mapping(cmp.mapping.complete_common_string(), {'i', 'c'}), + -- Complete + [''] = cmp.mapping(cmp.mapping.complete {}, {'i', 'c'}), + -- Confirm + [''] = cmp.mapping(cmp.mapping.confirm { select = false }, {'i', 'c'}), + }, + sources = { + { name = 'path' }, + { name = 'nvim_lsp' }, + { name = 'nvim_lua' }, + { name = 'snippy' }, + }, + -- Experimental features + experimental = { + -- Show completion result as virtual text + ghost_text = true, + }, + } + cmp.setup.cmdline(':', { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ + { name = 'path' } + }, + { + { + name = 'cmdline', + option = { + ignore_cmds = { 'Man', '!' } + } + } + }), + }) + cmp.setup.cmdline({'/', '?'}, { + mapping = cmp.mapping.preset.cmdline(), + sources = { + { name = 'buffer' } + }, + }) + cmp.setup.filetype({'dap-repl', 'dapui_watches', 'dapui_hover'}, { + sources = { + { name = 'dap' }, + }, + }) + end}, + -- TODO rustacean-vim + {'mfussenegger/nvim-jdtls', dependencies = {'neovim/nvim-lspconfig'}, config = function() + au('FileType', { + pattern = 'java', + callback = function() + local jdtls = require 'jdtls' + jdtls.tests = require'jdtls.tests' + jdtls.dap = require'jdtls.dap' + _G.jdt = jdtls + local lspconfig = require'lspconfig' + + local root_dir = jdtls.setup.find_root({'.git', 'mvnw', 'gradlew'}) + + local config = { + -- The command to launch jdtls with + cmd = { + 'jdtls', + -- Enable logging + '--jvm-arg=-Dlog.level=ALL', + '--jvm-arg=-Dlog.protocol=true', + -- Enable lombok + '--jvm-arg=-javaagent:' .. mason_path('jdtls') .. '/lombok.jar', + -- store workpace data in ~/.local/share/eclipse/ + '-data', vim.fn.expand('~/.local/share/eclipse/') .. vim.fn.fnamemodify(root_dir, ':p:h:t') + }, + + root_dir = root_dir, + + capabilities = lspconfig.util.default_config.capabilities, + + settings = { + java = {}, + }, + + init_options = { + -- JDTLS plugins + bundles = (function() + -- add java-debug-adapter + local bundles = { + vim.fn.glob(mason_path'java-debug-adapter' .. '/extension/server/com.microsoft.java.debug.plugin-*.jar', true) + } + -- add java-test + vim.list_extend(bundles, vim.split( + vim.fn.glob(vim.fn.expand('~/.local/share/vscode-java-test/server') .. '/*.jar', true), + '\n' + )) + + return bundles + end)(), + }, + + on_attach = function(client, bufnr) + jdtls.setup_dap() + end, + } + + jdtls.start_or_attach(config) + end + }) + end}, + {'pmizio/typescript-tools.nvim', opts = { + settings = { + tsserve_file_preferences = { + quotePreference = 'single' + }, + tsserver_plugins = (function () + if vim.system({'npm', 'list', '-g', '@styled/typescript-styled-plugin'}):wait().code == 0 then + return {'@styled/typescript-styled-plugin'} + else + return {} + end + end)() + } + }}, + {'nvimtools/none-ls.nvim', dependencies = {'nvim-lua/plenary.nvim'}, config = function() local null_ls = require'null-ls' null_ls.setup { sources = { @@ -367,33 +600,99 @@ require'packer'.startup(function(use) null_ls.builtins.code_actions.shellcheck, } } - end} - use 'SmiteshP/nvim-navic' - use {'utilyre/barbecue.nvim', config = function() - require'barbecue'.setup { - show_modified = true, - } - end} + end}, + {'SmiteshP/nvim-navic', config = function() + au('LspAttach', { callback = function(event) + local client = vim.lsp.get_client_by_id(event.data.client_id) + if not client then return end + if client.server_capabilities.documentSymbolProvider then + require'nvim-navic'.attach(client, event.buf) + end + end }) + end}, + {'utilyre/barbecue.nvim', opts = { + show_modified = true + }}, - -- UI elements -- - use 'vim-airline/vim-airline' - use 'vim-airline/vim-airline-themes' - use 'romgrk/barbar.nvim' - use {'luckasRanarison/clear-action.nvim', config = function() + -- UI Elements -- + {'vim-airline/vim-airline', dependencies = {'vim-airline/vim-airline-themes'}, init = function () + -- Permit spaces after tabs but not in between when doing mixed indent checking + -- (mainly for multiline /* */ style comments) + vim.g['airline#extensions#whitespace#mixed_indent_algo'] = 2 + -- truncate leading branch paths, i.e. agraven/foo → a/foo + vim.g['airline#extensions#branch#format'] = 2 + vim.g['airline#extensions#c_like_langs'] = {'typescript'} + -- Hide encoding section + vim.g['airline#extensions#default#layout'] = {{'a', 'b', 'c'}, {'x', 'z', 'warning', 'error'}} + vim.g.airline_detect_spell = 1 -- Show if 'spell' is enabled + vim.g.airline_detect_spelllang = 1 -- Display what language spell is using if enabled + vim.g.airline_inactive_collapse = 1 -- Show only filename in inactive windows + vim.g.airline_highlighting_cache = 1 -- Improves performance + vim.g.airline_theme = 'ayu_mirage' -- Airline's theme + vim.g.airline_powerline_fonts = 1 -- Enable symbols from the powerline font patch + + -- This doesn't work in lua for some reason + vim.cmd [[ + if !exists('g:airline_symbols') + let g:airline_symbols = {} " Initialize the table of symbols + endif + let g:airline_symbols.linenr = ' ' " Symbol before line number + let g:airline_symbols.maxlinenr = '' " Symbol after max line number + let g:airline_symbols.colnr = ' ' " Symbol before column number + let g:airline_symbols.dirty = '+' " Symbol on modified branch + let g:airline_symbols.notexists = '?' " Symbol for untracked file + ]] + end}, + {'romgrk/barbar.nvim', lazy = false, keys = { + {'', 'BufferPrevious', { desc = 'Next buffer' }}, + {'', 'BufferNext', { desc = 'Previous buffer' }}, + {'', 'BufferPick', { desc = 'Pick buffer' }}, + {'', 'BufferPin', { desc = 'Pin buffer' }}, + {'', 'BufferClose', { desc = 'Delete buffer' }}, + {'', 'BufferPickDelete', { desc = 'Delete picked buffer' }}, + {'', 'BufferMovePrevious', { desc = 'Move buffer left' }}, + {'>', 'BufferMoveNext', { desc = 'Move buffer right' }}, + {'b,', 'BufferPrevious', { desc = 'Next buffer' }}, + {'b.', 'BufferNext', { desc = 'Previous buffer' }}, + {'bb', 'BufferPick', { desc = 'Pick buffer' }}, + {'bp', 'BufferPin', { desc = 'Pin buffer' }}, + {'bd', 'BufferClose', { desc = 'Delete buffer' }}, + {'bx', 'BufferPickDelete', { desc = 'Delete picked buffer' }}, + {'bh', 'BufferMovePrevious', { desc = 'Move buffer left' }}, + {'bl', 'BufferMoveNext', { desc = 'Move buffer right' }}, + }}, + {'luckasRanarison/clear-action.nvim', config = function() require'clear-action'.setup { signs = { enable = true, + -- Only show one symbol instead of several per category combine = true, + -- Don't show the number of actions, show_count = false, + -- Which icons to use for code action sings + icons = { + combined = '🛈', + }, }, popup = { enable = true }, } - end} - use {'MattesGroeger/vim-bookmarks', config = function() + au('LspAttach', { callback = function(event) + local client = vim.lsp.get_client_by_id(event.data.client_id) + local code_action + if client and client.name ~= 'jdtls' then + code_action = require'clear-action'.code_action + else + code_action = vim.lsp.buf.code_action + end + vim.keymap.set('n', 'ga', code_action, { buffer = event.buf, desc = 'Code action' }) + vim.keymap.set('n', 'la', code_action, { buffer = event.buf, desc = 'Code action' }) + end }) + end}, + {'MattesGroeger/vim-bookmarks', config = function() vim.g.bookmark_no_default_key_mappings = 1 vim.g.bookmark_save_per_working_dir = 1 - end} - use {'kristijanhusak/vim-dadbod-ui', requires = {'tpope/vim-dadbod', 'kristijanhusak/vim-dadbod-completion'}, config = function() + end}, + {'kristijanhusak/vim-dadbod-ui', dependencies = {'tpope/vim-dadbod', 'kristijanhusak/vim-dadbod-completion'}, config = function() vim.g.db_ui_use_nerd_fonts = 1 vim.g.db_ui_auto_execute_table_helpers = 1 vim.g.db_ui_win_position = 'right' @@ -406,8 +705,8 @@ require'packer'.startup(function(use) end, desc = 'SQL dadbod completion', }) - end} - use {'mfussenegger/nvim-dap', config = function() + end}, + {'mfussenegger/nvim-dap', dependencies = {'folke/which-key.nvim'}, config = function() local dap = require'dap' vim.fn.sign_define('DapBreakpoint', {text = '⯃', texthl = 'DiagnosticError'}) dap.adapters.codelldb = { @@ -533,10 +832,11 @@ require'packer'.startup(function(use) p = {dap.pause, 'Pause execution'} } } - end} - use {'rcarriga/nvim-dap-ui', config = function() + end}, + {'rcarriga/nvim-dap-ui', dependencies = {'mfussenegger/nvim-dap'}, config = function() local dapui, dap = require'dapui', require'dap' dapui.setup() + -- Hooks for opening the debugger ui automatically dap.listeners.after.event_initialized.dapui_config = function() dapui.open {} end @@ -549,41 +849,80 @@ require'packer'.startup(function(use) require'which-key'.register { ['dd'] = {require'dapui'.toggle, 'Toggle'} } - end} - use {'theHamsta/nvim-dap-virtual-text', config = function() - require'nvim-dap-virtual-text'.setup { - clear_on_continue = true, - } - end} - use {'sindrets/diffview.nvim', config = function() - require'diffview'.setup { - -- Use nicer highlighting for diffs - enhanced_diff_hl = true, - } - end} - use {'stevearc/dressing.nvim', after = 'telescope.nvim', config = function() + end}, + {'theHamsta/nvim-dap-virtual-text', dependencies = {'mfussenegger/nvim-dap'}, opts = { + -- Clear virtual text when the debugger does a continue + clear_on_continue = true, + }}, + {'sindrets/diffview.nvim', opts = { + -- Use nicer highlighting for diffs + enhanced_diff_hl = true, + }}, + {'stevearc/dressing.nvim', dependencies = {'nvim-telescope/telescope.nvim'}, opts = { + input = { + insert_only = false, + win_options = { + -- Reuse telescope's highlights for windows made by dressing + winhighlight = 'NormalFloat:TelescopeNormal,FloatBorder:TelescopeBorder' + } + }, + select = { + enabled = false, + --telescope = require'telescope.themes'.get_cursor() + }, + }, config = function(_, opts) vim.cmd'highlight link FloatTitle TelescopeBorder' - require'dressing'.setup { - input = { - win_options = { - -- Reuse telescope's highlights for windows made by dressing - winhighlight = 'NormalFloat:TelescopeNormal,FloatBorder:TelescopeBorder' - } - }, - select = { - enabled = false, - telescope = require'telescope.themes'.get_cursor() - }, + require'dressing'.setup(opts) + end}, + {'j-hui/fidget.nvim', dependencies = {'kyazdani42/nvim-tree.lua', lazy = false}, opts = { + progress = { + lsp = { + -- Workaround for rust-analyzer messages getting stuck + progress_ringbuf_size = 2048, + } + }, + integration = { + -- Disable nvim-tree integration, has bugs when restoring sessions + ["nvim-tree"] = { + enable = false, + } } - end} - use {'j-hui/fidget.nvim', config = function() require'fidget'.setup() end} - use 'tpope/vim-fugitive' - use 'tpope/vim-rhubarb' - use 'shumphrey/fugitive-gitlab.vim' - use 'lewis6991/gitsigns.nvim' - use 'junegunn/goyo.vim' - use 'kosayoda/nvim-lightbulb' - use {'https://git.sr.ht/~whynothugo/lsp_lines.nvim', config = function() + }}, + {'tpope/vim-fugitive', lazy = false, dependencies = {'tpope/vim-rhubarb', 'shumphrey/fugitive-gitlab.vim'}, keys = { + {'g', 'vert Git', desc = 'Git status'}, + {'G', 'tab Git', desc = 'Git status (tab)'}, + }}, + {'lewis6991/gitsigns.nvim', opts = { + on_attach = function() + local gitsigns = require'gitsigns' + vim.keymap.set('n', ']c', gitsigns.next_hunk, {desc = 'Next hunk'}) + vim.keymap.set('n', '[c', gitsigns.prev_hunk, {desc = 'Previous hunk'}) + + require'which-key'.register { + ['h'] = { + name = '+gitsigns', + s = {gitsigns.stage_hunk, 'Stage hunk'}, + S = {gitsigns.stage_buffer, 'Stage buffer'}, + u = {gitsigns.unstage_hunk, 'Unstage hunk'}, + U = {gitsigns.unstage_buffer, 'Unstage buffer'}, + r = {gitsigns.reset_hunk, 'Reset hunk'}, + v = {gitsigns.select_hunk, 'Visual select hunk'}, + d = {gitsigns.toggle_deleted, 'Toggle deleted lines'}, + w = {gitsigns.toggle_word_diff, 'Toggle word diffs'}, + l = {gitsigns.blame_line, 'Blame current line'}, + L = {gitsigns.toggle_current_line_blame, 'Toggle line blame'}, + b = {':Gitsigns change_base ', 'Change diff base'}, + B = {gitsigns.reset_base, 'Reset diff base'}, + p = {gitsigns.preview_hunk_inline, 'Preview hunk'}, + P = {gitsigns.preview_hunk, 'Preview hunk popup'}, + } + } + end + }}, + {'junegunn/goyo.vim', config = function() + vim.g.goyo_height = '95%' + end}, + {url = 'https://git.sr.ht/~whynothugo/lsp_lines.nvim', config = function() require'lsp_lines'.setup() vim.diagnostic.config { virtual_text = { @@ -593,37 +932,30 @@ require'packer'.startup(function(use) only_current_line = true, } } - end} - use {'williamboman/mason.nvim', config = function() - require'mason'.setup() - end} - use {'williamboman/mason-lspconfig.nvim', config = function() - require'mason-lspconfig'.setup { - automatic_installation = true - -- figure out how to ensure java-test and java-debug-adapter - } - end} - use {'NeogitOrg/neogit', config = function() - require'neogit'.setup { - disable_context_highlighting = true, - integrations = { - diffview = true, - }, - signs = { - item = {"", ""}, - section = {"", ""}, - }, - } - end} - use {'rcarriga/nvim-notify', after = 'telescope.nvim', config = function() - require'notify'.setup { - stages = 'fade' - } + end}, + {'williamboman/mason.nvim', opts = {}}, + {'williamboman/mason-lspconfig.nvim', dependencies = {'williamboman/mason.nvim'}, opts = { + automatic_installation = true + }}, + {'NeogitOrg/neogit', opts = { + disable_context_highlighting = true, + integrations = { + diffview = true, + }, + signs = { + item = {"", ""}, + section = {"", ""}, + }, + }}, + {'rcarriga/nvim-notify', dependencies = {'nvim-telescope/telescope.nvim'}, opts = { + stages = 'fade' + }, config = function(_, opts) + require'notify'.setup(opts) vim.notify = require'notify' require'telescope'.load_extension('notify') - end} - use {'stevearc/overseer.nvim', after = 'nvim-dap', config = function() - require'overseer'.setup() + end}, + {'stevearc/overseer.nvim', dependencies = {'folke/which-key.nvim'}, config = function(plugin, opts) + require'overseer'.setup(opts) require'which-key'.register { ['r'] = { name = 'Overseer (run tasks)', @@ -636,13 +968,36 @@ require'packer'.startup(function(use) s = {'OverseerSaveBundle', 'Save task list'} } } - end} - use 'mhinz/vim-startify' - use {'nvim-telescope/telescope.nvim', after = 'which-key.nvim', config = function() + end}, + {'mhinz/vim-startify', init = function() + -- Don't change working directory when opening files + g.startify_change_to_dir = 0 + -- Change working dir to version control root when opening file + g.startify_change_to_vcs_root = 1 + -- Enable unicode box drawing in fortune message + g.startify_fortune_use_unicode = 1 + -- Items to show on the startup screen + g.startify_lists = { + { type = 'dir', header = {' Recently used ' .. fn.getcwd()} }, + { type = 'files', header = {' Recently used'} }, + { type = 'sessions', header = {' Sessions'} }, + { type = 'bookmarks', header = {' Bookmarks'} }, + { type = 'commands', header = {' Commands'} }, + } + end}, + {'nvim-telescope/telescope.nvim', dependencies = { + 'nvim-telescope/telescope-fzf-native.nvim', + 'nvim-telescope/telescope-file-browser.nvim', + 'nvim-telescope/telescope-project.nvim', + 'nvim-telescope/telescope-ui-select.nvim', + 'nvim-telescope/telescope-dap.nvim', + 'debugloop/telescope-undo.nvim', + 'folke/which-key.nvim', + }, config = function() local ok, telescope = pcall(require, 'telescope') if not ok then return end telescope.builtin = require'telescope.builtin' - telescope.themes = require'telescope.themes' + --telescope.themes = require'telescope.themes' telescope.setup { defaults = { sorting_strategy = 'ascending', @@ -669,11 +1024,11 @@ require'packer'.startup(function(use) -- TODO; check if this is right full_path = true, }, - ['ui-select'] = telescope.themes.get_cursor { - layout_config = { - height = 15, - }, - }, + --['ui-select'] = telescope.themes.get_cursor { + -- layout_config = { + -- height = 15, + -- }, + --}, }, } require'which-key'.register { @@ -707,656 +1062,128 @@ require'packer'.startup(function(use) s = {'Telescope lsp_dynamic_workspace_symbols', 'Symbols'}, S = {'Telescope lsp_document_symbols', 'Symbols - current file'}, n = {'Telescope notify', 'Notifications'}, - m = {'Telescope man_pages', 'Man pages'}, + m = {'Telescope man_pages sections=ALL', 'Man pages'}, [':'] = {'Telescope commands', 'Commands'}, u = {'Telescope undo', 'Undo'}, } } - end} - use {'nvim-telescope/telescope-fzf-native.nvim', run = 'make', after = 'telescope.nvim', config = function() require'telescope'.load_extension('fzf') - end} - use {'nvim-telescope/telescope-file-browser.nvim', after = 'telescope.nvim', config = function() require'telescope'.load_extension('file_browser') - end} - use {'nvim-telescope/telescope-project.nvim', after = 'telescope.nvim', config = function() require'telescope'.load_extension('project') - end} - use {'nvim-telescope/telescope-ui-select.nvim', after = 'telescope.nvim', config = function() require'telescope'.load_extension('ui-select') - end} - use {'nvim-telescope/telescope-dap.nvim', after = 'telescope.nvim', config = function() require'telescope'.load_extension('dap') - end} - use {'debugloop/telescope-undo.nvim', after = 'telescope.nvim', config = function() require'telescope'.load_extension('undo') - end} - use {'nvim-neotest/neotest', requires = {'rcasia/neotest-java', 'nvim-neotest/neotest-vim-test'}, config = function() + end}, + {'nvim-neotest/neotest', dependencies = {'rcasia/neotest-java', 'nvim-neotest/neotest-vim-test'}, config = function() require'neotest'.setup { adapters = { require'neotest-java' {}, require'neotest-vim-test' {}, } } - end} - use 'kyazdani42/nvim-tree.lua' - use 'hedyhli/outline.nvim' - use {'folke/which-key.nvim', config = function() require'which-key'.setup() end} + end}, + {'kyazdani42/nvim-tree.lua', opts = { + actions = { + open_file = { + window_picker = { + exclude = { + filetype = {'Outline', 'qf'}, + }, + } + }, + }, + -- Don't disable netrw + disable_netrw = false, + -- Show LSP diagnostics in the sign column + diagnostics = { + enable = true, + icons = { + hint = "", + }, + }, + git = { + -- Don't hide .gitignore'd files by default + ignore = false, + -- Extend timeout + timeout = 5000, + }, + -- Reload the tree when its window is focused + reload_on_bufenter = true, + -- Appeareance settings + renderer = { + -- highlight git status (unstaged, staged, clean) + highlight_git = true, + -- Highlight open files + highlight_opened_files = 'name', + -- Don't hightlight files as spceial + special_files = {}, + -- Combine nested folders with only one child + group_empty = true, + -- Icon settings + icons = { + -- Hide git attribute icons + show = { + git = false, + folder = true, + file = true, + folder_arrow = true, + }, + -- Change icons + glyphs = { + -- Set a default icon so entries are aligned + default = '🗋' + }, + }, + }, + -- Match tree cwd to vim's cwd + update_cwd = true, + view = { + width = 45, + }, + }, config = function(plugin, opts) + require'nvim-tree'.setup(opts) + -- Handle restoring sessions with nvim-tree windows properly + au('BufEnter', { + pattern = 'NvimTree*', + callback = function() + local api = require('nvim-tree.api') + local view = require('nvim-tree.view') - -- Utility and libraries - use 'nvim-lua/plenary.nvim' - use 'ryanoasis/vim-devicons' - use 'kyazdani42/nvim-web-devicons' - use {'ellisonleao/dotenv.nvim', config = function() - require'dotenv'.setup { - enable_on_load = false, - verbose = true, - } - end} - - -- Finish bootstrap if we just cloned - if packer_bootstrap then - require('packer').sync() - vim.notify('Bootstrapped plugin manager, you may need to restart neovim') - end -end) - - ----- airline ---- --- Permit spaces after tabs but not in between when doing mixed indent checking --- (mainly for multiline /* */ style comments) -g['airline#extensions#whitespace#mixed_indent_algo'] = 2 --- truncate leading branch paths, i.e. agraven/foo → a/foo -g['airline#extensions#branch#format'] = 2 -g['airline#extensions#c_like_langs'] = {'typescript'} --- Hide encoding section -g['airline#extensions#default#layout'] = {{'a', 'b', 'c'}, {'x', 'z', 'warning', 'error'}} -g.airline_detect_spell = 1 -- Show if 'spell' is enabled -g.airline_detect_spelllang = 1 -- Display what language spell is using if enabled -g.airline_inactive_collapse = 1 -- Show only filename in inactive windows -g.airline_highlighting_cache = 1 -- Improves performance -g.airline_theme = 'ayu_mirage' -- Airline's theme -g.airline_powerline_fonts = 1 -- Enable symbols from the powerline font patch - --- This doesn't work in lua for some reason -vim.cmd [[ - if !exists('g:airline_symbols') - let g:airline_symbols = {} " Initialize the table of symbols - endif - let g:airline_symbols.linenr = ' ' " Symbol before line number - let g:airline_symbols.maxlinenr = '' " Symbol after max line number - let g:airline_symbols.colnr = ' ' " Symbol before column number - let g:airline_symbols.dirty = '+' " Symbol on modified branch - let g:airline_symbols.notexists = '?' " Symbol for untracked file -]] - - ----- autopairs ---- -vim.g.AutoPairsMultilineClose = 0 -vim.g.AutoPairsMapCR = 0 -- temp workaround -vim.g.AutoPairsMapBS = 1 -vim.g.AutoPairsCompatibleMaps = 1 -vim.g.AutoPairsShortcutToggleMultilineClose = '' - ----- barbar ---- -require'which-key'.register { - [''] = {'BufferPrevious', 'Next buffer'}, - [''] = {'BufferNext', 'Previous buffer'}, - [''] = {'BufferPick', 'Pick buffer'}, - [''] = {'BufferPin', 'Pin buffer'}, - [''] = {'BufferClose', 'Delete buffer'}, - [''] = {'BufferPickDelete', 'Delete picked buffer'}, - [''] = {'BufferMovePrevious', 'Move buffer left'}, - ['>'] = {'BufferMoveNext', 'Move buffer right'}, -} -require'which-key'.register { - ['b'] = { - name = 'Buffers', - [','] = { 'BufferPrevious', 'Next buffer'}, - ['.'] = { 'BufferNext', 'Previous buffer'}, - b = {'BufferPick', 'Pick buffer'}, - p = {'BufferPin', 'Pin buffer'}, - d = {'BufferClose', 'Delete buffer'}, - x = {'BufferPickDelete', 'Delete picked buffer'}, - h = {'BufferMovePrevious', 'Move buffer left'}, - l = {'BufferMoveNext', 'Move buffer right'}, - } -} - - ----- devicons ---- -require'nvim-web-devicons'.setup { default = true } - - ----- fidget ---- -require'fidget'.setup {} - - ----- fugitive ---- -vim.keymap.set('n', 'g', 'vert Git', {desc = 'Git status'}) -vim.keymap.set('n', 'G', 'tab Git', {desc = 'Git status (new tab)'}) - - ----- gitsigns ---- -require'gitsigns'.setup { - on_attach = function() - local gitsigns = require'gitsigns' - vim.keymap.set('n', ']c', gitsigns.next_hunk, {desc = 'Next hunk'}) - vim.keymap.set('n', '[c', gitsigns.prev_hunk, {desc = 'Previous hunk'}) - - --- Prompt interactively for global comparison base - local function change_base() - require'gitsigns.cli' - vim.ui.input({ - prompt = 'Revision to compare to', - completion = "customlist,v:lua.require'gitsigns.cli'.complete", - }, function(revision) - if not revision then return end - gitsigns.change_base(revision, true) - end) - end + if not view.is_visible() then + api.tree.open() + end + end, + }) + vim.cmd'highlight NvimTreeOpenedFile guifg=NONE guibg=NONE gui=italic' + vim.keymap.set('n', 't', 'NvimTreeFindFile', {desc = 'Nvim Tree'}) + end}, + {'hedyhli/outline.nvim', opts = { + outline_window = { + -- Use absolute number of columns instead of percentage for sizing + relative_width = false, + -- Window should be 30 columns wide + width = 30, + }, + }, keys = { + {'o', 'Outline', desc = 'Symbols outline'} + }}, + {'folke/which-key.nvim', opts = {}, config = function (plugin, opts) + require'which-key'.setup(opts) require'which-key'.register { - ['h'] = { - name = '+gitsigns', - s = {gitsigns.stage_hunk, 'Stage hunk'}, - S = {gitsigns.stage_buffer, 'Stage buffer'}, - u = {gitsigns.unstage_hunk, 'Unstage hunk'}, - U = {gitsigns.unstage_buffer, 'Unstage buffer'}, - r = {gitsigns.reset_hunk, 'Reset hunk'}, - v = {gitsigns.select_hunk, 'Visual select hunk'}, - d = {gitsigns.toggle_deleted, 'Toggle deleted lines'}, - w = {gitsigns.toggle_word_diff, 'Toggle word diffs'}, - l = {gitsigns.blame_line, 'Blame current line'}, - L = {gitsigns.toggle_current_line_blame, 'Toggle line blame'}, - b = {':Gitsigns change_base ', 'Change diff base'}, - B = {gitsigns.reset_base, 'Reset diff base'}, - p = {gitsigns.preview_hunk_inline, 'Preview hunk'}, - P = {gitsigns.preview_hunk, 'Preview hunk popup'}, - } + ['q'] = { name = 'Quickfix' }, + ['l'] = { name = 'LSP' }, + ['b'] = { name = 'Buffer' }, + ['e'] = { name = 'Diagnostic' }, } - end -} + end}, ----- goyo ---- -g.goyo_height = '95%' - - ----- lightbulb ---- -g.lightbulb_cfg = { - sign = { - enabled = false, - }, - virtual_text = { - enabled = true, - text = "🛈", - } -} ---vim.cmd [[ --- highlight link LightBulbVirtualText Comment --- autocmd CursorHold,CursorHoldI * lua require'nvim-lightbulb'.update_lightbulb(vim.g.lightbulb_cfg) ---]] - - ----- lsp: cmp ---- -local feedkey = function(key, mode) - vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true) -end -local cmp = require'cmp' -local cmp_dap = require'cmp_dap' -cmp.setup { - enabled = function() - return vim.bo.buftype ~= 'prompt' or cmp_dap.is_dap_buffer() - end, - preselect = cmp.PreselectMode.None, - snippet = { - expand = function(args) - vim.fn['vsnip#anonymous'](args.body) - end, - }, - mapping = cmp.mapping.preset.insert { - -- Next item, or expand or jump snippet, or fallback - [''] = cmp.mapping( - function(fallback) - if cmp.visible() then - cmp.select_next_item() - elseif vim.fn['vsnip#available'](1) == 1 then - feedkey('(vsnip-expand-or-jump)', '') - else - fallback() - end - end, - {'i', 's'} - ), - -- Prev item, or jump snippet back, or fallback - [''] = cmp.mapping( - function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif vim.fn['vsnip#available'](-1) == 1 then - feedkey('(vsnip-jump-prev)', '') - else - fallback() - end - end, - {'i', 's'} - ), - -- Scroll documentation up - [''] = cmp.mapping(cmp.mapping.scroll_docs(4), {'i', 'c'}), - -- Scroll documentation down - [''] = cmp.mapping(cmp.mapping.scroll_docs(-4), {'i', 'c'}), - -- Complete common substring - [''] = cmp.mapping(cmp.mapping.complete_common_string(), {'i', 'c'}), - -- Complete - [''] = cmp.mapping(cmp.mapping.complete {}, {'i', 'c'}), - -- Confirm - [''] = cmp.mapping(cmp.mapping.confirm { select = false }, {'i', 'c'}), - }, - sources = { - { name = 'path' }, - { name = 'nvim_lsp' }, - { name = 'nvim_lua' }, - { name = 'vsnip' }, - }, - -- Experimental features - experimental = { - -- Show completion result as virtual text - ghost_text = true, - }, -} -cmp.setup.cmdline(':', { - mapping = cmp.mapping.preset.cmdline(), - sources = cmp.config.sources({ - { name = 'path' } - }, - { - { - name = 'cmdline', - option = { - ignore_cmds = { 'Man', '!' } - } - } - }), + -- Utilities + {'ryanoasis/vim-devicons', dependencies = {'mhinz/vim-startify'}}, + {'kyazdani42/nvim-web-devicons', opts = { default = true }}, + {'ellisonleao/dotenv.nvim', opts = { + enable_on_load = false, + verbose = true, + }} }) -cmp.setup.cmdline({'/', '?'}, { - mapping = cmp.mapping.preset.cmdline(), - sources = { - { name = 'buffer' } - }, -}) -cmp.setup.filetype({'dap-repl', 'dapui_watches', 'dapui_hover'}, { - sources = { - { name = 'dap' }, - }, -}) --- Which client functionality to tell LSP servers we support -local capabilities = require'cmp_nvim_lsp'.default_capabilities() --- nvim-ufo folding capabilities -capabilities.textDocument.foldingRange = { - dynamicRegistration = false, - lineFoldingOnly = true, -} - ----- lsp: language servers ---- -au('LspAttach', { - callback = function(event) - local bufnr = event.buf - local client = vim.lsp.get_client_by_id(event.data.client_id) - if not client then return end - local function code_action() - local ok, clear_action = pcall(require, 'clear-action') - if ok and client.name ~= 'jdtls' then - clear_action.code_action() - else - vim.lsp.buf.code_action() - end - end - require'which-key'.register({ - ['l'] = { - D = {vim.lsp.buf.declaration, 'Declaration'}, - d = {'Telescope lsp_definitions', 'Definition'}, - i = {'Telescope lsp_implementations', 'Implementation'}, - a = {code_action, 'Code action'}, - r = {vim.lsp.buf.rename, 'Rename'}, - h = {function() vim.lsp.inlay_hint.enable(0, not vim.lsp.inlay_hint.is_enabled()) end, 'Inlay hints'}, - l = {vim.lsp.codelens.refresh, 'Show codelenses'}, - L = {vim.lsp.codelens.run, 'Run codelens'}, - t = {'Telescope lsp_type_definitions', 'Type definition'}, - u = {'Telescope lsp_references', 'Usages/references'} - }, - g = { - d = {vim.lsp.buf.definition, 'Goto definition'}, - D = {vim.lsp.buf.implementation, 'Goto implementation'}, - a = {code_action, 'Code action'}, - R = {vim.lsp.buf.rename, 'Rename'}, - y = {vim.lsp.buf.type_definition, 'Type definition'}, - }, - [']'] = { - g = {vim.diagnostic.goto_next, 'Next diagnostic'}, - e = {function() vim.diagnostic.goto_next { severity = vim.diagnostic.severity.ERROR } end, 'Next error'}, - w = {function() vim.diagnostic.goto_next { severity = vim.diagnostic.severity.WARN } end, 'Next warning'}, - q = {vim.diagnostic.setqflist, 'Quickfix diagnostics'}, - }, - ['['] = { - g = {vim.diagnostic.goto_prev, 'Previous diagnostic'}, - e = {function() vim.diagnostic.goto_prev { severity = vim.diagnostic.severity.ERROR } end, 'Previous error'}, - w = {function() vim.diagnostic.goto_prev { severity = vim.diagnostic.severity.WARN } end, 'Previous warning'}, - }, - [''] = {vim.lsp.buf.document_highlight, 'Highlight object under cursor'}, - }, {buffer = bufnr}) - -- Hover - require'which-key'.register({ - ['K'] = {vim.lsp.buf.hover, 'Documentation'}, - [''] = {vim.lsp.buf.signature_help, 'Function signature'}, - }, {buffer = bufnr}) - require'which-key'.register({ - [''] = {vim.lsp.buf.signature_help, 'Function signature'} - }, {buffer = bufnr, mode = 'i'}) - - vim.bo.tagfunc = 'v:lua.vim.lsp.tagfunc' - if pcall(require, 'conform') == true then - vim.bo.formatexpr = "v:lua.require'conform'.formatexpr()" - end - - if client.server_capabilities.documentSymbolProvider then - require'nvim-navic'.attach(client, bufnr) - end - end -}) - --- Enable language servers -local default = { - capabilities = capabilities, -} - -require'lspconfig'.lua_ls.setup { - capabilities = capabilities, - settings = { - Lua = { - runtime = { - version = 'LuaJIT', - }, - diagnostics = { - globals = {'vim'}, - }, - workspace = { - library = vim.api.nvim_get_runtime_file('', true), - checkThirdParty = false, - }, - telemetry = { - enable = false, - }, - } - } -} - -require'lspconfig'.bashls.setup(default) -require'lspconfig'.clangd.setup(default) -au('FileType', { - pattern = 'java', - callback = function() - local ok, jdtls = pcall(require, 'jdtls') - if not ok then return end - jdtls.tests = require'jdtls.tests' - jdtls.dap = require'jdtls.dap' - _G.jdt = jdtls - - local root_dir = jdtls.setup.find_root({'.git', 'mvnw', 'gradlew'}) - - local config = { - -- The command to launch jdtls with - cmd = { - 'jdtls', - -- Enable logging - '--jvm-arg=-Dlog.level=ALL', - '--jvm-arg=-Dlog.protocol=true', - -- Enable lombok - '--jvm-arg=-javaagent:' .. mason_path('jdtls') .. '/lombok.jar', - -- store workpace data in ~/.local/share/eclipse/ - '-data', vim.fn.expand('~/.local/share/eclipse/') .. vim.fn.fnamemodify(root_dir, ':p:h:t') - }, - - root_dir = root_dir, - - settings = { - java = {}, - }, - - init_options = { - -- JDTLS plugins - bundles = (function() - -- add java-debug-adapter - local bundles = { - vim.fn.glob(mason_path'java-debug-adapter' .. '/extension/server/com.microsoft.java.debug.plugin-*.jar', true) - } - -- add java-test - vim.list_extend(bundles, vim.split( - vim.fn.glob(mason_path'java-test' .. '/extension/server/*.jar', true), - '\n' - )) - - return bundles - end)(), - }, - - capabilities = capabilities, - - on_attach = function(client, bufnr) - jdtls.setup_dap() - end, - } - - jdtls.start_or_attach(config) - end -}) -require'lspconfig'.nil_ls.setup(default) -require'lspconfig'.pyright.setup(default) --- Defer setup to silence deprecation notice -au('FileType', { - pattern = 'sql', - callback = function() - require'lspconfig'.sqls.setup { - capabilities = capabilities, - on_attach = function(client, bufnr) - local ok, sqls = pcall(require, 'sqls') - if not ok then return end - sqls.on_attach(client, bufnr) - end - } - end, -}) -require'typescript-tools'.setup(default) -require'lspconfig'.vimls.setup(default) - --- Completion menu bahevior -vim.opt.completeopt:append({'menuone', 'noinsert', 'noselect'}) - - ----- markdown ---- -g.vim_markdown_folding_disabled = 1 -g.vim_markdown_conceal = 1 -g.tex_conceal = "" -g.vim_markdown_math = 1 - - ----- rust ---- --- Don't use recommended style (space indent, textwidth=99) -g.rust_recommended_style = 0 --- Format with rustfmt on save -g.rustfmt_autosave = 1 --- rustfmt is >=1.0 -g.rustfmt_emit_files = 1 --- Use nigtly rustfmt for unstable settings -g.rustfmt_command = 'rustup run nightly rustfmt' - ----- rust-tools ---- -require'rust-tools'.setup { - tools = { - -- Automatically set inlay hints - autoSetHints = true, - -- Don't replace hover handler - hover_with_actions = false, - -- Configure inlay hints - inlay_hints = { - -- Only show hints for the current line - only_current_line = true, - -- AutoCmd to use for updating hints. CursorMove is more responsive but expensive. - only_current_line_autocmd = 'CursorMoved', - }, - }, - server = { - -- Enable standalone file (i.e. no cargo) support - standalone = true, - capabilities = capabilities, - settings = { - ['rust-analyzer'] = { - cargo = { - -- Load OUT_DIR when running check on save, needed for proc macros - loadOutDirsFromCheck = true, - }, - checkOnSave = true, - -- Error checking settings - check = { - -- Use clippy for error checking - command = "clippy", - -- Also run checks for tests - allTargets = true, - }, - diagnostics = { - -- Disable diagnostics with false positives - disabled = {'unresolved-import'}, - }, - procMacro = { - -- Enable proc macro support - enable = true, - }, - rustfmt = { - extraArgs = { '+nightly' } - }, - }, - }, - }, - dap = { - adapter = require'dap'.adapters.codelldb, - }, -} - - ----- startify ---- -g.startify_change_to_dir = 0 -- Don't change working directory when opening files -g.startify_change_to_vcs_root = 1 -- Change working dir to version control root -g.startify_fortune_use_unicode = 1 -- Enable unicode box drawing in fortune message --- Items to show on the startup screen -g.startify_lists = { - { type = 'dir', header = {' Recently used ' .. fn.getcwd()} }, - { type = 'files', header = {' Recently used'} }, - { type = 'sessions', header = {' Sessions'} }, - { type = 'bookmarks', header = {' Bookmarks'} }, - { type = 'commands', header = {' Commands'} }, -} - - ----- symbols-outline ---- -require'outline'.setup { - outline_window = { - -- Use absolute number of columns instead of percentage for sizing - relative_width = false, - -- Window should be 30 columns wide - width = 30, - }, -} -require'which-key'.register({['o'] = {'Outline', 'Symbols outline'}}) - - ----- tree ---- -require('nvim-tree').setup { - actions = { - open_file = { - window_picker = { - exclude = { - filetype = {'Outline'}, - }, - } - }, - }, - -- Don't disable netrw - disable_netrw = false, - -- Show LSP diagnostics in the sign column - diagnostics = { - enable = true, - icons = { - hint = "", - }, - }, - git = { - -- Don't hide .gitignore'd files by default - ignore = false, - -- Extend timeout - timeout = 5000, - }, - -- Reload the tree when its window is focused - reload_on_bufenter = true, - -- Appeareance settings - renderer = { - -- highlight git status (unstaged, staged, clean) - highlight_git = true, - -- Highlight open files - highlight_opened_files = 'name', - -- Don't hightlight files as spceial - special_files = {}, - -- Combine nested folders with only one child - group_empty = true, - -- Icon settings - icons = { - -- Hide git attribute icons - show = { - git = false, - folder = true, - file = true, - folder_arrow = true, - }, - -- Change icons - glyphs = { - -- Set a default icon so entries are aligned - default = '🗋' - }, - }, - }, - -- Match tree cwd to vim's cwd - update_cwd = true, - view = { - width = 45, - }, -} --- Handle restoring sessions with nvim-tree windows properly -au('BufEnter', { - pattern = 'NvimTree*', - callback = function() - local api = require('nvim-tree.api') - local view = require('nvim-tree.view') - - if not view.is_visible() then - api.tree.open() - end - end, -}) -vim.cmd'highlight NvimTreeOpenedFile guifg=NONE guibg=NONE gui=italic' - -vim.keymap.set('n', 't', 'NvimTreeFindFile', {desc = 'Nvim Tree'}) - - ----- treesitter ---- -require'nvim-treesitter.configs'.setup { - -- Configure the nvim-ts-autotag plugin - autotag = { - enable = true, - }, - ensure_installed = {'lua', 'html', 'c', 'cpp', 'nix', 'vim', 'rust', 'bash', 'markdown', 'java', 'markdown_inline'}, - highlight = { enable = true, disable = {'rust', 'bash'} }, - incremental_selection = { enable = true }, -} - -g.nord_italic = 1 -g.nord_italicize_comments = 1 -g.nord_underline = 1 vim.cmd 'colorscheme tokyonight-night'