---- Aliases ---- local cmd = vim.cmd local g = vim.g local opt = vim.opt ---- General Config ---- opt.mouse = "a" opt.tabstop = 2 opt.shiftwidth = 2 opt.number = true opt.breakindent = true opt.showmatch = true opt.ignorecase = true opt.smartcase = true opt.joinspaces = false opt.showmode = false opt.hidden = true opt.backup = false opt.writebackup = false opt.swapfile = false opt.shortmess:append({ I = true }) -- whichwrap -- left/right keys can traverse up/down opt.whichwrap:append("<,>,[,]") opt.cmdheight = 2 opt.showcmd = true g.mapleader = " " ---- Terminal ---- vim.api.nvim_create_autocmd({ "TermOpen" }, { callback = function() if vim.l then vim.l.number = false end end, }) ---- Theming ---- opt.termguicolors = true opt.background = "dark" g.gruvbox_italic = true cmd.colorscheme("gruvbox") opt.listchars = { eol = "↲", tab = "▶▹", nbsp = "␣", extends = "…", trail = "•", } -- vim-airline config --- g.airline_powerline_fonts = true g.airline_theme = "powerlineish" g["airline#extensions#tabline#enabled"] = 1 g["airline#extensions#tabline#left_sep"] = " " g["airline#extensions#tabline#left_alt_sep"] = "|" ---- Maps ---- vim.keymap.set("!", "", "") vim.keymap.set("v", ">", ">gv") vim.keymap.set("v", "<", "", ":nohlsearch") ---- Treesitter ---- local ts = require("nvim-treesitter.configs") ts.setup({ ensure_installed = { "bash", "c", "cmake", "comment", "cpp", "css", "dockerfile", "diff", "dot", "git_config", "git_rebase", "gitattributes", "gitcommit", "gitignore", "go", "html", "http", "ini", "javascript", "json", "kdl", "kotlin", "latex", "lua", "make", "markdown", "markdown_inline", "passwd", "perl", "php", "python", "regex", "rust", "scss", "sql", "terraform", "toml", "typescript", "vim", "yaml", }, highlight = { enable = true, indent = true }, }) ---- Filetypes --- vim.filetype.add({ extension = { kdl = "kdl" } }) ---- formatter.nvim ---- local formatter = require("formatter") formatter.setup({ filetype = { lua = { require("formatter.filetypes.lua").stylua, }, ["*"] = { require("formatter.filetypes.any").remove_trailing_whitespace, }, }, }) ---- LSP ---- local lsp = require("lspconfig") -- Use an on_attach function to only map the following keys -- after the language server attaches to the current buffer local on_lsp_attach = function(client, bufnr) vim.keymap.set("n", "gD", vim.lsp.buf.declaration) vim.keymap.set("n", "gd", vim.lsp.buf.definition) vim.keymap.set("n", "K", vim.lsp.buf.hover) vim.keymap.set("n", "gi", vim.lsp.buf.implementation) vim.keymap.set("n", "", vim.lsp.buf.signature_help) vim.keymap.set("n", "D", vim.lsp.buf.type_definition) vim.keymap.set("n", "rn", vim.lsp.buf.rename) vim.keymap.set("n", "ca", vim.lsp.buf.code_action) vim.keymap.set("n", "gr", vim.lsp.buf.references) vim.keymap.set("n", "e", vim.diagnostic.open_float) vim.keymap.set("n", "[d", vim.diagnostic.goto_prev) vim.keymap.set("n", "]d", vim.diagnostic.goto_next) vim.keymap.set("n", "q", vim.diagnostic.setloclist) vim.keymap.set("n", "", function() vim.lsp.buf.format({ async = true }) end) end -- Use a loop to conveniently call 'setup' on multiple servers and -- map buffer local keybindings when the language server attaches local servers = { clangd = {}, eslint = {}, gopls = {}, jsonls = {}, kotlin_language_server = {}, marksman = {}, pylsp = {}, rust_analyzer = {}, texlab = {}, tflint = {}, tsserver = {}, } -- Setup loop moved to the cmp section, since calling setup multiple times -- overrides the previous calls. -- Auto format on save vim.api.nvim_create_autocmd({ "BufWritePre" }, { callback = function() cmd("Format") vim.lsp.buf.format({ async = false }) end, }) ---- Plugins ---- -- Go g.ale_go_golangci_lint_options = "" g.ale_go_golangci_lint_package = 1 ---- nvim-lint ---- local lint = require("lint") local clippy_format = "%E%f:%l:%c: %\\d%#:%\\d%# %.%\\{-}" .. "error:%.%\\{-} %m,%W%f:%l:%c: %\\d%#:%\\d%# %.%\\{-}" .. "warning:%.%\\{-} %m,%C%f:%l %m,%-G,%-G" .. "error: aborting %.%#,%-G" .. "error: Could not compile %.%#,%E" .. "error: %m,%Eerror[E%n]: %m,%-G" .. "warning: the option `Z` is unstable %.%#,%W" .. "warning: %m,%Inote: %m,%C %#--> %f:%l:%c" lint.linters.clippy = { cmd = "cargo clippy", stdin = false, append_fname = true, args = {}, stream = "stdout", ignore_exitcode = false, env = nil, parser = require("lint.parser").from_errorformat(clippy_format), } linters = { bash = { "shellcheck" }, dockerfile = { "hadolint" }, go = { "golangcilint" }, python = { "flake8" }, rust = { "clippy" }, sql = { "sqlfluff" }, yaml = { "yamllint" }, } -- set linters -- lint.linters_by_ft = linters -- set autocommands -- for ft, ft_linters in pairs(linters) do local on_change = false local on_write = false for l in pairs(ft_linters) do if lint.linters.l.stdin then on_change = true else on_write = true end end if on_change then vim.api.nvim_create_autocmd({ "FileType" }, { pattern = ft, callback = function() vim.api.nvim_create_autocmd({ "TextChanged" }, { callback = function() lint.try_lint(nil, { ignore_errors = true }) end, }) end, lint.try_lint(nil, { ignore_errors = true }), }) end if on_write then vim.api.nvim_create_autocmd({ "FileType" }, { pattern = ft, callback = function() vim.api.nvim_create_autocmd({ "BufWritePost" }, { callback = function() lint.try_lint(nil, { ignore_errors = true }) end, }) end, }) end end ---- LuaSnip local luasnip = require("luasnip") require("luasnip.loaders.from_lua").lazy_load() luasnip.config.set_config({ store_selection_keys = "", }) vim.keymap.set({ "i", "s" }, "", function() if luasnip.expand_or_jumpable() then luasnip.expand_or_jump() else vim.api.nvim_feedkeys( vim.api.nvim_replace_termcodes("", true, false, true), "n", -- noremap to avoid infinite recursion true ) end end, { silent = true }) vim.keymap.set({ "i", "s" }, "", function() if luasnip.jumpable(-1) then luasnip.jump(-1) end end, { silent = true }) ---- completion-nvim local cmp = require("cmp") cmp.setup({ snippet = { expand = function(args) luasnip.lsp_expand(args.body) end, }, window = { -- completion = cmp.config.window.bordered(), -- documentation = cmp.config.window.bordered(), }, mapping = cmp.mapping.preset.insert({ [""] = cmp.mapping.scroll_docs(-4), [""] = cmp.mapping.scroll_docs(4), [""] = cmp.mapping.complete(), [""] = cmp.mapping.abort(), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items. [""] = cmp.mapping.confirm({ select = true }), }), sources = cmp.config.sources({ { name = "nvim_lsp" }, { name = "luasnip" }, { name = "path" }, { name = "buffer" }, }), }) -- Setup lspconfig. local capabilities = vim.lsp.protocol.make_client_capabilities() lsp.util.default_config = vim.tbl_deep_extend("force", lsp.util.default_config, { capabilities = capabilities }) for server, add_to_config in pairs(servers) do config = { on_attach = on_lsp_attach, flags = { debounce_text_changes = 150, }, } for k, v in pairs(add_to_config) do config[k] = v end lsp[server].setup(config) end ---- git-blame.nvim g.gitblame_enabled = 0 ---- gitsigns.nvim require("gitsigns").setup({ on_attach = function(bufnr) local gs = package.loaded.gitsigns -- Navigation vim.keymap.set("n", "]c", function() if vim.wo.diff then return "]c" end vim.schedule(function() gs.next_hunk() end) return "" end, { expr = true }) vim.keymap.set("n", "[c", function() if vim.wo.diff then return "[c" end vim.schedule(function() gs.prev_hunk() end) return "" end, { expr = true }) -- Actions vim.keymap.set({ "n", "v" }, "hs", ":Gitsigns stage_hunk") vim.keymap.set({ "n", "v" }, "hr", ":Gitsigns reset_hunk") vim.keymap.set("n", "hS", gs.stage_buffer) vim.keymap.set("n", "hu", gs.undo_stage_hunk) vim.keymap.set("n", "hR", gs.reset_buffer) vim.keymap.set("n", "hp", gs.preview_hunk) vim.keymap.set("n", "hb", function() gs.blame_line({ full = true }) end) vim.keymap.set("n", "tb", gs.toggle_current_line_blame) vim.keymap.set("n", "hd", gs.diffthis) vim.keymap.set("n", "hD", function() gs.diffthis("~") end) vim.keymap.set("n", "td", gs.toggle_deleted) -- Text object vim.keymap.set({ "o", "x" }, "ih", ":Gitsigns select_hunk") end, }) ---- Comment.nvim require("Comment").setup() ---- vim-markdown g.vim_markdown_no_default_key_mappings = 1 g.vim_markdown_folding_disabled = 1 g.vim_markdown_toml_frontmatter = 1 ---- Telescope local telescope = require("telescope") telescope.setup({ defaults = { file_ignore_patterns = { "%.avif", "%.jpg", "%.pdf", "%.png", "%.webp" }, }, pickers = { find_files = { hidden = true, }, }, }) telescope.load_extension("fzy_native") telescope.load_extension("luasnip") local builtin = require("telescope.builtin") vim.keymap.set("n", "f", builtin.fd) vim.keymap.set("n", "b", builtin.buffers) vim.keymap.set("n", "/", builtin.current_buffer_fuzzy_find) vim.keymap.set("n", "g", builtin.live_grep) vim.keymap.set("n", "cg", builtin.grep_string) vim.keymap.set("n", ":", builtin.commands) vim.keymap.set("n", "s", telescope.extensions.luasnip.luasnip) ---- nvim-dap local dap = require("dap") vim.fn.sign_define("DapBreakpoint", { text = "🟥", texthl = "", linehl = "", numhl = "" }) vim.fn.sign_define("DapStopped", { text = "▶️", texthl = "", linehl = "", numhl = "" }) -- Set keymaps to control the debugge vim.keymap.set("n", "dc", dap.continue) vim.keymap.set("n", "do", dap.step_over) vim.keymap.set("n", "di", dap.step_into) vim.keymap.set("n", "dO", dap.step_out) vim.keymap.set("n", "db", dap.toggle_breakpoint) vim.keymap.set("n", "dB", function() dap.set_breakpoint(vim.fn.input("Breakpoint condition: ")) end) local dapui = require("dapui") 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 -- nvim-dap-go require("dap-go").setup() ---- web-devicons require("nvim-web-devicons").setup()