-- Enable experimental faster module loader vim.loader.enable() ---- Built in settings ---- -- Create a convenient aliases local o = vim.o local g = vim.g local fn = vim.fn local opt = vim.opt -- Whether to enable workman remappings local workman = false -- Set font o.guifont = 'IosevkaTermSlab Nerd Font,IosevkaTerm Nerd Font,Iosevka Term Slab,Iosevka:h10:#e-subpixelantialias' vim.g.neovide_floating_z_height = 1 if fn.hostname() == 'tappy' then g.neovide_refresh_rate = 144 end opt.guicursor:append('a:blinkon1000-blinkoff1000-blinkwait1000') -- Blink cursor once a second for all modes o.mouse = 'a' -- Enable mouse input 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 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 } o.hlsearch = true -- Highlight search results o.scrolloff = 5 -- Margin between cursor and screen top/bottom o.showmatch = true -- Highlight matching brackets o.splitright = true -- Open new windows below o.splitbelow = true -- Open new windows to the right o.splitkeep = 'screen' -- Keep window position when creating splits o.title = true -- Set title of terminal window o.updatetime = 300 -- Write swap file every 300 ms (supposedly reduces delays) 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 opt.listchars = { -- Symbols for whitespace chars when 'list' is enabled tab = '🭰 ', trail = '-', nbsp = '+' } opt.fillchars = { -- Characters to fill certain types of empty space with diff = ' ', fold = ' ', foldopen = '', foldsep = ' ', foldclose = '' } opt.diffopt:append({'indent-heuristic', 'algorithm:histogram'}) if fn.has('nvim-0.10') then o.smoothscroll = true -- Scroll by screen lines instead of physical lines opt.display:append('lastline') end o.tabstop = 4 -- A physical tab is 4 characters wide o.shiftwidth = 4 -- A unit of indentention is 4 levels wide o.wrapmargin = 0 -- Disable hard line wrapping o.textwidth = 0 -- Comments lines should wrap at 100 chars o.laststatus = 3 -- Use one global status bar -- Set key g.mapleader = ' ' g.maplocalleader = '\\' vim.cmd 'filetype plugin indent on' o.exrc = true -- Load .nvim.lua .nvimrc and .exrc files -- Enable persistent undo if fn.has('persistent_undo') then o.undodir = fn.stdpath('data') .. '/undo' o.undofile = true end -- Use rg as grep program if fn.executable('rg') then o.grepprg = 'rg --vimgrep --smart-case --hidden' o.grepformat = '%f:%l:%c:%m' end if vim.fn.executable('darkman') then local mode = vim.trim(vim.fn.system('darkman get')) if mode == 'dark' or mode == 'light' then vim.o.background = mode end end 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, on_close = function() zoom_notification = nil end } if zoom_notification ~= nil then properties.replace = zoom_notification.id end zoom_notification = vim.notify('Changing font size to ' .. size, vim.log.levels.INFO, properties) end local function zoom_in() zoom(1) end 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'}, } 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 end vim.cmd [[ tnoremap ]] -- Commands vim.cmd [[ command! Light set background=light command! Dark set background=dark ]] -- Autocommands local augroup = vim.api.nvim_create_augroup('luarc', {clear = true}) local au = function(autocmd, opts) opts.group = augroup vim.api.nvim_create_autocmd(autocmd, opts) end au('User', { pattern = 'StartifyReady', callback = function() if workman then vim.keymap.set('', 'n', 'gj', {silent = true, buffer = true}) vim.keymap.set('', 'e', 'gk', {silent = true, buffer = true}) end 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', }) au('BufReadPost', { callback = function() local mark = vim.api.nvim_buf_get_mark(0, '"') local lcount = vim.api.nvim_buf_line_count(0) if mark[1] > 0 and mark[1] <= lcount then pcall(vim.api.nvim_win_set_cursor, 0, mark) end end, desc = 'Remember cursor position across restarts' }) -- Diagnostics vim.diagnostic.config { -- Configure underlining diagnostics underline = { -- Only underline warnings and up severity = { min = vim.diagnostic.severity.WARN } } } 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' }) -- netrw -- Set special URL handler g.netrw_browsex_viewer = 'xdg-open' ---- 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 require'packer'.startup(function(use) use 'wbthomason/packer.nvim' -- Themes -- use {'arcticicestudio/nord-vim', branch = 'main'} use 'chriskempson/base16-vim' use {'folke/tokyonight.nvim', config = function() require'tokyonight'.setup { style = 'night' } 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 -- 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 -- use 'LunarWatcher/auto-pairs' use 'ojroques/nvim-bufdel' use {'stevearc/conform.nvim', config = function() require'conform'.setup { format_on_save = { lsp_fallback = true, filter = function(client) return client.name == 'rust-analyzer' end } } vim.api.nvim_create_user_command( 'Conform', function() require'conform'.format { lsp_fallback = true, } end, { 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() 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 vim.keymap.set('n', 'zR', ufo.openAllFolds) vim.keymap.set('n', 'zR', ufo.closeAllFolds) ufo.setup {} end} use '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() local null_ls = require'null-ls' null_ls.setup { sources = { null_ls.builtins.diagnostics.zsh, null_ls.builtins.code_actions.shellcheck, } } end} use 'SmiteshP/nvim-navic' use {'utilyre/barbecue.nvim', config = function() require'barbecue'.setup { show_modified = true, } end} -- 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, }, 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} 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 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 = { type = 'server', port = '${port}', executable = { --command = mason_path('codelldb') .. '/extension/adapter/codelldb', --args = {'--liblldb', mason_path('codelldb') .. '/extension/lldb/lib/liblldb.so', '--port', '${port}'}, command = 'lldb', args = {'--port', '${port}'}, }, } dap.adapters.sh = { type = 'executable', command = mason_path('bash-debug-adapter') .. '/bash-debug-adapter' } dap.adapters['pwa-node'] = { type = 'server', host = 'localhost', port = '${port}', executable = { command = 'node', args = { mason_path('js-debug-adapter') .. '/js-debug/src/dapDebugServer.js', '${port}' }, }, } dap.configurations.cpp = { { name = 'Launch file', type = 'codelldb', request = 'launch', program = function() return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') end, cwd = '${workspaceFolder}', stopOnEntry = true, }, } dap.configurations.rust = dap.configurations.cpp dap.configurations.c = dap.configurations.cpp dap.configurations.sh = { { name = 'Bash debugger', type = 'sh', request = 'launch', program = '${file}', cwd = '${fileDirname}', pathBashdb = mason_path('bash-debug-adapter') .. '/extension/bashdb_dir/bashdb', pathBashdbLib = mason_path('bash-debug-adapter') .. '/extension/bashdb_dir', pathBash = 'bash', pathCat = 'cat', pathMkfifo = 'mkfifo', pathPkill = 'pkill', env = {}, args = function() return vim.fn.split(vim.fn.input('Arguments: ', '', 'file')) end, }, } dap.configurations.javascript = { { type = 'pwa-node', request = 'launch', name = 'Launch current file', program = '${file}', cwd = '${workspaceFolder}', }, { type = 'pwa-node', request = 'launch', name = 'Launch file', program = function() return vim.fn.input('Path to file: ', vim.fn.getcwd() .. '/', 'file') end, cwd = '${workspaceFolder}', }, { type = 'pwa-node', request = 'attach', name = 'Attach', processId = require'dap.utils'.pick_process, cwd = '${workspaceFolder}', }, { type = 'pwa-node', request = 'launch', name = 'Debug Mocha Tests', -- trace = true, -- include debugger info runtimeExecutable = 'node', runtimeArgs = { './node_modules/mocha/bin/mocha', }, rootPath = '${workspaceFolder}', cwd = '${workspaceFolder}', console = 'integratedTerminal', internalConsoleOptions = 'neverOpen', } } dap.configurations.typescript = dap.configurations.javascript local function conditional_breakpoint() vim.ui.input({prompt = 'Breakpoint condition'}, function(condition) if not condition then return end dap.toggle_breakpoint(condition) end) end require'which-key'.register { ['d'] = { name = 'Debug', c = {dap.continue, 'Continue/start'}, s = {dap.terminate, 'Stop'}, b = {dap.toggle_breakpoint, 'Breakpoint'}, B = {conditional_breakpoint, 'Conditional breakpoint'}, e = {function() dap.set_exception_breakpoints('default') end, 'Exception breakpoints'}, o = {dap.step_over, 'Step over'}, i = {dap.step_into, 'Step into'}, O = {dap.step_out, 'Step out'}, r = {dap.step_back, 'Step back'}, R = {dap.reverse_continue, 'Continue backwards'}, C = {dap.run_to_cursor, 'Continue to cursor'}, p = {dap.pause, 'Pause execution'} } } end} use {'rcarriga/nvim-dap-ui', config = function() local dapui, dap = require'dapui', require'dap' dapui.setup() dap.listeners.after.event_initialized.dapui_config = function() dapui.open {} end dap.listeners.before.event_terminated.dapui_config = function() dapui.close {} end 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} use {'stevearc/overseer.nvim', after = 'nvim-dap', config = function() require'overseer'.setup() require'which-key'.register { ['r'] = { name = 'Overseer (run tasks)', r = {'OverseerToggle right', 'Open' }, R = {'OverseerToggle bottom', 'Open (bottom)' }, n = {'OverseerRun', 'New task' }, c = {'OverseerRunCmd', 'Run shell command' }, l = {'OverseerLoadBundle!', 'Load task list'}, L = {'OverseerLoadBundle', 'Load and start task list'}, s = {'OverseerSaveBundle', 'Save task list'} } } 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.setup { defaults = { sorting_strategy = 'ascending', mappings = { n = { n = 'move_selection_next', e = 'move_selection_previous', }, i = { [''] = 'which_key', }, }, }, extensions = { fzf = { override_generic_sorter = true, override_file_sorter = true, }, file_browser = { hijack_netrw = false, respect_gitignore = false, }, project = { -- TODO; check if this is right full_path = true, }, ['ui-select'] = telescope.themes.get_cursor { layout_config = { height = 15, }, }, }, } require'which-key'.register { ["f"] = { name = 'Telescope', [""] = {'Telescope', 'List pickers'}, f = {'Telescope find_files', 'Files'}, F = {'Telescope file_browser', 'File browser'}, [''] = { function() vim.ui.input( { completion = 'dir' }, function(input) telescope.builtin.find_files { search_dirs = {input} } end ) end, 'Files in subdirectory' }, d = {'Telescope find_files find_command=fd,--type,d,-I', 'Directories'}, r = {'Telescope oldfiles', 'Recent files'}, g = {'Telescope live_grep', 'Grep'}, G = {function() vim.ui.input({ completion = 'dir' }, function(input) telescope.builtin.live_grep { search_dirs = {input} } end) end, 'Grep in subdirectory'}, b = {'Telescope buffers', 'Buffers'}, e = {'Telescope diagnostics', 'Diagnostics'}, h = {'Telescope help_tags', 'Help page'}, o = {'Telescope options', 'Options'}, p = {'Telescope project', 'Projects'}, 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'}, [':'] = {'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() 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} -- 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, {'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', '!' } } } }), }) 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'