From 08297376a85a1719518507e54fca9de954d2376a Mon Sep 17 00:00:00 2001 From: Petri Hienonen Date: Thu, 23 May 2024 13:56:00 +0300 Subject: Agenix configuration --- home/nvim/autocommands.lua | 272 ++++++++++++++++++++++++++++++++++ home/nvim/default.nix | 93 ++++++++++++ home/nvim/keymaps.lua | 86 +++++++++++ home/nvim/lsp.lua | 305 +++++++++++++++++++++++++++++++++++++++ home/nvim/options.lua | 93 ++++++++++++ home/nvim/plugins/dap.lua | 147 +++++++++++++++++++ home/nvim/plugins/mini.lua | 14 ++ home/nvim/plugins/other.lua | 5 + home/nvim/plugins/treesitter.lua | 81 +++++++++++ home/nvim/plugins/undotree.lua | 1 + home/nvim/plugins/which.lua | 6 + 11 files changed, 1103 insertions(+) create mode 100644 home/nvim/autocommands.lua create mode 100644 home/nvim/default.nix create mode 100644 home/nvim/keymaps.lua create mode 100644 home/nvim/lsp.lua create mode 100644 home/nvim/options.lua create mode 100644 home/nvim/plugins/dap.lua create mode 100644 home/nvim/plugins/mini.lua create mode 100644 home/nvim/plugins/other.lua create mode 100644 home/nvim/plugins/treesitter.lua create mode 100644 home/nvim/plugins/undotree.lua create mode 100644 home/nvim/plugins/which.lua (limited to 'home/nvim') diff --git a/home/nvim/autocommands.lua b/home/nvim/autocommands.lua new file mode 100644 index 0000000..b8bf173 --- /dev/null +++ b/home/nvim/autocommands.lua @@ -0,0 +1,272 @@ +local augroup = vim.api.nvim_create_augroup("UserConfig", {}) + +vim.api.nvim_create_autocmd("TextYankPost", { + desc = "Highlight when yanking (copying) text", + group = vim.api.nvim_create_augroup("kickstart-highlight-yank", { clear = true }), + callback = function() vim.highlight.on_yank() end, +}) + +vim.api.nvim_create_autocmd({ "BufWritePre" }, { + pattern = { "*" }, + command = [[%s/\s\+$//e]], +}) + +-- Return to last edit position when opening files +vim.api.nvim_create_autocmd("BufReadPost", { + group = augroup, + callback = function() + local mark = vim.api.nvim_buf_get_mark(0, '"') + local lcount = vim.api.nvim_buf_line_count(0) + if mark[1] > 0 and mark[1] <= lcount then pcall(vim.api.nvim_win_set_cursor, 0, mark) end + end, +}) + +-- Auto-close terminal when process exits +vim.api.nvim_create_autocmd("TermClose", { + group = augroup, + callback = function() + if vim.v.event.status == 0 then vim.api.nvim_buf_delete(0, {}) end + end, +}) + +-- Disable line numbers in terminal +vim.api.nvim_create_autocmd("TermOpen", { + group = augroup, + callback = function() + vim.opt_local.number = false + vim.opt_local.relativenumber = false + vim.opt_local.signcolumn = "no" + end, +}) + +-- Auto-resize splits when window is resized +vim.api.nvim_create_autocmd("VimResized", { + group = augroup, + callback = function() vim.cmd("tabdo wincmd =") end, +}) + +local og_virt_text +local og_virt_line + +vim.api.nvim_create_autocmd({ "CursorMoved", "DiagnosticChanged" }, { + group = vim.api.nvim_create_augroup("diagnostic_only_virtlines", { clear = true }), + callback = function() + if og_virt_line == nil then og_virt_line = vim.diagnostic.config().virtual_lines end + + -- ignore if virtual_lines.current_line is disabled + if not (og_virt_line and og_virt_line.current_line) then + if og_virt_text then + vim.diagnostic.config({ virtual_text = og_virt_text }) + og_virt_text = nil + end + return + end + + if og_virt_text == nil then og_virt_text = vim.diagnostic.config().virtual_text end + + local lnum = vim.api.nvim_win_get_cursor(0)[1] - 1 + + if vim.tbl_isempty(vim.diagnostic.get(0, { lnum = lnum })) then + vim.diagnostic.config({ virtual_text = og_virt_text }) + else + vim.diagnostic.config({ virtual_text = false }) + end + end, +}) + +vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("lsp-attach", { clear = true }), + callback = function(event) + local map = function(keys, func, desc) + vim.keymap.set("n", keys, func, { buffer = event.buf, desc = "LSP: " .. desc }) + end + + local client = vim.lsp.get_client_by_id(event.data.client_id) + + if client and client:supports_method("textDocument/implementation") then + -- defaults: + -- https://neovim.io/doc/user/news-0.11.html#_defaults + map("gl", vim.diagnostic.open_float, "Open Diagnostic Float") + map("K", vim.lsp.buf.hover, "Hover Documentation") + map("gs", vim.lsp.buf.signature_help, "Signature Documentation") + map("gD", vim.lsp.buf.declaration, "Goto Declaration") + map("la", vim.lsp.buf.code_action, "Code Action") + map("lr", vim.lsp.buf.rename, "Rename all references") + map("lf", vim.lsp.buf.format, "Format") + map( + "v", + "vsplit | lua vim.lsp.buf.definition()", + "Goto Definition in Vertical Split" + ) + map("gd", vim.lsp.buf.definition, "Goto Definition") + map("gr", vim.lsp.buf.references, "Goto References") + map("gI", vim.lsp.buf.implementation, "Goto Implementation") + end + + if client and client:supports_method("textDocument/completion") then + vim.lsp.completion.enable(true, client.id, event.buf, { + autotrigger = true, + convert = function(item) return { abbr = item.label:gsub("%b()", "") } end, + }) + vim.keymap.set("i", "", function() vim.lsp.completion.get() end) + client.server_capabilities.completionProvider = client.server_capabilities.completionProvider or {} + local trigger_chars = {} + for i = 32, 126 do + table.insert(trigger_chars, string.char(i)) + end + client.server_capabilities.completionProvider.triggerCharacters = vim.list_extend( + client.server_capabilities.completionProvider.triggerCharacters or {}, + trigger_chars + ) + end + + if client and client:supports_method("textDocument/formatting") then + vim.api.nvim_create_autocmd("BufWritePre", { + group = vim.api.nvim_create_augroup("my.lsp", { clear = false }), + buffer = event.buf, + callback = function() + vim.lsp.buf.format({ bufnr = event.buf, id = client.id, timeout_ms = 1000 }) + end, + }) + end + + if client and client:supports_method("textDocument/inlayHint") then + vim.lsp.inlay_hint.enable(true, { bufnr = event.buf }) + end + + if client and client:supports_method("textDocument/documentHighlight") then + local highlight_augroup = + vim.api.nvim_create_augroup("lsp-highlight", { clear = false }) + + -- When cursor stops moving: Highlights all instances of the symbol under the cursor + -- When cursor moves: Clears the highlighting + vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, { + buffer = event.buf, + group = highlight_augroup, + callback = vim.lsp.buf.document_highlight, + }) + vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, { + buffer = event.buf, + group = highlight_augroup, + callback = vim.lsp.buf.clear_references, + }) + + -- When LSP detaches: Clears the highlighting + vim.api.nvim_create_autocmd("LspDetach", { + group = vim.api.nvim_create_augroup("lsp-detach", { clear = true }), + callback = function(event2) + vim.lsp.buf.clear_references() + vim.api.nvim_clear_autocmds({ group = "lsp-highlight", buffer = event2.buf }) + end, + }) + end + end, +}) + +vim.api.nvim_create_autocmd("ModeChanged", { + group = vim.api.nvim_create_augroup("diagnostic_redraw", {}), + callback = function() pcall(vim.diagnostic.show) end, +}) + +-- terminal +local terminal_state = { + buf = nil, + win = nil, + is_open = false, +} + +local function FloatingTerminal() + -- If terminal is already open, close it (toggle behavior) + if terminal_state.is_open and vim.api.nvim_win_is_valid(terminal_state.win) then + vim.api.nvim_win_close(terminal_state.win, false) + terminal_state.is_open = false + return + end + + -- Create buffer if it doesn't exist or is invalid + if not terminal_state.buf or not vim.api.nvim_buf_is_valid(terminal_state.buf) then + terminal_state.buf = vim.api.nvim_create_buf(false, true) + -- Set buffer options for better terminal experience + vim.api.nvim_buf_set_option(terminal_state.buf, "bufhidden", "hide") + end + + -- Calculate window dimensions + local width = math.floor(vim.o.columns * 0.8) + local height = math.floor(vim.o.lines * 0.8) + local row = math.floor((vim.o.lines - height) / 2) + local col = math.floor((vim.o.columns - width) / 2) + + -- Create the floating window + terminal_state.win = vim.api.nvim_open_win(terminal_state.buf, true, { + relative = "editor", + width = width, + height = height, + row = row, + col = col, + style = "minimal", + border = "rounded", + }) + + -- Set transparency for the floating window + vim.api.nvim_win_set_option(terminal_state.win, "winblend", 0) + + -- Set transparent background for the window + vim.api.nvim_win_set_option( + terminal_state.win, + "winhighlight", + "Normal:FloatingTermNormal,FloatBorder:FloatingTermBorder" + ) + + -- Define highlight groups for transparency + vim.api.nvim_set_hl(0, "FloatingTermNormal", { bg = "none" }) + vim.api.nvim_set_hl(0, "FloatingTermBorder", { bg = "none" }) + + -- Start terminal if not already running + local has_terminal = false + local lines = vim.api.nvim_buf_get_lines(terminal_state.buf, 0, -1, false) + for _, line in ipairs(lines) do + if line ~= "" then + has_terminal = true + break + end + end + + if not has_terminal then vim.fn.termopen(os.getenv("SHELL")) end + + terminal_state.is_open = true + vim.cmd("startinsert") + + -- Set up auto-close on buffer leave + vim.api.nvim_create_autocmd("BufLeave", { + buffer = terminal_state.buf, + callback = function() + if terminal_state.is_open and vim.api.nvim_win_is_valid(terminal_state.win) then + vim.api.nvim_win_close(terminal_state.win, false) + terminal_state.is_open = false + end + end, + once = true, + }) +end + +-- Function to explicitly close the terminal +local function CloseFloatingTerminal() + if terminal_state.is_open and vim.api.nvim_win_is_valid(terminal_state.win) then + vim.api.nvim_win_close(terminal_state.win, false) + terminal_state.is_open = false + end +end + +-- Key mappings +vim.keymap.set( + "n", + "t", + FloatingTerminal, + { noremap = true, silent = true, desc = "Toggle floating terminal" } +) +vim.keymap.set("t", "", function() + if terminal_state.is_open then + vim.api.nvim_win_close(terminal_state.win, false) + terminal_state.is_open = false + end +end, { noremap = true, silent = true, desc = "Close floating terminal from terminal mode" }) diff --git a/home/nvim/default.nix b/home/nvim/default.nix new file mode 100644 index 0000000..038d8d6 --- /dev/null +++ b/home/nvim/default.nix @@ -0,0 +1,93 @@ +{ pkgs, pkgs-unstable, ... }: + +{ + programs.neovim = + let + toLua = str: "lua << EOF\n${str}\nEOF\n"; + toLuaFile = file: "lua << EOF\n${builtins.readFile file}\nEOF\n"; + in + { + enable = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + vimdiffAlias = true; + extraPackages = with pkgs-unstable; [ + inotify-tools + + # debuggers + delve # golang debugger + lldb # rust, c, etc, debugger + + # format + rustfmt + dprint # platform for many formatters + yamlfmt + + # LSP + biome # javascript, biome + clippy # rust error checking + clang-tools # C + dprint # format engine for multiple langeuages + dprint-plugins.dprint-plugin-markdown # markdown + dprint-plugins.dprint-plugin-toml # toml + dprint-plugins.g-plane-malva # css + dprint-plugins.g-plane-markup_fmt # html + dprint-plugins.g-plane-pretty_yaml # yaml + fish-lsp # fish + gopls # golang + ltex-ls # latex, markdown + lua-language-server # lua + nil # lsp server for nix + nodePackages.bash-language-server # bash + nodePackages.typescript-language-server # javascript validation + ruff # python format and lint + rust-analyzer + tex-fmt # latex + texlab # latex lsp + tree-sitter # generate tree-sitter grammars + ty # python type checker written in rust + vale-ls # prose (md, asciidoc) + ]; + + extraPython3Packages = ps: [ + ps.debugpy + ps.pynvim + ]; + plugins = with pkgs-unstable.vimPlugins; [ + { + plugin = nvim-dap; + config = toLuaFile ./plugins/dap.lua; + } + { + plugin = which-key-nvim; + config = toLuaFile ./plugins/which.lua; + } + { + plugin = undotree; + config = toLuaFile ./plugins/undotree.lua; + } + { + plugin = mini-nvim; + config = toLuaFile ./plugins/mini.lua; + } + { + plugin = nvim-treesitter.withAllGrammars; + config = toLuaFile ./plugins/treesitter.lua; + } + hardtime-nvim + nvim-dap-view + nvim-dap-virtual-text + nord-nvim + ]; + + extraLuaConfig = '' + ${builtins.readFile ./lsp.lua} + ${builtins.readFile ./autocommands.lua} + ${builtins.readFile ./keymaps.lua} + ${builtins.readFile ./options.lua} + ${builtins.readFile ./plugins/other.lua} + ''; + }; + +} diff --git a/home/nvim/keymaps.lua b/home/nvim/keymaps.lua new file mode 100644 index 0000000..d8907bf --- /dev/null +++ b/home/nvim/keymaps.lua @@ -0,0 +1,86 @@ +vim.g.mapleader = " " +vim.g.maplocalleader = " " +vim.keymap.set("v", "<", "", ">gv", { desc = "Indent right" }) + +vim.keymap.set("n", "", "Pick buffers", { desc = "Search open files" }) +vim.keymap.set("n", "ff", "Pick files", { desc = "Search all files" }) +vim.keymap.set("n", "fh", "Pick help", { desc = "Search help tags" }) + +-- Alternative navigation (more intuitive) +vim.keymap.set("n", "tn", ":tabnew", { desc = "New tab" }) +vim.keymap.set("n", "tx", ":tabclose", { desc = "Close tab" }) + +-- Tab moving +vim.keymap.set("n", "tm", ":tabmove", { desc = "Move tab" }) +vim.keymap.set("n", "t>", ":tabmove +1", { desc = "Move tab right" }) +vim.keymap.set("n", "t<", ":tabmove -1", { desc = "Move tab left" }) + +vim.keymap.set("n", "dq", vim.diagnostic.disable) +vim.keymap.set("n", "ds", vim.diagnostic.enable) + +vim.keymap.set({ "n", "x" }, "gy", '"+y', { desc = "Copy to clipboard" }) +vim.keymap.set({ "n", "x" }, "gp", '"+p', { desc = "Paste clipboard text" }) + +vim.keymap.set("n", "", "nohlsearch") +vim.keymap.set( + "n", + "q", + vim.diagnostic.setloclist, + { desc = "Open diagnostic [Q]uickfix list" } +) +vim.keymap.set("n", "q", ":bpspbnbd", { desc = "Close buffer" }) +vim.keymap.set("n", "Q", ":bd!", { desc = "Force close buffer" }) +vim.keymap.set("t", "", "", { desc = "Exit terminal mode" }) + +vim.keymap.set("n", "", "", { desc = "Move focus to the left window" }) +vim.keymap.set("n", "", "", { desc = "Move focus to the right window" }) +vim.keymap.set("n", "", "", { desc = "Move focus to the lower window" }) +vim.keymap.set("n", "", "", { desc = "Move focus to the upper window" }) + +vim.keymap.set("n", "e", ":lua MiniFiles.open()", { desc = "Open [E]xplorer" }) + +vim.keymap.set("n", "", "DapContinue", { desc = "DAP: Continue" }) +vim.keymap.set("n", "bp", "DapToggleBreakpoint", { desc = "DAP: Toggle Breakpoint" }) +vim.keymap.set("n", "", "DapStepOver", { desc = "DAP: Step Over" }) +vim.keymap.set("n", "", "DapStepInto", { desc = "DAP: Step Into" }) +vim.keymap.set("n", "", "DapStepOut", { desc = "DAP: Step Out" }) +vim.keymap.set("n", "dt", "DapTerminate", { desc = "DAP: Terminate" }) + +local function tab_complete() + if vim.fn.pumvisible() == 1 then + -- navigate to next item in completion menu + return "" + end + + local c = vim.fn.col(".") - 1 + local is_whitespace = c == 0 or vim.fn.getline("."):sub(c, c):match("%s") + + if is_whitespace then + -- insert tab + return "" + end + + local lsp_completion = vim.bo.omnifunc == "v:lua.vim.lsp.omnifunc" + + if lsp_completion then + -- trigger lsp code completion + return "" + end + + -- suggest words in current buffer + return "" +end + +local function tab_prev() + if vim.fn.pumvisible() == 1 then + -- navigate to previous item in completion menu + return "" + end + + -- insert tab + return "" +end + +vim.keymap.set("i", "", tab_complete, { expr = true }) +vim.keymap.set("i", "", tab_prev, { expr = true }) diff --git a/home/nvim/lsp.lua b/home/nvim/lsp.lua new file mode 100644 index 0000000..07665bc --- /dev/null +++ b/home/nvim/lsp.lua @@ -0,0 +1,305 @@ +-- example configurations available https://github.com/neovim/nvim-lspconfig/tree/master/lsp +vim.lsp.set_log_level(vim.log.levels.WARN) +vim.lsp.log.set_format_func(vim.inspect) + +vim.diagnostic.config({ + virtual_text = true, + virtual_lines = { current_line = true }, + underline = true, + update_in_insert = false, + severity_sort = true, + float = { + border = "rounded", + source = true, + }, + signs = { + text = { + [vim.diagnostic.severity.ERROR] = "󰅚 ", + [vim.diagnostic.severity.WARN] = "󰀪 ", + [vim.diagnostic.severity.INFO] = "󰋽 ", + [vim.diagnostic.severity.HINT] = "󰌶 ", + }, + numhl = { + [vim.diagnostic.severity.ERROR] = "ErrorMsg", + [vim.diagnostic.severity.WARN] = "WarningMsg", + }, + }, +}) + +local capabilities = vim.lsp.protocol.make_client_capabilities() + +capabilities = vim.tbl_deep_extend("force", capabilities, { + textDocument = { + inlayHint = { + dynamicRegistration = false, -- Static registration + resolveSupport = { + properties = { "textEdits", "tooltip", "label" }, -- Resolve additional hint details + }, + }, + synchronization = { + dynamicRegistration = false, -- Static registration + willSave = true, -- Notify server before saving + willSaveWaitUntil = true, -- Allow server to provide edits before saving + didSave = true, -- Notify server after saving + }, + hover = { + dynamicRegistration = false, -- Static registration + contentFormat = { "markdown", "plaintext" }, -- Prefer markdown, fallback to plaintext + }, + documentSymbol = { + dynamicRegistration = false, -- Static registration + hierarchicalDocumentSymbolSupport = true, -- Support nested symbols + symbolKind = { + valueSet = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + }, -- All standard symbol kinds (file, module, namespace, etc.) + }, + }, + completion = { + completionItem = { + snippetSupport = true, + preselectSupport = true, + insertReplaceSupport = true, + labelDetailsSupport = true, + deprecatedSupport = true, + commitCharactersSupport = true, + tagSupport = { valueSet = { 1 } }, + resolveSupport = { + properties = { "documentation", "detail", "additionalTextEdits" }, + }, + }, + }, + diagnostic = { + documentDiagnosticProvider = true, -- Enable document-level diagnostics + relatedInformation = true, -- Show related diagnostic information + tagSupport = { valueSet = { 1, 2 } }, -- Support deprecated (1) and unused (2) tags + dataSupport = true, -- Allow custom data in diagnostics + }, + semanticTokens = { + multilineTokenSupport = true, + overlappingTokenSupport = true, + augmentsSyntaxTokens = true, + }, + foldingRange = { + dynamicRegistration = false, + lineFoldingOnly = true, + }, + }, + workspace = { + configuration = true, + workspaceFolders = true, + didChangeWatchedFiles = { + dynamicRegistration = true, + }, + fileOperations = { + didRename = true, + willRename = true, + didDelete = true, + didCreate = true, + }, + symbol = { + dynamicRegistration = false, -- Static registration + symbolKind = { + valueSet = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + }, -- All standard symbol kinds + }, + }, + diagnostic = { + workspaceDiagnosticsProvider = true, -- Enable workspace-level diagnostics + }, + }, +}) + +vim.lsp.config("*", { + capabilities = capabilities, + root_markers = { ".git" }, +}) + +vim.lsp.config("lua_ls", { + cmd = { "lua-language-server" }, + filetypes = { "lua" }, + root_markers = { ".luarc.json", ".luarc.jsonc" }, + settings = { + Lua = { + format = { + enable = true, + defaultConfig = { + indent_style = "tab", + indent_size = 1, + quote_style = "double", + max_line_length = 120 + }, + }, + runtime = { version = "LuaJIT" }, + diagnostics = { globals = { "vim", "luassert" }, enable = true }, + workspace = { + checkThirdParty = true, + library = vim.api.nvim_get_runtime_file("", true), + }, + telemetry = { enable = false }, + hint = { + enable = true, + setType = true, + paramType = true, + paramName = "All", + }, + }, + }, +}) + +vim.lsp.config("nil_ls", { + cmd = { "nil" }, + root_markers = { "flake.nix" }, + filetypes = { "nix" }, + settings = { + ["nil"] = { + formatting = { command = { "nixfmt" } }, + }, + }, +}) + +vim.lsp.config("ts_ls", { + cmd = { "typescript-language-server", "--stdio" }, + root_markers = { ".editorconfig", "jsconfig.json" }, + filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact", "vue" }, + init_options = { + preferences = { + disableSuggestions = false, + includeCompletionsForModuleExports = true, + }, + }, + capabilities = { + textDocument = { + formatting = false, + }, + }, + on_attach = function(client, bufnr) + client.server_capabilities.documentFormattingProvider = false + client.server_capabilities.documentRangeFormattingProvider = false + end, +}) + +vim.lsp.config("ruff", { + cmd = { "ruff", "server" }, + root_markers = { "pyproject.toml" }, + filetypes = { "python" }, + init_options = { + settings = { + configurationPreference = "filesystemFirst", + fixAll = true, + lineLength = 100, + lint = { enable = true }, + organizeImports = true, + }, + }, +}) + +vim.lsp.config("dprint", { + cmd = { "dprint", "lsp" }, + filetypes = { "toml", "yaml", "markdown", "css" }, + settings = {}, +}) + +vim.lsp.config("clangd", { + cmd = { "clangd" }, + filetypes = { "c", "cpp" }, + root_markers = { + ".clangd", ".git" + }, +}) + +vim.lsp.config("vale_ls", { + cmd = { "vale-ls" }, + filetypes = { "markdown", "text", "tex", "rst", "adoc", "asciidoc" }, + root_markers = { ".vale.ini" }, +}) + +vim.lsp.config("ty", { + cmd = { "ty", "server" }, + root_markers = { "pyproject.toml" }, + filetypes = { "python" }, + settings = { + ty = { + diagnosticMode = "workspace", + experimental = { + rename = true, + autoImport = true, + completions = true, + }, + }, + }, +}) + +vim.lsp.config("rust_analyzer", { + cmd = { "rust-analyzer" }, + root_markers = { "Cargo.toml" }, + filetypes = { "rust" }, + settings = { + ["rust-analyzer"] = { + check = { + command = "clippy", + }, + }, + }, +}) + +vim.lsp.config("biome", { + cmd = { "biome", "lsp-proxy" }, + workspace_required = true, + filetypes = { + "graphql", + "javascript", + "json", + "html" + }, + root_markers = { "biome.json" }, + capabilities = { + textDocument = { + formatting = { + dynamicRegistration = false, + }, + }, + }, + single_file_support = false +}) + +vim.lsp.config("gopls", { + cmd = { "gopls" }, + root_markers = { "go.mod" }, + filetypes = { "go", "gomod", "gowork", "gotmpl" }, + settings = { + gopls = { + analyses = { + unusedparams = true, + }, + staticcheck = true, + }, + }, +}) + +vim.lsp.config("bashls", { + cmd = { "bash-language-server", "start" }, + filetypes = { "sh" }, +}) + +vim.lsp.config("texlab", { + cmd = { "texlab" }, + filetypes = { "tex", "plaintex", "bib" }, +}) + +vim.lsp.enable({ + "bashls", + "biome", + "clangd", + "dprint", + "gopls", + "lua_ls", + "nil_ls", + "ruff", + "rust_analyzer", + "texlab", + "ts_ls", + "ty", + "vale_ls", +}) diff --git a/home/nvim/options.lua b/home/nvim/options.lua new file mode 100644 index 0000000..ee2fac2 --- /dev/null +++ b/home/nvim/options.lua @@ -0,0 +1,93 @@ +vim.opt.title = true -- set the title of window to the value of the titlestring +vim.opt.titlestring = "%<%F%=%l/%L - nvim" -- what the title of the window will be set to +vim.g.have_nerd_fonts = true +vim.o.shell = "fish" +vim.o.fileencoding = "utf-8" +vim.opt.conceallevel = 0 +vim.opt.clipboard:append("unnamedplus") -- copy & paste +vim.o.termguicolors = true -- Enable GUI colors for the terminal to get truecolor +vim.o.mouse = "a" -- turn on mouse interaction +vim.o.signcolumn = "yes" +vim.o.guicursor = table.concat({ + "n-v-c:block-Cursor/lCursor-blinkwait1000-blinkon100-blinkoff100", + "i-ci:ver25-Cursor/lCursor-blinkwait1000-blinkon100-blinkoff100", + "r:hor50-Cursor/lCursor-blinkwait100-blinkon100-blinkoff100", +}, ",") + +vim.opt.completeopt = { "menu", "menuone", "noselect", "noinsert", "preview" } -- completion options +vim.opt.shortmess:append("c") +vim.o.updatetime = 100 -- CursorHold interval +vim.opt.wrap = true +vim.opt.linebreak = true +vim.opt.breakindent = true +vim.opt.inccommand = "split" +vim.opt.virtualedit = "block" +vim.opt.grepprg = "rg --vimgrep" +vim.opt.grepformat = "%f:%l:%c:%m" +vim.o.textwidth = 100 +vim.o.tabstop = 4 +vim.o.softtabstop = 4 +vim.o.shiftwidth = 4 +vim.o.expandtab = true +vim.o.smartindent = true +vim.opt.smartcase = true +vim.o.shiftwidth = 4 +vim.o.autoindent = true +vim.o.smarttab = true -- / indent/dedent in leading whitespace +vim.o.list = true -- show hidden characters by default +vim.opt.hidden = true -- required to keep multiple buffers and open multiple buffers + +vim.o.undofile = true +vim.o.undodir = "/home/petri/.config/nvim/undo/" +vim.o.backupdir = "/home/petri/.config/nvim/backup/" +vim.o.directory = "/home/petri/.config/nvim//swp/" + +vim.o.number = true -- show line numbers +vim.o.showmode = false -- we are already showing mode +vim.o.relativenumber = true -- relative line numbers +vim.o.hlsearch = true -- highlighted search results +vim.o.incsearch = true -- incremental search +vim.o.ignorecase = true -- ignore case sensetive while searching +vim.o.colorcolumn = "100" +vim.o.cursorline = true -- highlight current line +vim.opt.showmatch = true -- show matching bracket +vim.opt.matchtime = 2 -- how long to show matching bracket +vim.opt.pumblend = 10 -- popup menu transparency +vim.opt.winblend = 0 +vim.opt.winborder = "rounded" +vim.opt.synmaxcol = 300 + +vim.opt.swapfile = false +vim.opt.autoread = true +vim.opt.path:append("**") -- include subdirectories in search +vim.opt.selection = "exclusive" -- Selection behavior +vim.opt.showtabline = 2 -- show when multiple open + +vim.opt.foldmethod = "syntax" +vim.opt.foldlevel = 99 -- Start with all folds open +vim.opt.foldenable = true -- Enable folding + +vim.opt.scrolloff = 8 +vim.opt.sidescrolloff = 8 + +vim.opt.formatoptions:remove({ "c", "t" }) +vim.opt.listchars = { tab = "» ", trail = "·", nbsp = "␣" } +vim.opt.backspace = "indent,start,eol" -- make backspace behave like normal again +vim.opt.splitbelow = true -- open horizontal splits below current window +vim.opt.splitright = true -- open vertical splits to the right of the current window +vim.opt.laststatus = 2 -- always show status line +vim.opt.wildignore = vim.opt.wildignore + "*.o,*.rej,*.so" -- patterns to ignore during file-navigation +vim.opt.lazyredraw = false -- faster scrolling + +vim.opt.spell = false +vim.opt.spelllang = "en" +vim.opt.wildmenu = true +vim.opt.wildmode = "longest:full,full" +vim.opt.wildignore:append({ "*.pyc" }) + +vim.opt.diffopt:append("linematch:60") + +vim.opt.redrawtime = 10000 +vim.opt.maxmempattern = 50000 + +vim.cmd.colorscheme("nord") diff --git a/home/nvim/plugins/dap.lua b/home/nvim/plugins/dap.lua new file mode 100644 index 0000000..c20ae36 --- /dev/null +++ b/home/nvim/plugins/dap.lua @@ -0,0 +1,147 @@ +-- Store DAP configuration in a function to load on demand +local function setup_dap() + local dap = require("dap") + local dapview = require("dap-view") + local dapvt = require("nvim-dap-virtual-text") + + dapview.setup({}) + + dapvt.setup { + enabled = true, + enabled_commands = true, + highlight_changed_variables = true, + highlight_new_as_changed = false, + show_stop_reason = true, + commented = false, + only_first_definition = true, + all_references = false, + clear_on_continue = false, + display_callback = function(variable, buf, stackframe, node, options) + if options.virt_text_pos == "inline" then + return " = " .. variable.value:gsub("%s+", " ") + else + return variable.name .. " = " .. variable.value:gsub("%s+", " ") + end + end, + all_frames = true, + virt_lines = true, + virt_text_win_col = nil, + } + + -- === PYTHON === + dap.adapters.python = { + type = "executable", + command = "python", + args = { "-m", "debugpy.adapter" }, + } + dap.configurations.python = { + { + type = "python", + request = "launch", + name = "Launch file", + program = "${file}", + console = "integratedTerminal", + justMyCode = true, + }, + { + type = "python", + request = "attach", + name = "Attach to process", + connect = { host = "127.0.0.1", port = 5678 }, + }, + } + + -- === RUST === + dap.adapters.lldb = { + type = "executable", + command = "lldb-dap", + name = "lldb", + } + dap.configurations.rust = { + { + name = "Launch (LLDB)", + type = "lldb", + request = "launch", + program = function() + return vim.fn.input("Path to executable: ", vim.fn.getcwd() .. "/target/debug/", "file") + end, + cwd = "${workspaceFolder}", + stopOnEntry = false, + args = {}, + runInTerminal = false, + }, + { + name = "Attach to process (LLDB)", + type = "lldb", + request = "attach", + pid = require("dap.utils").pick_process, + args = {}, + }, + } + + -- === GO === + dap.adapters.go = { + type = "executable", + command = "dlv", + args = { "dap" }, + } + dap.configurations.go = { + { type = "go", name = "Debug main.go", request = "launch", program = "${file}" }, + { type = "go", name = "Debug package", request = "launch", program = "${workspaceFolder}" }, + { type = "go", name = "Attach to process", request = "attach", processId = require("dap.utils").pick_process }, + } + + -- === EVENT LISTENERS === + dap.listeners.after.event_initialized["dapview_config"] = function() dapview.open() end + dap.listeners.before.event_terminated["dapview_config"] = function() dapview.close() end + dap.listeners.before.event_exited["dapview_config"] = function() dapview.close() end +end + +-- Define custom commands to trigger DAP setup +local function define_dap_commands() + vim.api.nvim_create_user_command("DapContinue", function() + setup_dap() + require("dap").continue() + end, {}) + vim.api.nvim_create_user_command("DapToggleBreakpoint", function() + setup_dap() + require("dap").toggle_breakpoint() + end, {}) + vim.api.nvim_create_user_command("DapStepOver", function() + setup_dap() + require("dap").step_over() + end, {}) + vim.api.nvim_create_user_command("DapStepInto", function() + setup_dap() + require("dap").step_into() + end, {}) + vim.api.nvim_create_user_command("DapStepOut", function() + setup_dap() + require("dap").step_out() + end, {}) + vim.api.nvim_create_user_command("DapTerminate", function() + setup_dap() + require("dap").terminate() + end, {}) +end + +-- Create autocommand group for DAP +local augroup = vim.api.nvim_create_augroup("DapLazyLoad", { clear = true }) + +-- Load DAP on filetypes +vim.api.nvim_create_autocmd("FileType", { + group = augroup, + pattern = { "python", "rust", "go" }, + callback = function() + define_dap_commands() + end, +}) + +-- Load DAP on specific commands +vim.api.nvim_create_autocmd("CmdUndefined", { + group = augroup, + pattern = { "DapContinue", "DapToggleBreakpoint", "DapStepOver", "DapStepInto", "DapStepOut", "DapTerminate" }, + callback = function() + define_dap_commands() + end, +}) diff --git a/home/nvim/plugins/mini.lua b/home/nvim/plugins/mini.lua new file mode 100644 index 0000000..f41f1b4 --- /dev/null +++ b/home/nvim/plugins/mini.lua @@ -0,0 +1,14 @@ +require("mini.animate").setup() +require("mini.diff").setup() +require("mini.files").setup() +require("mini.git").setup() +require("mini.icons").setup() +require("mini.notify").setup() +require("mini.pick").setup() +require("mini.sessions").setup() +require("mini.starter").setup() +require("mini.statusline").setup() +require("mini.tabline").setup({ + show_icons = true +}) +require("mini.completion").setup() diff --git a/home/nvim/plugins/other.lua b/home/nvim/plugins/other.lua new file mode 100644 index 0000000..10efd0e --- /dev/null +++ b/home/nvim/plugins/other.lua @@ -0,0 +1,5 @@ +-- hardtime +require("hardtime").setup() + +vim.g.nord_italic = true +require("nord").set() diff --git a/home/nvim/plugins/treesitter.lua b/home/nvim/plugins/treesitter.lua new file mode 100644 index 0000000..968af11 --- /dev/null +++ b/home/nvim/plugins/treesitter.lua @@ -0,0 +1,81 @@ +local function disable(lang, buf) + local max_filesize = 100 * 1024 -- 100 KB + local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf)) + if ok and stats and stats.size > max_filesize then + return true + end +end + +require("nvim-treesitter.configs").setup({ + ensure_installed = {}, + sync_install = false, + ignore_install = {}, + modules = {}, + auto_install = false, + highlight = { + enable = true, + disable = disable, + additional_vim_regex_highlighting = false, + }, + indent = { enable = true, disable = { "rust", "lua", "python", "golang", "nix", "json", "html", "javascript" } }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = "vv", + node_incremental = "+", + scope_incremental = false, + node_decremental = "_", + }, + }, + textobjects = { + select = { + enable = true, + lookahead = true, + keymaps = { + -- You can use the capture groups defined in textobjects.scm + ["af"] = { query = "@function.outer", desc = "around a function" }, + ["if"] = { query = "@function.inner", desc = "inner part of a function" }, + ["ac"] = { query = "@class.outer", desc = "around a class" }, + ["ic"] = { query = "@class.inner", desc = "inner part of a class" }, + ["ai"] = { query = "@conditional.outer", desc = "around an if statement" }, + ["ii"] = { query = "@conditional.inner", desc = "inner part of an if statement" }, + ["al"] = { query = "@loop.outer", desc = "around a loop" }, + ["il"] = { query = "@loop.inner", desc = "inner part of a loop" }, + ["ap"] = { query = "@parameter.outer", desc = "around parameter" }, + ["ip"] = { query = "@parameter.inner", desc = "inside a parameter" }, + }, + selection_modes = { + ["@parameter.outer"] = "v", -- charwise + ["@parameter.inner"] = "v", -- charwise + ["@function.outer"] = "v", -- charwise + ["@conditional.outer"] = "V", -- linewise + ["@loop.outer"] = "V", -- linewise + ["@class.outer"] = "", -- blockwise + }, + include_surrounding_whitespace = false, + }, + move = { + enable = true, + set_jumps = true, -- whether to set jumps in the jumplist + goto_previous_start = { + ["[f"] = { query = "@function.outer", desc = "Previous function" }, + ["[c"] = { query = "@class.outer", desc = "Previous class" }, + ["[p"] = { query = "@parameter.inner", desc = "Previous parameter" }, + }, + goto_next_start = { + ["]f"] = { query = "@function.outer", desc = "Next function" }, + ["]c"] = { query = "@class.outer", desc = "Next class" }, + ["]p"] = { query = "@parameter.inner", desc = "Next parameter" }, + }, + }, + swap = { + enable = true, + swap_next = { + ["a"] = "@parameter.inner", + }, + swap_previous = { + ["A"] = "@parameter.inner", + }, + }, + }, +}) diff --git a/home/nvim/plugins/undotree.lua b/home/nvim/plugins/undotree.lua new file mode 100644 index 0000000..b6b9276 --- /dev/null +++ b/home/nvim/plugins/undotree.lua @@ -0,0 +1 @@ +vim.keymap.set("n", "u", vim.cmd.UndotreeToggle) diff --git a/home/nvim/plugins/which.lua b/home/nvim/plugins/which.lua new file mode 100644 index 0000000..09aa796 --- /dev/null +++ b/home/nvim/plugins/which.lua @@ -0,0 +1,6 @@ +local wk = require("which-key") +wk.add({ + "?", + function() require("which-key").show({ global = false }) end, + desc = "Buffer Local Keymaps (which-key)", +}) -- cgit v1.2.3-70-g09d2