diff --git a/init.lua b/init.lua index 7d1d651..78f03e0 100644 --- a/init.lua +++ b/init.lua @@ -2,7 +2,7 @@ vim.loader.enable() ---- Built in settings ---- --- Create convenient aliases +-- Create a convenient aliases local o = vim.o local g = vim.g local fn = vim.fn @@ -13,19 +13,15 @@ local workman = false -- Set font o.guifont = 'IosevkaTermSlab Nerd Font,IosevkaTerm Nerd Font,Iosevka Term Slab,Iosevka:h10:#e-subpixelantialias' -g.neovide_floating_z_height = 1 -g.neovide_confirm_quit = true -- Confirm closing neovide window when changes are unsaved -g.neovide_cursor_smooth_blink = true -g.neovide_text_gamma = 0.8 -g.neovide_text_contrast = 0.1 +vim.g.neovide_floating_z_height = 1 if fn.hostname() == 'tappy' then g.neovide_refresh_rate = 144 end -opt.guicursor:append('a:blinkon1500-blinkoff1500-blinkwait1200') -- Blink cursor once every 1.5 seconds +opt.guicursor:append('a:blinkon1000-blinkoff1000-blinkwait1000') -- Blink cursor once a second for all modes o.mouse = 'a' -- Enable mouse input -o.mousemoveevent = true -- Allow plugins to detect mouse movement o.termguicolors = true -- Enable 24bit terminal colors +g.neovide_confirm_quit = 1 -- Confirm closing neovide window when changes are unsaved -- Other interface settings o.clipboard = 'unnamedplus' -- Use system clipboard by default @@ -33,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' -- 'showbreak' character should appear before virtual indentention + sbr = true -- Line break character should appear before virtual indentention } o.hlsearch = true -- Highlight search results o.scrolloff = 5 -- Margin between cursor and screen top/bottom @@ -47,7 +43,6 @@ 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 = '-', @@ -102,9 +97,13 @@ local zoom_notification = nil --- "Zoom" by changing gui font size --- @param delta integer function _G.zoom(delta) + local size = fn.substitute(o.guifont, [[^.*:h\([^:]*\).*$]], [[\1]], '') + size = size + delta + local guifont = fn.substitute(o.guifont, [[:h\([^:]*\)]], ':h' .. size, '') + o.guifont = guifont local properties = { + title = 'Font size', hide_from_history = true, - render = 'compact', on_close = function() zoom_notification = nil end @@ -112,21 +111,7 @@ function _G.zoom(delta) if zoom_notification ~= nil then properties.replace = zoom_notification.id end - - local message - if vim.g.neovide_scale_factor ~= nil then - properties.title = 'Zoom' - vim.g.neovide_scale_factor = vim.g.neovide_scale_factor + (delta * 0.05) - message = 'Zoom set to ' .. vim.g.neovide_scale_factor * 100 .. '%' - else - properties.title = 'Font size' - local size = fn.substitute(o.guifont, [[^.*:h\([^:]*\).*$]], [[\1]], '') - size = size + delta - local guifont = fn.substitute(o.guifont, [[:h\([^:]*\)]], ':h' .. size, '') - o.guifont = guifont - message = 'Font size set to ' .. size - end - zoom_notification = vim.notify(message, vim.log.levels.INFO, properties) + zoom_notification = vim.notify('Changing font size to ' .. size, vim.log.levels.INFO, properties) end local function zoom_in() @@ -137,69 +122,60 @@ local function zoom_out() zoom(-1) end -if not workman then - vim.keymap.set('n', 'j', 'gj') - vim.keymap.set('n', 'k', 'gk') -end -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' }) +-- 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'}, + } --- Quickfix mappings -local function quickfix_toggle() - for _, win in pairs(vim.fn.getwininfo()) do - if win.quickfix == 1 then - vim.cmd.cclose() - return + 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'} + } end end - vim.cmd.copen() -end -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)' }) -vim.keymap.set('t', '', '', { desc = 'Normal mode' }) - --- 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' }) - -if vim.g.neovide then - vim.keymap.set({'i', 'c'}, '', '+', { desc = 'Paste' }) - vim.keymap.set({'i', 'c'}, '', '+', { desc = 'Paste' }) - vim.keymap.set('t', '', 'pi', { desc = 'Paste' }) end +vim.cmd [[ +tnoremap +]] -- Commands vim.cmd [[ @@ -223,6 +199,11 @@ 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', @@ -244,104 +225,75 @@ vim.diagnostic.config { underline = { -- Only underline warnings and up severity = { min = vim.diagnostic.severity.WARN } - }, - virtual_text = { - severity = { min = vim.diagnostic.severity.WARN }, - }, - virtual_lines = { - current_line = true, - }, - signs = { - text = { - [vim.diagnostic.severity.ERROR] = '', - [vim.diagnostic.severity.WARN] = '', - [vim.diagnostic.severity.INFO] = '', - [vim.diagnostic.severity.HINT] = '', - }, - }, + } } +fn.sign_define('DiagnosticSignInfo', { text = '', texthl = 'DiagnosticSignInfo' }) +fn.sign_define('DiagnosticSignHint', { text = '', texthl = 'DiagnosticSignHint' }) +fn.sign_define('DiagnosticSignWarn', { text = '', texthl = 'DiagnosticSignWarn' }) +fn.sign_define('DiagnosticSignError', { text = '', texthl = 'DiagnosticSignError' }) -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(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 }) +-- netrw +-- Set special URL handler +g.netrw_browsex_viewer = 'xdg-open' -function _G.mason_path(package) +---- 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) return vim.fn.stdpath('data') .. '/mason/packages/' .. package end --- Bootstrap plugin system -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) - -require('lazy').setup({ +require'packer'.startup(function(use) + use 'wbthomason/packer.nvim' -- Themes -- - {'miikanissi/modus-themes.nvim', opts = {}}, - 'arcticicestudio/nord-vim', - 'folke/tokyonight.nvim', - {'catppuccin/nvim', name = 'catppuccin', opts = { - integrations = { - barbar = true, + use {'arcticicestudio/nord-vim', branch = 'main'} + use 'chriskempson/base16-vim' + use {'folke/tokyonight.nvim', config = function() + require'tokyonight'.setup { + style = 'night' } - }}, - 'navarasu/onedark.nvim', + 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} -- Filetype plugins -- - 'rhysd/vim-crystal', - 'bakpakin/fennel.vim', - 'mboughaba/i3config.vim', - {'OXY2DEV/markview.nvim', lazy = false, opts = { preview = { enable = false } }}, - 'mracos/mermaid.vim', - 'lifepillar/pgsql.vim', - 'digitaltoad/vim-pug', - 'ajouellette/sway-vim-syntax', - 'mfussenegger/nvim-ansible', + 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' - -- Editing - {'altermo/ultimate-autopair.nvim', branch = 'v0.6', opts = { - -- Settings for moving delimiter after cursor/Alt-E mapping - fastwarp = { - -- Don't make the cursor stay in place - nocursormove = false, - } - }}, - 'ojroques/nvim-bufdel', - {'stevearc/conform.nvim', config = function () + -- Editing -- + use 'LunarWatcher/auto-pairs' + use 'ojroques/nvim-bufdel' + use {'stevearc/conform.nvim', config = function() require'conform'.setup { - formatters_by_ft = { - html = {"prettier"}, - }, format_on_save = { lsp_fallback = true, filter = function(client) @@ -360,402 +312,102 @@ require('lazy').setup({ desc = 'Format buffer', } ) - 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() - -- Uncomment to move test output to the side instead of bottom - -- vim.g['test#neovim#term_position'] = 'vert' - vim.g['echo_command'] = 1 + 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() + vim.g['test#neovim#term_position'] = 'vert' vim.g['test#strategy'] = 'neovim' - end}, - {'julian/vim-textobj-variable-segment', dependencies = {'kana/vim-textobj-user'}}, - {'nvim-treesitter/nvim-treesitter', dependencies = {'OXY2DEV/markview.nvim'}, 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') + 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 vim.keymap.set('n', 'zR', ufo.openAllFolds) vim.keymap.set('n', 'zR', ufo.closeAllFolds) ufo.setup {} - end}, - 'hrsh7th/vim-vsnip', + end} + use 'hrsh7th/vim-vsnip' -- LSP -- - {'neovim/nvim-lspconfig', dependencies = {'saghen/blink.cmp', 'williamboman/mason-lspconfig.nvim'}, config = function() - local lspconfig = require'lspconfig' - -- Extend the LSP client capabilities advertized to servers - local capabilities = require'blink.cmp'.get_lsp_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 - vim.lsp.config('lua_ls', { - settings = { - Lua = { - runtime = { - version = 'LuaJIT', - path = { - 'lua/?.lua', - 'lua/?/init.lua', - }, - workspace = { - checkThirdParty = false, - library = { - vim.env.VIMRUNTIME - }, - }, - }, - }, - }, - }) - vim.lsp.enable({ - 'ansiblels', - 'ast_grep', - 'bashls', - 'clangd', - 'cssls', - 'html', - 'jsonls', - 'lemminx', - 'lua_ls', - 'ty', - 'vimls', - 'yamlls', - }) - end}, - {'Saghen/blink.cmp', dependencies = {'altermo/ultimate-autopair.nvim', 'rcarriga/cmp-dap'}, lazy = false, build = 'cargo build --release', opts_extend = {'sources.default'}, opts = { - keymap = { - -- Tab to select completion, enter to accept - preset = 'enter', - [''] = {'select_next', 'snippet_forward', 'fallback'}, - [''] = {'select_prev', 'snippet_backward', 'fallback'}, - [''] = {'show_signature', 'hide_signature', 'fallback'}, - }, - - enabled = function() - return vim.api.nvim_buf_get_option(0, "buftype") ~= "prompt" - or require("cmp_dap").is_dap_buffer() - end, - appearance = { - -- Use nvim-cmp highlight groups as fallback for plugins without direct support for blink.cmp - use_nvim_cmp_as_default = true, - -- Set to 'mono' for 'Nerd Font Mono' or 'normal' for 'Nerd Font' - -- Adjusts spacing to ensure icons are aligned - nerd_font_variant = 'normal', - }, - - cmdline = { - completion = { - list = { - selection = { preselect = false, auto_insert = true } - }, - menu = { - auto_show = true - }, - }, - }, - completion = { - list = { - -- Don't automatically select the first completion item - selection = { preselect = false, auto_insert = true } - }, - - accept = { - -- Disable experimental automatic bracket insertion - auto_brackets = { enabled = false } - }, - - documentation = { - -- Show documentation in the completion menu automatically - auto_show = true, - }, - - -- Show virtual text of completion result after cursor - ghost_text = { enabled = true }, - }, - - -- Experimental function signature help - signature = { - enabled = true, - window = { - -- Prefer showing signature help below cursor - direction_priority = {'s', 'n'}, - -- Don't show documentation by default - show_documentation = false, - }, - }, - - -- Default list of sources - sources = { - default = {'lsp', 'path', 'snippets'}, - per_filetype = { - ['dap-repl'] = {'dap'}, - dapui_watches = {'dap'}, - dapui_hover = {'dap'}, - }, - providers = { - dap = { - name = 'dap', - module = 'blink.compat.source', - }, - }, - }, - }}, - {'Saghen/blink.compat', lazy = true, opts = {}}, - {'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', - -- Shut the warning up - '--jvm-arg=-XX:+EnableDynamicAgentLoading', - -- 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 = { - autobuild = { enabled = false }, - }, - }, - - 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() - vim.keymap.set('n', 'lo', jdtls.organize_imports, { desc = 'Organize imports', buffer = bufnr }) - vim.keymap.set('n', 'Xm', jdtls.test_nearest_method, { desc = 'Test nearest method', buffer = bufnr }) - vim.keymap.set('n', 'Xc', jdtls.test_class, { desc = 'Test class', buffer = bufnr }) - vim.keymap.set('n', 'Xg', jdtls.tests.goto_subjects, { desc = 'Go to test', buffer = bufnr }) - vim.keymap.set('n', 'Xb', 'JdtCompile full', { desc = 'Build', buffer = bufnr }) - end, - } - - jdtls.start_or_attach(config) - end - }) - end}, - {'mrcjkb/rustaceanvim', config = function () - vim.g.rustaceanvim = { - server = { - default_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' } - }, - }, - } - }, - } - end}, - {'Saecki/crates.nvim', opts = { - lsp = { - enabled = true, - actions = true, - completion = true, - hover = true, - } - }}, - {'pmizio/typescript-tools.nvim', opts = { - settings = { - tsserver_file_preferences = { - quotePreference = 'single', - semicolons = 'remove', - convertTabsToSpaces = false, - }, - tsserver_format_options = { - semicolons = 'remove', - convertTabsToSpaces = false, - }, - tsserver_plugins = (function () - if fn.has('nvim-0.10') == 0 then return end - if vim.fn.executable('npm') == 1 and vim.system({'npm', 'list', '-g', '@styled/typescript-styled-plugin'}):wait().code == 0 then - return {'@styled/typescript-styled-plugin'} - else - return {} - end - end)(), - expose_as_code_action = 'all', - jsx_close_tag = { enable = true }, - } - }}, - {'dmmulroy/ts-error-translator.nvim', opts = {}}, - {'nvimtools/none-ls.nvim', dependencies = {'nvim-lua/plenary.nvim'}, config = function() + 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() local null_ls = require'null-ls' null_ls.setup { sources = { null_ls.builtins.diagnostics.zsh, + null_ls.builtins.code_actions.shellcheck, } } - end}, - {'Bekaboo/dropbar.nvim', lazy = false, config = function() - vim.keymap.set('n', '', require'dropbar.api'.pick, { desc = 'Navigate' }) - end}, + end} + use 'SmiteshP/nvim-navic' + use {'utilyre/barbecue.nvim', config = function() + require'barbecue'.setup { + show_modified = true, + } + end} - -- 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}, - {'akinsho/bufferline.nvim', lazy = false, opts = { - options = { - diagnostics = 'nvim_lsp', - themable = true, - hover = { - enabled = 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() + require'clear-action'.setup { + signs = { + enable = true, + combine = true, + show_count = false, }, - tab_size = 24, - max_name_length = 24, - }, - }, keys = { - {'', 'BufferLineCyclePrev', { desc = 'Next buffer' }}, - {'', 'BufferLineCycleNext', { desc = 'Previous buffer' }}, - {'', 'BufferLinePick', { desc = 'Pick buffer' }}, - {'', 'BufferLineTogglePin', { desc = 'Pin buffer' }}, - {'', 'BufDel', { desc = 'Delete buffer' }}, - {'', 'BufferLinePickClose', { desc = 'Delete picked buffer' }}, - {'', 'BufferLineMovePrevious', { desc = 'Move buffer left' }}, - {'>', 'BufferLineMoveNext', { desc = 'Move buffer right' }}, - {'b,', 'BufferLineCyclePrev', { desc = 'Next buffer' }}, - {'b.', 'BufferLineCycleNext', { desc = 'Previous buffer' }}, - {'bb', 'BufferLinePick', { desc = 'Pick buffer' }}, - {'bp', 'BufferLineTogglePin', { desc = 'Pin buffer' }}, - {'bd', 'BufDel', { desc = 'Delete buffer' }}, - {'bx', 'BufferLinePickClose', { desc = 'Delete picked buffer' }}, - {'bh', 'BufferLineMovePrev', { desc = 'Move buffer left' }}, - {'bl', 'BufferLineMoveNext', { desc = 'Move buffer right' }}, - }}, - {'Chaitanyabsprip/fastaction.nvim', opts = { - dismiss_keys = {'q', '', ''}, - keys = 'fjdkslarueiwovmcxpzbnty', - register_ui_select = false, - }, config = function(_, opts) - local fastaction = require'fastaction' - fastaction.setup(opts) - vim.keymap.set('n', 'ga', fastaction.code_action) - vim.keymap.set('n', 'la', fastaction.code_action) - end}, - {'MattesGroeger/vim-bookmarks', config = function() + popup = { enable = true }, + } + end} + use {'MattesGroeger/vim-bookmarks', config = function() vim.g.bookmark_no_default_key_mappings = 1 vim.g.bookmark_save_per_working_dir = 1 - end}, - {'kristijanhusak/vim-dadbod-ui', dependencies = {'tpope/vim-dadbod', 'kristijanhusak/vim-dadbod-completion'}, config = function() + end} + use {'kristijanhusak/vim-dadbod-ui', requires = {'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' vim.o.previewheight = 40 - end}, - {'mfussenegger/nvim-dap', dependencies = {'folke/which-key.nvim'}, config = function() + vim.api.nvim_create_autocmd('FileType', { + group = 'luarc', + pattern = {'sql','mysql','plsql'}, + callback = function() + require('cmp').setup.buffer({ sources = {{ name = 'vim-dadbod-completion' }} }) + end, + desc = 'SQL dadbod completion', + }) + end} + use {'mfussenegger/nvim-dap', config = function() local dap = require'dap' vim.fn.sign_define('DapBreakpoint', {text = '⯃', texthl = 'DiagnosticError'}) dap.adapters.codelldb = { @@ -764,7 +416,7 @@ require('lazy').setup({ executable = { --command = mason_path('codelldb') .. '/extension/adapter/codelldb', --args = {'--liblldb', mason_path('codelldb') .. '/extension/lldb/lib/liblldb.so', '--port', '${port}'}, - command = 'codelldb', + command = 'lldb', args = {'--port', '${port}'}, }, } @@ -777,8 +429,9 @@ require('lazy').setup({ host = 'localhost', port = '${port}', executable = { - command = 'js-debug-adapter', + command = 'node', args = { + mason_path('js-debug-adapter') .. '/js-debug/src/dapDebugServer.js', '${port}' }, }, @@ -836,17 +489,10 @@ require('lazy').setup({ { type = 'pwa-node', request = 'attach', - name = 'Attach to process', + name = 'Attach', processId = require'dap.utils'.pick_process, cwd = '${workspaceFolder}', }, - { - type = 'pwa-node', - request = 'attach', - name = 'Attach to port', - address = 'localhost', - port = 9229, - }, { type = 'pwa-node', request = 'launch', @@ -887,213 +533,102 @@ require('lazy').setup({ p = {dap.pause, 'Pause execution'} } } - end}, - {'mfussenegger/nvim-dap-python', dependencies = {'mfussenegger/nvim-dap'}, config = function() - require'dap-python'.setup('uv') - end}, - {'rcarriga/nvim-dap-ui', dependencies = { - 'mfussenegger/nvim-dap', - 'nvim-neotest/nvim-nio' - }, config = function() + end} + use {'rcarriga/nvim-dap-ui', 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 - vim.keymap.set('n', 'dd', dapui.toggle, { desc = 'Toggle' }) - end}, - {'theHamsta/nvim-dap-virtual-text', dependencies = {'mfussenegger/nvim-dap'}, opts = { - -- Clear virtual text when the debugger does a continue - clear_on_continue = true, - }}, - {'LiadOz/nvim-dap-repl-highlights', opts = {}}, - {'lucaSartore/nvim-dap-exception-breakpoints', dependencies = {'mfussenegger/nvim-dap'}, config = function() - vim.keymap.set('n', 'de', require'nvim-dap-exception-breakpoints', { desc = 'Exception breakpoints'}) - end}, - {'sindrets/diffview.nvim', opts = { - -- Use nicer highlighting for diffs - enhanced_diff_hl = true, - win_config = { - win_opts = { - wrap = false, - } - }, - key_bindings = { - view = { - ["gq"] = "DiffviewClose", - }, - file_panel = { - ["gq"] = "DiffviewClose", - }, - file_history_panel = { - ["gq"] = "DiffviewClose", - }, - } - }}, - {'stevearc/dressing.nvim', opts = { - input = { - -- Allow exiting insert mode in picker - insert_only = false, - win_options = { - -- Reuse telescope's highlights for windows made by dressing - winhighlight = 'NormalFloat:TelescopeNormal,FloatBorder:TelescopeBorder' - } - }, - select = { - enabled = false, - }, - }, config = function(_, opts) - vim.cmd'highlight link FloatTitle TelescopeBorder' - 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, - } - } - }}, - {'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)'}, - }}, - {'harrisoncramer/gitlab.nvim', dependencies = { - 'MunifTanjim/nui.nvim', - 'nvim-lua/plenary.nvim', - 'sindrets/diffview.nvim', - }, build = function() - require'gitlab.server'.build(true) - end, opts = { - attachment_dir = vim.fn.expand('~/Desktop/'), - keymaps = { - global = { - disable_all = true, - } - }, - popup = { - -- Backup popup input in these registers - temp_registers = {'p', 'P'} - }, - discussion_tree = { - -- Place the discussion tree at the bottom - position = 'bottom', - }, - create_mr = { - -- Mark source branch for deletion by default - delete_branch = true, - } - }, config = function(plugin, opts) - local gitlab = require('gitlab') - gitlab.setup(opts) - require'which-key'.register { - ['a'] = { - name = '+gitlab', - o = {gitlab.review, 'Review'}, - s = {gitlab.summary, 'Summary'}, - a = {gitlab.add_assignee, 'Add assignee'}, - A = {gitlab.delete_assignee, 'Remove assignee'}, - r = {gitlab.add_reviewer, 'Add reviewer'}, - R = {gitlab.delete_reviewer, 'Remove reviewer'}, - Y = {gitlab.approve, 'Approve'}, - N = {gitlab.revoke, 'Unapprove'}, - M = {gitlab.merge, 'Merge'}, - f = {gitlab.choose_merge_request, 'Pick MR'}, - n = {gitlab.create_note, 'Note'}, - m = {gitlab.create_mr, 'Create MR'}, - x = {gitlab.open_in_browser, 'Open in browser'}, - p = {gitlab.pipeline, 'Pipeline'}, - P = {gitlab.publish_all_drafts, 'Publish all drafts'}, - q = {function () - gitlab.close_review() - require'gitlab.server'.shutdown() - end, 'Close review'}, - } - } - require'which-key'.register({ - ['a'] = { - c = {gitlab.create_multiline_comment, 'Multiline comment'}, - C = {gitlab.create_comment_suggestion, 'Suggestion'}, - } - }, { mode = "v" }) - end}, - {'lewis6991/gitsigns.nvim', dependencies = {'folke/which-key.nvim'}, opts = { - on_attach = function() - local gitsigns = require'gitsigns' - vim.keymap.set('n', ']c', function() gitsigns.nav_hunk('next') end, {desc = 'Next hunk'}) - vim.keymap.set('n', '[c', function() gitsigns.nav_hunk('prev') end, {desc = 'Previous hunk'}) - - require'which-key'.register { - ['h'] = { - name = '+gitsigns', - s = {gitsigns.stage_hunk, 'Stage hunk'}, - S = {gitsigns.stage_buffer, 'Stage 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'}, - } - } + dap.listeners.before.event_terminated.dapui_config = function() + dapui.close {} end - }}, - {'junegunn/goyo.vim', config = function() - vim.g.goyo_height = '95%' - end}, - {'williamboman/mason.nvim', version = "^2.1.0", opts = {}}, - {'williamboman/mason-lspconfig.nvim', version = "^2.1.0", dependencies = {'williamboman/mason.nvim', 'neovim/nvim-lspconfig'}, opts = { - automatic_enable = false, - }}, - {'NeogitOrg/neogit', lazy = false, opts = { - disable_context_highlighting = true, - integrations = { - diffview = true, - telescope = true, - }, - signs = { - item = {"", ""}, - section = {"", ""}, - }, - }, keys = { - {'g', 'Neogit', { desc = 'Neogit' }} - }}, - {'rcarriga/nvim-notify', dependencies = {'nvim-telescope/telescope.nvim'}, opts = { - stages = 'fade', - render = 'compact', - }, config = function(_, opts) - require'notify'.setup(opts) + dap.listeners.before.event_exited.dapui_config = function() + dapui.close {} + end + 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() + 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() + }, + } + 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() + require'lsp_lines'.setup() + vim.diagnostic.config { + virtual_text = { + severity = { min = vim.diagnostic.severity.WARN }, + }, + virtual_lines = { + 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' + } vim.notify = require'notify' require'telescope'.load_extension('notify') - end}, - {'stevearc/overseer.nvim', dependencies = {'folke/which-key.nvim'}, opts = { - task_list = { - bindings = { - ['x'] = 'Stop', - ['dd'] = 'Dispose', - ['r'] = 'OverseerQuickAction restart', - [''] = false, - [''] = false, - }, - }, - }, config = function(plugin, opts) - require'overseer'.setup(opts) + end} + use {'stevearc/overseer.nvim', after = 'nvim-dap', config = function() + require'overseer'.setup() require'which-key'.register { ['r'] = { name = 'Overseer (run tasks)', - r = {'OverseerToggle bottom', 'Open' }, - R = {'OverseerToggle right', 'Open (right)' }, + r = {'OverseerToggle right', 'Open' }, + R = {'OverseerToggle bottom', 'Open (bottom)' }, n = {'OverseerRun', 'New task' }, c = {'OverseerRunCmd', 'Run shell command' }, l = {'OverseerLoadBundle!', 'Load task list'}, @@ -1101,45 +636,13 @@ require('lazy').setup({ s = {'OverseerSaveBundle', 'Save task list'} } } - 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 = 'sessions', header = {' Sessions'} }, - { type = 'bookmarks', header = {' Bookmarks'} }, - { type = 'commands', header = {' Commands'} }, - { type = 'dir', header = {' Recently used ' .. fn.getcwd()} }, - { type = 'files', header = {' Recently used'} }, - } - g.startify_bookmarks = { - { c = '~/.config/nvim/init.lua' }, - } - g.startify_commands = { - { L = {'Lazy - plugin manager', 'Lazy'} }, - { M = {'Mason - tool manager', 'Mason'} }, - } - end}, - {'nvim-telescope/telescope.nvim', dependencies = { - 'altermo/ultimate-autopair.nvim', - 'nvim-telescope/telescope-fzf-native.nvim', - 'nvim-telescope/telescope-file-browser.nvim', - 'nvim-telescope/telescope-project.nvim', - 'nvim-telescope/telescope-live-grep-args.nvim', - 'nvim-telescope/telescope-ui-select.nvim', - 'nvim-telescope/telescope-dap.nvim', - 'debugloop/telescope-undo.nvim', - 'folke/which-key.nvim', - }, config = function() + end} + use 'mhinz/vim-startify' + use {'nvim-telescope/telescope.nvim', after = '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', @@ -1166,10 +669,9 @@ require('lazy').setup({ -- TODO; check if this is right full_path = true, }, - ['ui-select'] = require'telescope.themes'.get_cursor { + ['ui-select'] = telescope.themes.get_cursor { layout_config = { height = 15, - width = 100, }, }, }, @@ -1179,7 +681,7 @@ require('lazy').setup({ name = 'Telescope', [""] = {'Telescope', 'List pickers'}, f = {'Telescope find_files', 'Files'}, - F = {'Telescope file_browser hidden=true', 'File browser'}, + F = {'Telescope file_browser', 'File browser'}, [''] = { function() vim.ui.input( @@ -1191,10 +693,9 @@ require('lazy').setup({ }, d = {'Telescope find_files find_command=fd,--type,d,-I', 'Directories'}, r = {'Telescope oldfiles', 'Recent files'}, - g = {'Telescope live_grep_args', 'Grep'}, + g = {'Telescope live_grep', 'Grep'}, G = {function() vim.ui.input({ completion = 'dir' }, function(input) - if not input then return end telescope.builtin.live_grep { search_dirs = {input} } end) end, 'Grep in subdirectory'}, @@ -1206,141 +707,656 @@ require('lazy').setup({ s = {'Telescope lsp_dynamic_workspace_symbols', 'Symbols'}, S = {'Telescope lsp_document_symbols', 'Symbols - current file'}, n = {'Telescope notify', 'Notifications'}, - m = {'Telescope man_pages sections=ALL', 'Man pages'}, + m = {'Telescope man_pages', 'Man pages'}, [':'] = {'Telescope commands', 'Commands'}, u = {'Telescope undo', 'Undo'}, - ['.'] = {'Telescope resume', 'Resume'}, } } + 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') - require'telescope'.load_extension('live_grep_args') + 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}, - {'nvim-neotest/neotest', dependencies = { - 'nvim-neotest/neotest-vim-test', - 'rouge8/neotest-rust', - }, config = function() + end} + use {'nvim-neotest/neotest', requires = {'rcasia/neotest-java', 'nvim-neotest/neotest-vim-test'}, config = function() require'neotest'.setup { adapters = { - require'neotest-vim-test' { allow_file_types = {'java'} }, - require'neotest-rust' {}, + require'neotest-java' {}, + require'neotest-vim-test' {}, } } - require'which-key'.register { - ['x'] = { - name = 'Test', - s = {'Neotest summary','Summary'}, - a = {'Neotest attach', 'Attach to running test'}, - k = {'Neotest stop', 'Stop'}, - o = {'Neotest output-panel', 'Output'} - } - } - 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, -- triggers deprecation warning - 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') + end} + use 'kyazdani42/nvim-tree.lua' + use 'hedyhli/outline.nvim' + use {'folke/which-key.nvim', config = function() require'which-key'.setup() end} - if not api.tree.is_visible() then - api.tree.open() + -- 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 + + 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 +} + +---- 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, - }) - 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'.add { - {'q', group = 'Quickfix' }, - {'l', group = 'LSP' }, - {'b', group = 'Buffer' }, - {'e', group = 'Diagnostic' }, + {'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', '!' } + } } - end}, - - -- 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'