-- Enables byte-compiled, cached Lua module loading vim.loader.enable() -- Options ---------- vim.o.undofile = true vim.o.backup = true vim.opt.backupdir:remove "." vim.opt.shortmess:append "A" vim.opt.shortmess:append "c" vim.opt.diffopt:append "linematch:60" vim.o.mouse = "a" vim.o.ignorecase = true vim.o.smartcase = true vim.o.smartindent = true -- TODO: check that vim.o.cindent = true -- tabstop and shiftwidth are also set locally by individual filetypes vim.o.tabstop = 4 vim.o.shiftwidth = 4 vim.o.inccommand = "split" vim.o.scrolloff = 1 vim.o.sidescrolloff = 5 vim.o.colorcolumn = "80" vim.o.cursorline = true vim.o.title = true vim.opt.wildmode = { "longest:full", "full" } vim.opt.completeopt = { "menu", "menuone", "preview", "noinsert", "noselect" } -- Use ripgrep vim.o.grepprg = vim.g.ripgrep_path .. " --vimgrep --smart-case" vim.o.grepformat = "%f:%l:%c:%m," .. vim.o.grepformat vim.o.termguicolors = true vim.o.background = "dark" vim.o.updatetime = 1000 -- Mode already shown by the status line vim.o.showmode = false vim.opt.listchars = { extends = ">", nbsp = "+", precedes = "<", tab = " ", trail = "-", } vim.wo.list = true -- Polyglot ----------- vim.g.polyglot_disabled = { "ftdetect", "autoindent", "sensible", } -- Leaders ---------- vim.g.maplocalleader = "," vim.g.mapleader = ";" -- Misc ------- -- From neovim#14420 -- Restores the position of previously opened files -- Inspired by: https://github.com/ethanholz/nvim-lastplace local last_cursor_pos_augroup = vim.api.nvim_create_augroup("LastCursorPos", {}) vim.api.nvim_create_autocmd("BufReadPost", { group = last_cursor_pos_augroup, desc = "Restore the position of previously opened files", callback = function(opts) if vim.tbl_contains({ "quickfix", "nofile", "help" }, vim.bo.buftype) then return end if vim.tbl_contains({ "gitcommit", "gitrebase", "svn", "hgcommit" }, vim.bo.filetype) then return end -- If a line has already been specified on the command line, we are done -- nvim file +num if vim.fn.line "." > 1 then return end -- If the last line is set and the less than the last line in the buffer if vim.fn.line [['"]] > 0 and vim.fn.line [['"]] <= vim.fn.line "$" then if vim.fn.line "w$" == vim.fn.line "$" then -- if the last line in the current buffer is also the last line visible -- in this window vim.cmd [[normal! g`"]] elseif vim.fn.line "$" - vim.fn.line [['"]] > ((vim.fn.line "w$" - vim.fn.line "w0") / 2) - 1 then -- if we're not at the bottom of the file, center the cursor on the -- screen after we make the jump vim.cmd [[normal! g`"zz]] else -- otherwise, show as much context as we can by jumping to the end of -- the file and then to the mark. If we pressed zz here, there would be -- blank lines at the bottom of the screen. We intentionally leave the -- last line blank by pressing so the user has a clue that they -- are near the end of the file. vim.cmd [[normal! G'"]] end end end, }) vim.api.nvim_create_autocmd("TextYankPost", { desc = "Highlight yanked text", callback = function(opts) vim.highlight.on_yank() end, }) vim.g.tex_flavor = "latex" vim.g.gruvbox_italic = 1 vim.cmd "colorscheme gruvbox" -- Mappings ----------- local mapopts = { noremap = true, silent = true } vim.fn["camelcasemotion#CreateMotionMappings"] "" vim.keymap.set("n", "yof", function() if vim.opt_local.formatoptions:get().a then vim.opt_local.formatoptions:remove "a" print ":setlocal formatoptions-=a" else vim.opt_local.formatoptions:append "a" print ":setlocal formatoptions+=a" end end, mapopts) -- Plugins ---------- -- Gitsigns require("gitsigns").setup { on_attach = function(bufnr) local gs = package.loaded.gitsigns local function map(mode, l, r, opts) opts = vim.tbl_extend("force", { noremap = true, buffer = buffnr, silent = true, }, opts or {}) vim.keymap.set(mode, l, r, opts) end -- Navigation map('n', ']c', function() if vim.wo.diff then return ']c' end vim.schedule(function() gs.next_hunk() end) return '' end, { expr = true }) map('n', '[c', function() if vim.wo.diff then return '[c' end vim.schedule(function() gs.prev_hunk() end) return '' end, { expr = true }) -- Actions map('n', 'hs', gs.stage_hunk, { desc = "Stage Hunk" }) map('n', 'hr', gs.reset_hunk, { desc = "reset Hunk" }) map('v', 'hs', function() gs.stage_hunk { vim.fn.line('.'), vim.fn.line('v') } end, { desc = "Stage hunk" }) map('v', 'hr', function() gs.reset_hunk { vim.fn.line('.'), vim.fn.line('v') } end, { desc = "Reset hunk" }) map('n', 'hS', gs.stage_buffer, { desc = "Stage buffer" }) map('n', 'hu', gs.undo_stage_hunk, { desc = "Undo stage hunk" }) map('n', 'hR', gs.reset_buffer, { desc = "Reset buffer" }) map('n', 'hp', gs.preview_hunk, { desc = "Preview hunk" }) map('n', 'hb', function() gs.blame_line { full = true } end, { desc = "Blame line" }) map('n', 'tb', gs.toggle_current_line_blame, { desc = "Toggle current line blame" }) map('n', 'hd', gs.diffthis, { desc = "Diff this" }) map('n', 'hD', function() gs.diffthis('~') end, { desc = "Diff this against ~" }) map('n', 'td', gs.toggle_deleted, { desc = "Toggle deleted" }) -- Text object map({ 'o', 'x' }, 'ih', ':Gitsigns select_hunk', { desc = "Select hunk" }) end, } -- Treesitter require("nvim-treesitter.configs").setup { parser_install_dir = vim.fn.stdpath("data") .. "/site", highlight = { enable = true, }, incremental_selection = { enable = true, keymaps = { init_selection = "gnn", node_incremental = "grn", scope_incremental = "grc", node_decremental = "grm", }, }, indent = { enable = true, disable = { "rust" }, }, matchup = { enable = true, }, refactor = { highlight_definitions = { enable = true }, navigation = { enable = true }, }, textobjects = { lsp_interop = { enable = true, border = "none", peek_definition_code = { ["df"] = "@function.outer", ["dF"] = "@class.outer", }, }, move = { enable = true, goto_next_start = { ["]m"] = "@function.outer", ["]]"] = "@class.outer", }, goto_next_end = { ["]M"] = "@function.outer", ["]["] = "@class.outer", }, goto_previous_start = { ["[m"] = "@function.outer", ["[["] = "@class.outer", }, goto_previous_end = { ["[M"] = "@function.outer", ["[]"] = "@class.outer", }, }, select = { enable = true, keymaps = { -- You can use the capture groups defined in textobjects.scm ["af"] = "@function.outer", ["if"] = "@function.inner", ["aF"] = "@call.outer", ["iF"] = "@call.inner", ["ac"] = "@class.outer", ["ic"] = "@class.inner", ["aC"] = "@comment.outer", ["iC"] = "@comment.inner", ["ab"] = "@block.outer", ["ib"] = "@block.inner", ["aa"] = "@parameter.outer", ["ia"] = "@parameter.inner", }, }, swap = { enable = true, swap_next = { ["a"] = "@parameter.inner", }, swap_previous = { ["A"] = "@parameter.inner", }, }, }, } vim.o.foldmethod = "expr" vim.o.foldexpr = "nvim_treesitter#foldexpr()" vim.o.foldlevel = 99 vim.api.nvim_set_hl(0, "TSCurrentScope", { bg = vim.g.current_gruvbox_colors.dark0_soft[1], }) vim.api.nvim_set_hl(0, "TSDefinition", { bg = vim.g.current_gruvbox_colors.faded_blue[1], }) vim.api.nvim_set_hl(0, "TSDefinitionUsage", { bg = vim.g.current_gruvbox_colors.faded_aqua[1], }) -- Treesitter highlight groups vim.api.nvim_set_hl(0, "@attribute", { link = "Macro" }) vim.api.nvim_set_hl(0, "@error", { link = "ErrorMsg" }) vim.api.nvim_set_hl(0, "@text.diff.add", { link = "diffAdded" }) vim.api.nvim_set_hl(0, "@text.diff.delete", { link = "diffRemoved" }) vim.api.nvim_set_hl(0, "@text.strong", { bold = true }) vim.api.nvim_set_hl(0, "@text.emphasis", { italic = true }) vim.api.nvim_set_hl(0, "@text.underline", { underline = true }) vim.api.nvim_set_hl(0, "@text.strike", { strikethrough = true }) vim.api.nvim_set_hl(0, "@text.environment", { link = "Macro" }) vim.api.nvim_set_hl(0, "@text.note", { link = "ModeMsg" }) vim.api.nvim_set_hl(0, "@text.warning", { link = "WarningMsg" }) vim.api.nvim_set_hl(0, "@text.warning", { link = "ErrorMsg" }) vim.api.nvim_set_hl(0, "@tag.attribute", { link = "@attribute" }) vim.api.nvim_set_hl(0, "@tag.delimiter", { link = "@punctuation.delimiter" }) -- nvim-cmp local cmp = require "cmp" cmp.setup { snippet = { expand = function(args) vim.fn["vsnip#anonymous"](args.body) end, }, mapping = cmp.mapping.preset.insert { [""] = cmp.mapping.confirm { select = false }, }, sources = cmp.config.sources({ { name = "nvim_lsp" }, { name = "vsnip" }, { name = "latex_symbols" }, { name = "calc" }, }, { { name = "path" }, { name = "treesitter" }, }, { { name = "tmux" }, { name = "spell" }, -- Use \k for iskeyword because of UTF-8 { name = "buffer", option = { keyword_pattern = [[\k\+]] } }, }), } -- cmp.setup.cmdline("/", { -- sources = { -- { name = "buffer", option = { keyword_pattern = [[\k\+]] } }, -- }, -- mapping = cmp.mapping.preset.cmdline {}, -- }) -- cmp.setup.cmdline(":", { -- sources = cmp.config.sources { -- { name = "cmdline" }, -- }, -- mapping = cmp.mapping.preset.cmdline {}, -- }) -- Telescope require("telescope").setup { extensions = { ["ui-select"] = { require("telescope.themes").get_dropdown(), }, }, } require("telescope").load_extension "ui-select" local telescope_builtin = require("telescope.builtin") vim.keymap.set("n", "fb", telescope_builtin.buffers, mapopts) vim.keymap.set("n", "ff", telescope_builtin.find_files, mapopts) vim.keymap.set("n", "fg", telescope_builtin.live_grep, mapopts) vim.keymap.set("n", "fh", telescope_builtin.help_tags, mapopts) vim.keymap.set("n", "fo", telescope_builtin.oldfiles, mapopts) vim.keymap.set("n", "fs", telescope_builtin.spell_suggest, mapopts) vim.keymap.set("n", "ft", telescope_builtin.treesitter, mapopts) -- Oil.nvim require("oil").setup() vim.keymap.set("n", "-", require("oil").open, { desc = "Open parent directory" }) -- Disable netrw vim.g.loaded_netrw = 1 vim.g.loaded_netrwPlugin = 1 -- Lualine require("lualine").setup { options = { component_separators = "", icons_enabled = false, section_separators = "", }, sections = { lualine_c = { "filename", { "lsp_progress", display_components = { "lsp_client_name", { "title", "percentage", "message" } }, }, }, }, } -- VSnip vim.keymap.set("i", "", "vsnip#jumpable(1) ? '(vsnip-jump-next)' : ''", { silent = true, expr = true }) vim.keymap.set("s", "", "vsnip#jumpable(1) ? '(vsnip-jump-next)' : ''", { silent = true, expr = true }) vim.keymap.set( "i", "", "vsnip#jumpable(-1) ? '(vsnip-jump-prev)' : ''", { silent = true, expr = true } ) vim.keymap.set( "s", "", "vsnip#jumpable(-1) ? '(vsnip-jump-prev)' : ''", { silent = true, expr = true } ) -- OSCyank -- Text yanked into the "t register gets copied using OSC52 escape sequences -- (e.g. goes through SSH) vim.api.nvim_create_autocmd("TextYankPost", { desc = "Setup for OSCYank", callback = function(opts) if vim.v.event.regname == "t" then vim.cmd [[OSCYankReg t]] end end, }) -- Diffview require("diffview").setup { use_icons = false, enhanced_diff_hl = true, } -- Notify vim.cmd [[highlight link NotifyERRORBorder DiagnosticError]] vim.cmd [[highlight link NotifyERRORIcon DiagnosticError]] vim.cmd [[highlight link NotifyERRORTitle DiagnosticError]] vim.cmd [[highlight link NotifyWARNBorder DiagnosticWarn]] vim.cmd [[highlight link NotifyWARNIcon DiagnosticWarn]] vim.cmd [[highlight link NotifyWARNTitle DiagnosticWarn]] vim.cmd [[highlight link NotifyINFOBorder DiagnosticInfo]] vim.cmd [[highlight link NotifyINFOIcon DiagnosticInfo]] vim.cmd [[highlight link NotifyINFOTitle DiagnosticInfo]] vim.cmd [[highlight link NotifyDEBUGBorder DiagnosticHint]] vim.cmd [[highlight link NotifyDEBUGIcon DiagnosticHint]] vim.cmd [[highlight link NotifyDEBUGTitle DiagnosticHint]] vim.cmd [[highlight link NotifyDEBUGBorder GruvboxPurple]] vim.cmd [[highlight link NotifyDEBUGIcon GruvboxPurple]] vim.cmd [[highlight link NotifyDEBUGTitle GruvboxPurple]] require("notify").setup { stages = "static" } vim.notify = require("notify") -- Comment require("Comment").setup {} -- Indent Blankline vim.api.nvim_set_hl(0, "IndentBlanklineContextChar", { fg = vim.g.current_gruvbox_colors.aqua[1], }) require("indent_blankline").setup { show_current_context = true, show_current_context_start = true, } -- Local config local function isModuleAvailable(name) if package.loaded[name] then return true else for _, searcher in ipairs(package.searchers or package.loaders) do local loader = searcher(name) if type(loader) == "function" then package.preload[name] = loader return true end end return false end end vim.opt.runtimepath:append "~/.config/nvim" if isModuleAvailable "local_config" then require "local_config" end