local cmp = require("cmp") local luasnip = require("luasnip") local cmp_nvim_lsp = require("cmp_nvim_lsp") local telescope = require("telescope") local builtin = require("telescope.builtin") local themes = require("telescope.themes") local map = vim.keymap.set local ok_autopairs, autopairs = pcall(require, "nvim-autopairs") local ok_cmp_autopairs, cmp_autopairs = pcall(require, "nvim-autopairs.completion.cmp") local ok_comment, comment = pcall(require, "Comment") local ok_flash, flash = pcall(require, "flash") local ok_oil, oil = pcall(require, "oil") vim.opt.completeopt = { "menu", "menuone", "noselect" } vim.filetype.add({ extension = { jai = "jai", }, }) local function format_tex_buffer() local result = vim.system({ "latexindent" }, { stdin = table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), "\n") .. "\n", text = true, }):wait() if result.code ~= 0 then vim.notify(result.stderr ~= "" and result.stderr or "latexindent failed", vim.log.levels.ERROR) return end local formatted = vim.split(result.stdout or "", "\n", { plain = true, trimempty = false }) if formatted[#formatted] == "" then table.remove(formatted, #formatted) end local view = vim.fn.winsaveview() vim.api.nvim_buf_set_lines(0, 0, -1, false, formatted) vim.fn.winrestview(view) end local function format_buffer() if vim.bo.filetype == "tex" and vim.fn.executable("latexindent") == 1 then format_tex_buffer() return end vim.lsp.buf.format({ async = true }) end luasnip.config.setup({}) require("luasnip.loaders.from_vscode").lazy_load() if ok_autopairs then autopairs.setup({}) end if ok_comment then comment.setup() end if ok_flash then flash.setup() end if ok_oil then oil.setup({ default_file_explorer = true, skip_confirm_for_simple_edits = true, view_options = { show_hidden = true, }, }) end telescope.setup({ extensions = { ["ui-select"] = themes.get_dropdown({}), undo = { layout_strategy = "vertical", layout_config = { preview_height = 0.6, }, side_by_side = true, }, }, }) pcall(telescope.load_extension, "ui-select") pcall(telescope.load_extension, "undo") -- Completion shortcuts. local cmp_insert_mappings = cmp.mapping.preset.insert({ [""] = cmp.mapping.scroll_docs(-4), [""] = cmp.mapping.scroll_docs(4), [""] = cmp.mapping.complete(), [""] = cmp.mapping.abort(), [""] = cmp.mapping.confirm({ select = true }), -- Accept the selected completion. }) local cmp_cmdline_mappings = cmp.mapping.preset.cmdline() -- Search and buffers. map("n", "", builtin.git_files, { desc = "Search tracked files", silent = true }) map("n", "", builtin.find_files, { desc = "Search all files", silent = true }) map("n", "f", builtin.live_grep, { desc = "Grep project", silent = true }) map("n", "/", function() builtin.current_buffer_fuzzy_find(themes.get_dropdown({ previewer = false, winblend = 10 })) end, { desc = "Search current buffer", silent = true }) map("n", "fh", builtin.help_tags, { desc = "Search help", silent = true }) map("n", "fr", builtin.oldfiles, { desc = "Recent files", silent = true }) map("n", "fu", "Telescope undo", { desc = "Undo history", silent = true }) map("n", "", builtin.buffers, { desc = "Switch buffers", silent = true }) -- File browsing. map("n", "-", "Oil", { desc = "Open parent directory", silent = true }) map("n", "e", "Oil", { desc = "Open file explorer", silent = true }) map("n", "E", function() require("oil").open(vim.fn.expand("%:p:h")) end, { desc = "Open current file directory", silent = true }) -- LSP and diagnostics. map("n", "gd", vim.lsp.buf.definition, { desc = "Go to definition", silent = true }) map("n", "gr", builtin.lsp_references, { desc = "List references", silent = true }) map("n", "gi", builtin.lsp_implementations, { desc = "List implementations", silent = true }) map("n", "K", vim.lsp.buf.hover, { desc = "Hover docs", silent = true }) map("n", "L", vim.diagnostic.open_float, { desc = "Show diagnostics", silent = true }) map({ "n", "v" }, "ca", vim.lsp.buf.code_action, { desc = "Code action", silent = true }) map("n", "rn", vim.lsp.buf.rename, { desc = "Rename symbol", silent = true }) map("n", "[d", function() vim.diagnostic.jump({ count = -1, float = true }) end, { desc = "Previous diagnostic", silent = true }) map("n", "]d", function() vim.diagnostic.jump({ count = 1, float = true }) end, { desc = "Next diagnostic", silent = true }) map("n", "q", vim.diagnostic.setloclist, { desc = "Diagnostics list", silent = true }) map("n", "fm", format_buffer, { desc = "Format buffer", silent = true }) -- LaTeX workflow. map("n", "tc", "VimtexCompile", { desc = "Compile TeX", silent = true }) map("n", "tk", "VimtexStop", { desc = "Stop TeX compile", silent = true }) map("n", "tv", "VimtexView", { desc = "Open TeX PDF", silent = true }) map("n", "to", "VimtexCompileOutput", { desc = "TeX compiler output", silent = true }) map("n", "tt", "VimtexTocToggle", { desc = "TeX table of contents", silent = true }) map("n", "te", "VimtexErrors", { desc = "TeX errors", silent = true }) map("n", "tl", "VimtexClean", { desc = "Clean TeX build files", silent = true }) -- Editing and utility shortcuts. map({ "n", "v" }, "y", '"+y', { desc = "Yank to clipboard", silent = true }) map("n", "u", "UndotreeToggle", { desc = "Toggle undo tree", silent = true }) map({ "n", "x", "o" }, "s", function() require("flash").jump() end, { desc = "Flash jump", silent = true }) map({ "n", "x", "o" }, "S", function() require("flash").treesitter() end, { desc = "Flash Tree-sitter jump", silent = true }) cmp.setup({ snippet = { expand = function(args) luasnip.lsp_expand(args.body) end, }, mapping = cmp_insert_mappings, sources = cmp.config.sources({ { name = "nvim_lsp" }, { name = "luasnip" }, { name = "path" }, }, { { name = "buffer" }, }), }) cmp.setup.cmdline("/", { mapping = cmp_cmdline_mappings, sources = { { name = "buffer" }, }, }) cmp.setup.cmdline(":", { mapping = cmp_cmdline_mappings, sources = cmp.config.sources({ { name = "path" }, }, { { name = "cmdline" }, }), }) if ok_cmp_autopairs then cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done()) end vim.diagnostic.config({ virtual_text = true, signs = true, underline = true, update_in_insert = true, }) local capabilities = cmp_nvim_lsp.default_capabilities() local servers = { ts_ls = {}, clangd = {}, gopls = { cmd = { "gopls", "serve" }, settings = { gopls = { analyses = { unusedparams = true, }, staticcheck = true, }, }, }, pyright = {}, texlab = { settings = { texlab = { build = { executable = "latexmk", args = { "-pdf", "-interaction=nonstopmode", "-synctex=1", "-file-line-error", "%f", }, onSave = true, forwardSearchAfter = false, }, chktex = { onOpenAndSave = false, onEdit = false, }, }, }, }, rust_analyzer = { cmd = { "rust-analyzer" }, settings = { ["rust-analyzer"] = { checkOnSave = { allFeatures = true, overrideCommand = { "cargo", "clippy", "--workspace", "--message-format=json", "--all-targets", "--all-features", }, }, }, }, }, ["kotlin-language-server"] = { cmd = { "kotlin-language-server" }, filetypes = { "kotlin" }, }, cmake = {}, html = {}, glsl_analyzer = {}, lua_ls = {}, zls = {}, } for server, config in pairs(servers) do config.capabilities = capabilities vim.lsp.config(server, config) vim.lsp.enable(server) end vim.api.nvim_create_autocmd("FileType", { group = vim.api.nvim_create_augroup("UserTreesitterHighlight", { clear = true }), callback = function(args) pcall(vim.treesitter.start, args.buf) end, desc = "Start Tree-sitter highlighting when a parser is available", })