vim.g.mapleader = " " vim.g.maplocalleader = "," -- FIX to create spell dir if not existent local spelldir = vim.fn.stdpath("data") .. "/site/spell" if not vim.loop.fs_stat(spelldir) then vim.fn.mkdir(spelldir, "p") end vim.opt.autoindent = true vim.opt.backupdir = { vim.fn.stdpath("state") .. "/nvim/backup//" } -- don't store backup in files dir vim.opt.clipboard = "unnamedplus" -- sync with system clipboard vim.opt.conceallevel = 2 vim.opt.expandtab = true -- spaces instead of tabs vim.opt.guifont = "Fira Code Nerd Font:h1" vim.opt.ignorecase = true vim.opt.mouse = "a" -- mouse for all modes vim.opt.number = true vim.opt.relativenumber = true vim.opt.scrolloff = 4 -- lines of context vim.opt.shiftround = true -- round indent vim.opt.shiftwidth = 0 -- use tabstop value vim.opt.shortmess:append({ c = true }) vim.opt.signcolumn = "yes" vim.opt.smartcase = true vim.opt.splitbelow = true vim.opt.splitright = true vim.opt.tabstop = 2 vim.opt.termguicolors = true vim.opt.undofile = true vim.opt.undolevels = 10000 vim.opt.updatetime = 300 vim.opt_local.spell = true vim.opt_local.spelllang = { "en", "de_20" } -- all English regions and new German spelling require("catppuccin").setup({ compile_path = vim.fn.stdpath("cache") .. "/catppuccin", -- fix issue of writing to nix store integrations = { which_key = true, }, }) vim.cmd.colorscheme("catppuccin-macchiato") vim.o.timeout = true vim.o.timeoutlen = 500 local wk = require("which-key") require("noice").setup({ lsp = { -- override markdown rendering so that **cmp** and other plugins use **Treesitter** override = { ["vim.lsp.util.convert_input_to_markdown_lines"] = true, ["vim.lsp.util.stylize_markdown"] = true, ["cmp.entry.get_documentation"] = true, }, progress = { enabled = false, }, }, -- you can enable a preset for easier configuration presets = { bottom_search = true, -- use a classic bottom cmdline for search command_palette = true, -- position the cmdline and popupmenu together long_message_to_split = true, -- long messages will be sent to a split inc_rename = false, -- enables an input dialog for inc-rename.nvim lsp_doc_border = false, -- add a border to hover docs and signature help }, }) require("telescope").load_extension("zoxide") wk.register({ f = { name = "find", f = { "Telescope find_files", "find file" }, z = { "Telescope zoxide list", "find location" }, l = { "Telescope current_buffer_fuzzy_find", "find line" }, g = { "Telescope live_grep", "live grep" }, b = { "Telescope buffers", "find buffer" }, }, }, { prefix = "" }) -- To get fzf loaded and working with telescope, you need to call -- load_extension, somewhere after setup function: require("telescope").load_extension("fzf") require("neogit").setup({ disable_commit_confirmation = true, }) wk.register({ g = { "Neogit", "git" }, }, { prefix = "" }) require("nvim-treesitter.configs").setup({ sync_install = false, auto_install = false, highlight = { enable = true, additional_vim_regex_highlighting = true, }, }) local lspkind = require("lspkind") local cmp = require("cmp") local luasnip = require("luasnip") cmp.setup({ formatting = { format = lspkind.cmp_format({ mode = "symbol", -- show only symbol annotations maxwidth = 50, -- prevent the popup from showing more than provided characters ellipsis_char = "...", -- when popup menu exceed maxwidth, the truncated part would show ellipsis_char instead symbol_map = { Copilot = "", }, }), }, snippet = { -- REQUIRED - you must specify a snippet engine expand = function(args) require("luasnip").lsp_expand(args.body) end, }, mapping = 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 }), [""] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_next_item() elseif luasnip.expand_or_jumpable() then luasnip.expand_or_jump() else fallback() end end, { "i", "s" }), [""] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_prev_item() elseif luasnip.jumpable(-1) then luasnip.jump(-1) else fallback() end end, { "i", "s" }), }), sources = { { name = "buffer", priority = 1 }, { name = "copilot", priority = 8 }, { name = "luasnip", priority = 7 }, { name = "nvim_lsp", priority = 9 }, { name = "orgmode", priority = 9 }, }, }) ---merge tables ---@param ... table[] ---@return table local function table_merge(...) local tables_to_merge = { ... } assert(#tables_to_merge > 1, "There should be at least two tables to merge them") for k, t in ipairs(tables_to_merge) do assert(type(t) == "table", string.format("Expected a table as function parameter %d", k)) end local result = tables_to_merge[1] for i = 2, #tables_to_merge do local from = tables_to_merge[i] for k, v in pairs(from) do if type(v) == "table" then result[k] = result[k] or {} result[k] = table_merge(result[k], v) else result[k] = v end end end return result end -- Provides the Format, FormatWrite, FormatLock, and FormatWriteLock commands require("formatter").setup({ -- Enable or disable logging logging = true, -- Set the log level log_level = vim.log.levels.WARN, -- All formatter configurations are opt-in filetype = { -- Formatter configurations for filetype "lua" go here -- and will be executed in order lua = { -- "formatter.filetypes.lua" defines default configurations for the -- "lua" filetype require("formatter.filetypes.lua").stylua, }, nix = { require("formatter.filetypes.nix").nixpkgs_fmt, }, python = { require("formatter.filetypes.python").black, }, rust = { require("formatter.filetypes.rust").rustfmt, }, sh = { require("formatter.filetypes.sh").shfmt, }, toml = { require("formatter.filetypes.toml").taplo, }, yaml = { require("formatter.filetypes.yaml").yamlfmt, }, -- HACK to use specific formatters only when specified alejandra = { require("formatter.filetypes.nix").alejandra, }, isort = { require("formatter.filetypes.python").isort, }, -- Use the special "*" filetype for defining formatter configurations on -- any filetype ["*"] = { -- "formatter.filetypes.any" defines default configurations for any -- filetype require("formatter.filetypes.any").remove_trailing_whitespace, }, }, }) vim.api.nvim_create_user_command("Fmt", function(opts) local params = vim.split(opts.args, "%s+", { trimempty = true }) local filetype = vim.bo.filetype vim.cmd("set filetype=" .. params[1]) -- fake filetype vim.cmd(":Format") vim.cmd("set filetype=" .. filetype) -- restore original filetype end, { nargs = 1, complete = function() local languages = { nix = { "alejandra" }, python = { "isort" }, } return languages[vim.bo.filetype] or {} end, }) wk.register({ ["="] = { "Format", "format (formatter)" }, }, { noremap = true, silent = true }) local lsp_lines = require("lsp_lines") lsp_lines.setup() -- Disable virtual_text since it's redundant due to lsp_lines. vim.diagnostic.config({ virtual_text = false, }) -- The nvim-cmp almost supports LSP's capabilities so You should advertise it to LSP servers.. local capabilities = require("cmp_nvim_lsp").default_capabilities() require("lspsaga").setup({ symbol_in_winbar = { enable = false, }, }) local lspconfig = require("lspconfig") local on_attach_def = function(_, bufnr) wk.register({ K = { "Lspsaga hover_doc ++quiet", "show info" }, [""] = { l = { name = "lsp", d = { "Lspsaga show_cursor_diagnostics", "open diagnostic window" }, n = { "Lspsaga diagnostic_jump_next", "next error" }, p = { "Lspsaga diagnostic_jump_prev", "prev error" }, c = { "Lspsaga code_action", "code action" }, r = { "Lspsaga rename", "rename" }, i = { "Lspsaga hover_doc ++keep", "show info (sticky)" }, f = { function() vim.lsp.buf.format({ async = true }) end, "format (lsp)", mode = { "n", "v" }, }, }, w = { name = "workspace", a = { vim.lsp.buf.add_workspace_folder, "add workspace folder" }, r = { vim.lsp.buf.remove_workspace_folder, "remove workspace folder" }, l = { function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, "list workspace folders", }, }, t = { name = "toggle", l = { lsp_lines.toggle, "lsp lines" }, }, }, g = { name = "goto", d = { "Lspsaga peek_definition", "definition" }, t = { "Lspsaga peek_type_definition", "type defininition" }, h = { "Lspsaga lsp_finder", "lsp finder" }, }, }, { buffer = bufnr, silent = true }) end local lspconfig_default_options = { on_attach = on_attach_def, capabilities = capabilities, flags = { debounce_text_changes = 100, }, } ---function to add default options to lspconfig ---@param lsp string ---@param options table ---@return nil local function lspconfig_setup(lsp, options) local final_options = table_merge(lspconfig_default_options, options) lspconfig[lsp].setup(final_options) end local servers = { "nil_ls", "pylsp", "rust_analyzer", "ruff_lsp" } for _, lsp in ipairs(servers) do lspconfig_setup(lsp, {}) end lspconfig_setup("lua_ls", { on_attach = on_attach_def, capabilities = capabilities, settings = { Lua = { runtime = { -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim) version = "LuaJIT", }, diagnostics = { -- Get the language server to recognize the `vim` global globals = { "vim" }, }, workspace = { -- Make the server aware of Neovim runtime files library = vim.api.nvim_get_runtime_file("", true), checkThirdParty = false, }, -- Do not send telemetry data containing a randomized but unique identifier telemetry = { enable = false, }, format = { enable = false, }, }, }, }) require("dashboard").setup({ theme = "hyper", config = { packages = { enable = false }, week_header = { enable = true, }, }, }) require("lualine").setup({ options = { icons_enabled = true, theme = "auto", component_separators = "|", section_separators = { left = "", right = "" }, disabled_filetypes = { statusline = {}, winbar = {}, }, ignore_focus = {}, always_divide_middle = true, globalstatus = false, refresh = { statusline = 1000, tabline = 1000, winbar = 1000, }, }, sections = { lualine_a = { { "mode", separator = { left = "" }, right_padding = 2 }, }, lualine_b = { "branch", "diff", "diagnostics" }, lualine_c = { "filename", "lsp_progress" }, lualine_x = { "encoding", "fileformat", "filetype" }, lualine_y = { "progress" }, lualine_z = { { "location", separator = { right = "" }, left_padding = 2 }, }, }, inactive_sections = { lualine_a = {}, lualine_b = {}, lualine_c = { "filename" }, lualine_x = { "location" }, lualine_y = {}, lualine_z = {}, }, tabline = {}, winbar = {}, inactive_winbar = {}, extensions = {}, }) require("Comment").setup() require("nvim-treesitter.configs").setup({ context_commentstring = { enable = true, }, }) require("nvim-surround").setup({}) require("nvim-treesitter.configs").setup({ textsubjects = { enable = true, prev_selection = ",", -- (Optional) keymap to select the previous selection keymaps = { ["."] = "textsubjects-smart" }, }, }) require("copilot").setup({ suggestion = { enabled = false }, panel = { enabled = false }, }) vim.api.nvim_create_autocmd("VimEnter", { desc = "Disable Copilot by default on startup", command = "Copilot disable", }) require("copilot_cmp").setup() local orgmode = require("orgmode") -- Load custom treesitter grammar for org filetype orgmode.setup_ts_grammar() -- Treesitter configuration require("nvim-treesitter.configs").setup({ -- If TS highlights are not enabled at all, or disabled via `disable` prop, -- highlighting will fallback to default Vim syntax highlighting highlight = { enable = true, -- Required for spellcheck, some LaTex highlights and -- code block highlights that do not have ts grammar additional_vim_regex_highlighting = { "org" }, }, }) orgmode.setup({ org_agenda_files = { "~/Notes/org" }, org_default_notes_file = "~/Notes/org/refile.org", }) require("gitsigns").setup() require("nvim-lastplace").setup({ lastplace_ignore_buftype = { "quickfix", "nofile", "help" }, lastplace_ignore_filetype = { "gitcommit", "gitrebase", "svn", "hgcommit" }, lastplace_open_folds = true, }) require("nvim-autopairs").setup() -- disable netrw at the very start of your init.lua (strongly advised) vim.g.loaded_netrw = 1 vim.g.loaded_netrwPlugin = 1 -- set termguicolors to enable highlight groups vim.opt.termguicolors = true -- empty setup using defaults require("nvim-tree").setup() wk.register({ t = { "NvimTreeFindFileToggle", "nvim tree" }, }, { prefix = "t", silent = true }) require("smartcolumn").setup({ colorcolumn = 120, disabled_filetypes = { "help", "text", "markdown", "dashboard" }, })