-- Do fast startup if we can do local ok, _ = pcall(require, 'impatient') if not ok then vim.notify('impatient unavailable') end end ---- Built in settings ---- -- Create a convenient aliases local o = vim.o local g = vim.g local fn = vim.fn local opt = vim.opt -- Define functions for keymaps local function noremap(mode, key, mapping) -- no recursion, silent local opts = { noremap = true, silent = true } vim.api.nvim_set_keymap(mode, key, mapping, opts) end local function inoremap(key, mapping) noremap('i', key, mapping) end -- Set font if fn.hostname() == 'sharpy' then o.guifont = 'Iosevka Term Slab,Iosevka:h10' else o.guifont = 'Iosevka Term Slab Extended,Iosevka:h9' end if fn.hostname() == 'tappy' then g.neovide_refresh_rate = 144 end opt.guicursor:append('a:blinkon1000') -- 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 o.hlsearch = false -- Don't 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.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.conceallevel = 2 -- Hide concealed text, use replacement if defined opt.listchars = { -- Symbols for whitespace chars when 'list' is enabled tab = '🭰 ', trail = '-', nbsp = '+' } 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 -- Set key g.mapleader = ' ' vim.cmd 'filetype plugin indent on' -- Enable persistent undo if fn.has('persistent_undo') then o.undodir = fn.expand('~/.local/share/nvim/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 local zoom_notification = nil --- "Zoom" by changing gui font size --- @param delta integer local function 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 zoom_notification = vim.notify('Changing font size to ' .. size, vim.log.levels.INFO, { title = 'Font size', replace = zoom_notification, hide_from_history = true, }) 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'} } which_key.register { [''] = {'set number! relativenumber!', 'Toggle relative numbers'} } which_key.register { [''] = {'set number!', 'Toggle line numbers'} } which_key.register { [''] = {'h', 'Go to the left window'} } which_key.register { [''] = {'l', 'Go to the right window'} } which_key.register { [''] = {'n', 'Go to the up window'} } which_key.register { [''] = {'e', 'Go to the down window'} } which_key.register { ['+'] = {zoom_in, "Zoom in"} } which_key.register { ['-'] = {zoom_out, "Zoom out"} } end end -- Do workman remappings noremap('', 'n', 'gj') noremap('', 'j', 'n') noremap('', 'e', 'gk') noremap('', 'k', 'e') -- Commands vim.cmd [[ command! Light colorscheme base16-atelier-sulphurpool-light command! Dark colorscheme nord ]] -- Autocommands vim.cmd [[ augroup vimrc au! " Restore file position from previous session au BufReadPost * \ if line("'\"") > 1 && line("'\"") <= line("$") && &ft !~# 'commit' \ | exe "normal! g`\"" \ | endif " Highlight yanked text au TextYankPost * silent! lua vim.highlight.on_yank() au User StartifyReady noremap n gj| noremap e gk " Recompile plugin config cache when vimrc is updated au BufWritePost */.config/nvim/init.lua source | PackerCompile augroup END ]] --local au = vim.api.nvim_create_augroup --local augroup = vim.api.nvim_create_augroup('luarc', {clear = true}) --au('User', { pattern = 'StartifyReady', group = augroup, callback = function(cmd) -- vim.keymap.set('', 'n', 'gj', {silent = true, buffer = true}) -- vim.keymap.set('', 'e', 'gk', {silent = true, buffer = true}) --end}) --au('BufWritePost', { -- pattern = '*/.config/nvim/init.lua', -- group = augroup, -- command = 'source | PackerCompile' --}) --au('TextYankPost', { pattern = '*', group = augroup, callback = vim.highlight.on_yank }) --au('BufWritePost', { pattern = '*/.config/nvim/init.lua', command = 'source | PackerCompile' }) --au('BufReadPost', { pattern = '*', group = augroup, command = function() -- local line = vim.fn.line -- if line[['\"]] > 1 && line[['\"]] <= line'$' && o.ft ~= 'commit' then -- vim.cmd'normal g`"' -- end --end }) -- Diagnostics vim.diagnostic.config { -- Configure underlining diagnostics underline = { -- Only underline warnings and up severity = vim.diagnostic.severity.WARN } } -- 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 require'packer'.startup(function(use) use 'wbthomason/packer.nvim' -- Themes -- use {'arcticicestudio/nord-vim', branch = 'main'} use 'chriskempson/base16-vim' use 'folke/tokyonight.nvim' 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} -- Filetype plugins -- use 'rhysd/vim-crystal' use 'editorconfig/editorconfig-vim' use 'mboughaba/i3config.vim' use 'plasticboy/vim-markdown' use 'mracos/mermaid.vim' use 'ajouellette/sway-vim-syntax' use 'cespare/vim-toml' use 'rust-lang/rust.vim' -- Editing -- use 'jiangmiao/auto-pairs' use 'ojroques/nvim-bufdel' use 'yuttie/comfortable-motion.vim' use {'mizlan/iswap.nvim', config = function() require'iswap'.setup{} require'which-key'.register{['s'] = {'ISwapWith','Swap'}} end} use 'bfredl/nvim-luadev' -- lua scratchpad use 'tpope/vim-repeat' use 'tpope/vim-sleuth' -- spellsitter: syntax aware spellchecking use {'lewis6991/spellsitter.nvim', config = function() require'spellsitter'.setup() end} 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'}} use {'nvim-treesitter/nvim-treesitter', run = ':TSUpdate'} use 'hrsh7th/vim-vsnip' -- LSP -- use 'neovim/nvim-lspconfig' use 'hrsh7th/nvim-cmp' use 'hrsh7th/cmp-nvim-lsp' use 'hrsh7th/cmp-buffer' use 'hrsh7th/cmp-path' use 'hrsh7th/cmp-cmdline' use 'simrat39/rust-tools.nvim' use {'jose-elias-alvarez/null-ls.nvim', requires = {'nvim-lua/plenary.nvim'}, config = function () local null_ls = require'null-ls' null_ls.setup { sources = { null_ls.builtins.code_actions.shellcheck, null_ls.builtins.diagnostics.shellcheck, } } end} -- UI elements -- use 'vim-airline/vim-airline' use 'vim-airline/vim-airline-themes' use 'romgrk/barbar.nvim' use {'MattesGroeger/vim-bookmarks', config = function() vim.g.bookmark_save_per_working_dir = 1 end} use {'stevearc/dressing.nvim', config = function() vim.cmd'highlight link FloatTitle TelescopeBorder' require'dressing'.setup { input = { winhighlight = 'NormalFloat:TelescopeNormal,FloatBorder:TelescopeBorder' }, select = { enabled = false, telescope = require'telescope.themes'.get_cursor() }, } end} use 'j-hui/fidget.nvim' 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 = false } 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 {'luukvbaal/stabilize.nvim', config = function() require'stabilize'.setup() end} use 'mhinz/vim-startify' use {'nvim-telescope/telescope.nvim', after = 'which-key.nvim', config = function() require'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'] = { require'telescope.themes'.get_cursor() }, }, } require'which-key'.register { ["f"] = { name = 'Telescope', [""] = {'Telescope', 'List pickers'}, f = {'Telescope find_files', 'Files'}, F = {'Telescope file_browser', 'File browser'}, d = {'Telescope find_files find_command=fd,--type,d,-I', 'Directories'}, r = {'Telescope oldfiles', 'Recent files'}, g = {'Telescope live_grep', 'Grep'}, b = {'Telescope buffers', 'Buffers'}, e = {'Telescope diagnostics', 'Diagnostics'}, h = {'Telescope help_tags', 'Help page'}, p = {'Telescope project', 'Projects'}, s = {'Telescope lsp_dynamic_workspace_symbols', 'Symbols'}, n = {'Telescope notify', 'Notifications'}, m = {'Telescope man_pages', 'Man pages'}, [':'] = {'Telescope commands', 'Commands'}, } } end} use {'nvim-telescope/telescope-fzf-native.nvim', run = 'make', config = function() require'telescope'.load_extension('fzf') end} use {'nvim-telescope/telescope-file-browser.nvim', config = function () require'telescope'.load_extension('file_browser') end} use {'nvim-telescope/telescope-project.nvim', config = function () require'telescope'.load_extension('project') end} use {'nvim-telescope/telescope-ui-select.nvim', config = function () require'telescope'.load_extension('ui-select') end} use 'kyazdani42/nvim-tree.lua' use 'simrat39/symbols-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 'antoinemadec/FixCursorHold.nvim' use 'lewis6991/impatient.nvim' -- speeds up load times -- 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 ---- barbar ---- require'which-key'.register { [''] = {'BufferPrevious', 'Next buffer'}, [''] = {'BufferNext', 'Previous buffer'}, [''] = {'BufferPick', 'Pick buffer'}, [''] = {'BufferPin', 'Pin buffer'}, [''] = {'BufferClose', 'Delete buffer'}, [''] = {'BufferMovePrevious', 'Move buffer left'}, ['>'] = {'BufferMoveNext', 'Move buffer right'}, } ---- devicons ---- require'nvim-web-devicons'.setup { default = true } ---- editorconfig ---- g.EditorConfig_exclude_patterns = {'fugitive://.*'} ---- fidget ---- require'fidget'.setup {} ---- fugitive ---- require'which-key'.register {['g'] = {'vert Git', 'Git information'}} ---- gitsigns ---- require'gitsigns'.setup {} ---- 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' cmp.setup { preselect = cmp.PreselectMode.None, snippet = { expand = function(args) vim.fn['vsnip#anonymous'](args.body) end, }, mapping = { -- 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'}), -- 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 = 'vsnip' }, }, -- Experimental features experimental = { -- Show completion result as virtual text ghost_text = true, }, } local capabilities = require'cmp_nvim_lsp'.update_capabilities(vim.lsp.protocol.make_client_capabilities()) ---- lsp: language servers ---- --- Performs keymaps and other setup specific to buffers with LSP enabled --- @param bufnr number local function on_attach(_client, bufnr) require'which-key'.register({ g = { d = {vim.lsp.buf.definition, 'Goto definition'}, D = {vim.lsp.buf.implementation, 'Goto implementation'}, a = {vim.lsp.buf.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'}, } }, {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({ ['=1.0 g.rustfmt_emit_files = 1 -- Use nigtly rustfmt for unstable settings g.rustfmt_command = 'rustup run nightly rustfmt' -- use cargo-lints if available local checkOnSave = {}; if fn.executable('cargo-lints') == 1 then checkOnSave = { overrideCommand = {"cargo", "lints", "clippy", "--workspace", "--message-format=json", "--all-targets"} } else checkOnSave = { -- Use clippy for error checking command = "clippy", -- Also run checks for tests allTargets = true, } end ---- 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, on_attach = on_attach, settings = { ['rust-analyzer'] = { cargo = { -- Load OUT_DIR when running check on save, needed for proc macros loadOutDirsFromCheck = true, }, checkOnSave = checkOnSave, diagnostics = { -- Disable diagnostics with false positives disabled = {'unresolved-import'}; }, procMacro = { -- Enable proc macro support enable = true, } } } } } ---- 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 ---- vim.g.symbols_outline = { -- Don't display preview automatically auto_preview = false, -- Don't highlight the hovered item highlight_hovered_item = false, -- Width should be in colums, not percent relative_width = false, -- width of the symbols window width = 30, } require'which-key'.register({['o'] = {'SymbolsOutline', '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, }, git = { -- Don't hide .gitignore'd files by default ignore = false, }, -- 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 = {}, -- 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 = '🗋' }, }, }, -- Open on startup open_on_setup = true, -- Match tree cwd to vim's cwd update_cwd = true, } vim.cmd'highlight NvimTreeOpenedFile guifg=NONE gui=italic' vim.api.nvim_create_autocmd('ColorScheme', { group = 'vimrc', desc = 'Change NvimTreeOpenedFile highlight', command = 'highlight NvimTreeOpenedFile guifg=NONE gui=italic' }) require'which-key'.register{['t'] = {'NvimTreeFindFileToggle', 'Nvim Tree'}} ---- treesitter ---- require'nvim-treesitter.configs'.setup { -- Configure the nvim-ts-autotag plugin autotag = { enable = true, }, -- TODO; Pick list manually ensure_installed = {'lua', 'html', 'c', 'cpp', 'nix', 'vim', 'rust', 'markdown'}, highlight = { enable = true, disable = 'rust' }, incremental_selection = { enable = true }, } g.nord_italic = 1 g.nord_italicize_comments = 1 g.nord_underline = 1 vim.cmd [[ colorscheme nord ]]