aboutsummaryrefslogtreecommitdiffstats
path: root/home/nvim
diff options
context:
space:
mode:
authorPetri Hienonen <petri.hienonen@gmail.com>2024-05-23 13:56:00 +0300
committerPetri Hienonen <petri.hienonen@gmail.com>2025-11-30 12:29:57 +0200
commit08297376a85a1719518507e54fca9de954d2376a (patch)
tree3b9c58304b40248533bbb2bb5b7bad2da9da1ff0 /home/nvim
parent75c2af4aedd2ac5c2cfc74b346625fa4b265541d (diff)
downloadnixos-08297376a85a1719518507e54fca9de954d2376a.tar.zst
Agenix configuration
Diffstat (limited to 'home/nvim')
-rw-r--r--home/nvim/autocommands.lua272
-rw-r--r--home/nvim/default.nix93
-rw-r--r--home/nvim/keymaps.lua86
-rw-r--r--home/nvim/lsp.lua305
-rw-r--r--home/nvim/options.lua93
-rw-r--r--home/nvim/plugins/dap.lua147
-rw-r--r--home/nvim/plugins/mini.lua14
-rw-r--r--home/nvim/plugins/other.lua5
-rw-r--r--home/nvim/plugins/treesitter.lua81
-rw-r--r--home/nvim/plugins/undotree.lua1
-rw-r--r--home/nvim/plugins/which.lua6
11 files changed, 1103 insertions, 0 deletions
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("<leader>la", vim.lsp.buf.code_action, "Code Action")
+ map("<leader>lr", vim.lsp.buf.rename, "Rename all references")
+ map("<leader>lf", vim.lsp.buf.format, "Format")
+ map(
+ "<leader>v",
+ "<cmd>vsplit | lua vim.lsp.buf.definition()<cr>",
+ "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", "<c-space>", 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",
+ "<leader>t",
+ FloatingTerminal,
+ { noremap = true, silent = true, desc = "Toggle floating terminal" }
+)
+vim.keymap.set("t", "<Esc>", 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 left" })
+vim.keymap.set("v", ">", ">gv", { desc = "Indent right" })
+
+vim.keymap.set("n", "<leader><space>", "<cmd>Pick buffers<cr>", { desc = "Search open files" })
+vim.keymap.set("n", "<leader>ff", "<cmd>Pick files<cr>", { desc = "Search all files" })
+vim.keymap.set("n", "<leader>fh", "<cmd>Pick help<cr>", { desc = "Search help tags" })
+
+-- Alternative navigation (more intuitive)
+vim.keymap.set("n", "<leader>tn", ":tabnew<CR>", { desc = "New tab" })
+vim.keymap.set("n", "<leader>tx", ":tabclose<CR>", { desc = "Close tab" })
+
+-- Tab moving
+vim.keymap.set("n", "<leader>tm", ":tabmove<CR>", { desc = "Move tab" })
+vim.keymap.set("n", "<leader>t>", ":tabmove +1<CR>", { desc = "Move tab right" })
+vim.keymap.set("n", "<leader>t<", ":tabmove -1<CR>", { desc = "Move tab left" })
+
+vim.keymap.set("n", "<leader>dq", vim.diagnostic.disable)
+vim.keymap.set("n", "<leader>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", "<Esc>", "<cmd>nohlsearch<CR>")
+vim.keymap.set(
+ "n",
+ "<leader>q",
+ vim.diagnostic.setloclist,
+ { desc = "Open diagnostic [Q]uickfix list" }
+)
+vim.keymap.set("n", "<leader>q", ":bp<bar>sp<bar>bn<bar>bd<CR>", { desc = "Close buffer" })
+vim.keymap.set("n", "<leader>Q", ":bd!<CR>", { desc = "Force close buffer" })
+vim.keymap.set("t", "<Esc><Esc>", "<C-\\><C-n>", { desc = "Exit terminal mode" })
+
+vim.keymap.set("n", "<C-h>", "<C-w><C-h>", { desc = "Move focus to the left window" })
+vim.keymap.set("n", "<C-l>", "<C-w><C-l>", { desc = "Move focus to the right window" })
+vim.keymap.set("n", "<C-j>", "<C-w><C-j>", { desc = "Move focus to the lower window" })
+vim.keymap.set("n", "<C-k>", "<C-w><C-k>", { desc = "Move focus to the upper window" })
+
+vim.keymap.set("n", "<leader>e", "<CMD>:lua MiniFiles.open()<CR>", { desc = "Open [E]xplorer" })
+
+vim.keymap.set("n", "<F5>", "<cmd>DapContinue<CR>", { desc = "DAP: Continue" })
+vim.keymap.set("n", "<leader>bp", "<cmd>DapToggleBreakpoint<CR>", { desc = "DAP: Toggle Breakpoint" })
+vim.keymap.set("n", "<F6>", "<cmd>DapStepOver<CR>", { desc = "DAP: Step Over" })
+vim.keymap.set("n", "<F7>", "<cmd>DapStepInto<CR>", { desc = "DAP: Step Into" })
+vim.keymap.set("n", "<F8>", "<cmd>DapStepOut<CR>", { desc = "DAP: Step Out" })
+vim.keymap.set("n", "<leader>dt", "<cmd>DapTerminate<CR>", { desc = "DAP: Terminate" })
+
+local function tab_complete()
+ if vim.fn.pumvisible() == 1 then
+ -- navigate to next item in completion menu
+ return "<Down>"
+ 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 "<Tab>"
+ end
+
+ local lsp_completion = vim.bo.omnifunc == "v:lua.vim.lsp.omnifunc"
+
+ if lsp_completion then
+ -- trigger lsp code completion
+ return "<C-x><C-o>"
+ end
+
+ -- suggest words in current buffer
+ return "<C-x><C-n>"
+end
+
+local function tab_prev()
+ if vim.fn.pumvisible() == 1 then
+ -- navigate to previous item in completion menu
+ return "<Up>"
+ end
+
+ -- insert tab
+ return "<Tab>"
+end
+
+vim.keymap.set("i", "<Tab>", tab_complete, { expr = true })
+vim.keymap.set("i", "<S-Tab>", 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 -- <tab>/<BS> 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 = "<leader>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"] = "<c-v>", -- 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 = {
+ ["<leader>a"] = "@parameter.inner",
+ },
+ swap_previous = {
+ ["<leader>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", "<leader>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({
+ "<leader>?",
+ function() require("which-key").show({ global = false }) end,
+ desc = "Buffer Local Keymaps (which-key)",
+})