---- 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 opt.splitright = true opt.splitbelow = 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 = "•", } ---- lualine.nvim ---- local lualine = require('lualine') local theme = require('lualine.themes.gruvbox') theme.terminal = theme.insert lualine.setup({ options = { component_separators = { left = '│', right = '│' }, section_separators = { left = '', right = '' }, theme = theme, }, sections = { lualine_a = { 'mode' }, lualine_b = { 'diagnostics' }, lualine_c = { { 'filename', path = 1, }, }, lualine_x = { { 'fileformat', cond = function() return vim.bo.fileformat ~= 'unix' end, }, { 'encoding', cond = function() return vim.bo.fileencoding ~= 'utf-8' end, }, }, lualine_y = { { 'filetype', icons_enabled = false, symbols = { modified = '', readonly = '', unnamed = '', new = '󰎔', }, } }, lualine_z = { 'searchcount', 'progress', 'location' }, }, tabline = (g.started_by_firenvim == true and {}) or { lualine_a = { 'buffers' }, lualine_z = { 'tabs' }, }, }) ---- Maps ---- vim.keymap.set("!", "", "") vim.keymap.set("v", ">", ">gv") vim.keymap.set("v", "<", "", ":nohlsearch") ---- Treesitter ---- local ts = require("nvim-treesitter.configs") ts.setup({ auto_install = true, sync_install = false, ignore_install = {}, ensure_installed = { "bash", "c", "cmake", "comment", "cpp", "css", "dockerfile", "diff", "dot", "git_config", "git_rebase", "gitattributes", "gitcommit", "gitignore", "go", "html", "htmldjango", "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 --- -- KDL -- vim.filetype.add({ extension = { kdl = "kdl" } }) -- Markdown -- vim.api.nvim_create_autocmd({ "FileType" }, { pattern = "markdown", callback = function() vim.opt_local.textwidth = 85 end, }) -- YAML -- vim.api.nvim_create_autocmd({ "FileType" }, { pattern = "yaml", callback = function() vim.opt_local.expandtab = true vim.opt_local.foldmethod = "indent" end, }) ---- formatter.nvim ---- local formatter = require("formatter") formatter.setup({ filetype = { lua = { require("formatter.filetypes.lua").stylua, }, terraform = { require("formatter.filetypes.terraform").terraformfmt, } }, ["*"] = { -- "formatter.filetypes.any" defines default configurations for any -- filetype 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 = {}, lua_ls = { settings = { Lua = { runtime = { version = "LuaJIT" }, diagnostics = { globals = { "vim" }, unusedLocalExclude = { "_*" }, }, workspace = { library = vim.api.nvim_get_runtime_file("", true), }, telemetry = { enable = false }, }, }, }, marksman = {}, pylsp = {}, rust_analyzer = {}, taplo = {}, 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() local lsp_format = false for _, client in pairs(vim.lsp.buf_get_clients()) do if client.server_capabilities.documentFormattingProvider then lsp_format = true break end end if lsp_format then vim.lsp.buf.format({ async = false }) else cmd("Format") end end, }) ---- Plugins ---- ---- 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" -- clippy -- lint.linters.clippy = { name = "clippy", cmd = "cargo", stdin = false, append_fname = false, args = { "clippy" }, stream = "stdout", ignore_exitcode = false, env = nil, parser = require("lint.parser").from_errorformat(clippy_format), } -- sqlfluff -- lint.linters.sqlfluff.args = { "lint", "--format=json", "--dialect=postgres", "-", } -- yamllint -- lint.linters.yamllint.args = { args = { "--format=parsable", "-d relaxed" }, } local 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 ipairs(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, }) 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, }) -- we want to also call linters here so we don't wait -- for the first write to happen lint.try_lint(nil, { ignore_errors = true }) 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 local 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() ---- firenvim if g.started_by_firenvim == true then vim.cmd("packadd firenvim") g.firenvim_config = { globalSettings = { alt = 'all', }, localSettings = { ['.*'] = { selector = 'textarea:not([readonly]):not([class="handsontableInput"]), div[role="textbox"]', takeover = 'never', }, ['https://github\\.com.*'] = { priority = 1, takeover = 'always', } } } vim.api.nvim_create_autocmd({ 'BufEnter' }, { pattern = "github.com_*.txt", callback = function() vim.cmd("set filetype=markdown") end }) lualine.setup({ sections = { lualine_a = { 'mode' }, lualine_b = {}, lualine_c = {}, lualine_x = { 'searchcount' }, lualine_y = { 'progress' }, lualine_z = { 'location' }, }, }) end