diff options
Diffstat (limited to 'dot-config/nvim/init.lua')
-rw-r--r-- | dot-config/nvim/init.lua | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/dot-config/nvim/init.lua b/dot-config/nvim/init.lua new file mode 100644 index 0000000..3f7a2be --- /dev/null +++ b/dot-config/nvim/init.lua @@ -0,0 +1,444 @@ +-- Settings +local set = vim.o + +set.et = true +set.sw = 4 +set.sts = -1 +set.ts = 4 +set.nu = true +set.signcolumn = "yes" +set.updatetime = 1000 +set.ignorecase = true +set.smartcase = true +set.backup = false +set.undodir = vim.fn.stdpath("data") .. "/undodir" +set.undofile = true +set.splitright = true +set.splitbelow = true +set.breakindent = true +set.termguicolors = true +set.linebreak = true + +vim.g.omni_sql_no_default_maps = 1337 +-- vim.g.asmsyntax = "nasm" + +vim.api.nvim_create_autocmd("TermOpen", { + group = vim.api.nvim_create_augroup("TermNoNumbers", {}), + command = "setlocal nonu nornu signcolumn=no" +}) + +vim.api.nvim_create_autocmd("TextYankPost", { + group = vim.api.nvim_create_augroup("HighlightYank", {}), + callback = function() vim.highlight.on_yank() end, +}) + +vim.filetype.add({ + filename = { + ["compose.yaml"] = "yaml.docker-compose", + ["docker-compose.yaml"] = "yaml.docker-compose", + }, + extension = { + templ = "templ", + typ = "typst", + } +}) + +vim.diagnostic.config({ + virtual_text = true, + virtual_lines = { current_line = true }, +}) + +-- Keymaps +for _, mod in ipairs({ + function(x) return x end, + function(x) return "<c-w>" .. x end, + function(x) return "<c-w><c-" .. x .. ">" end, + function(x) return string.upper(x) end, +}) do + vim.keymap.set("", mod("n"), mod("j")) + vim.keymap.set("", mod("e"), mod("k")) + vim.keymap.set("", mod("k"), mod("n")) + vim.keymap.set("", mod("j"), mod("e")) +end + +vim.g.mapleader = " " +vim.keymap.set("n", "gp", vim.cmd.bp) +vim.keymap.set("n", "gn", vim.cmd.bn) +vim.keymap.set("n", "<leader>h", function() set.hls = not set.hls end) +vim.keymap.set("t", "<c-l>", "<c-\\><c-n>") +vim.keymap.set("n", "<space>", "<nop>", { silent = true }) + +local function lsp_maps(buf) + local telescope_builtin = require("telescope.builtin") + local opts = { buffer = buf } + + vim.keymap.set("n", "gd", telescope_builtin.lsp_definitions, opts) + vim.keymap.set("n", "gr", telescope_builtin.lsp_references, opts) + vim.keymap.set("n", "gi", telescope_builtin.lsp_implementations, opts) + vim.keymap.set("n", "gy", telescope_builtin.lsp_type_definitions, opts) + vim.keymap.set("n", "<leader>d", telescope_builtin.diagnostics, opts) + vim.keymap.set("n", "grn", vim.lsp.buf.rename, opts) + vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts) + vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) + vim.keymap.set("n", "<leader>k", vim.diagnostic.open_float, opts) + vim.keymap.set("n", "<leader>K", vim.diagnostic.setqflist, opts) + vim.keymap.set("n", "<leader>e", vim.lsp.buf.hover, opts) + vim.keymap.set("i", "<c-k>", vim.lsp.buf.signature_help, opts) + vim.keymap.set("n", "<leader>.", vim.lsp.buf.code_action, opts) + vim.keymap.set("n", "<leader>i", vim.lsp.buf.format, opts) +end + +-- LSP +vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("UserLspConfig", {}), + callback = function(ev) + local client = vim.lsp.get_client_by_id(ev.data.client_id) + lsp_maps(ev.buf) + + if client.server_capabilities.documentHighlightProvider then + local bg = require("catppuccin.palettes").get_palette().surface0 + vim.api.nvim_set_hl(0, "LspReferenceText", { bg = bg }) + vim.api.nvim_set_hl(0, "LspReferenceRead", { bg = bg }) + vim.api.nvim_set_hl(0, "LspReferenceWrite", { bg = bg }) + + local group = vim.api.nvim_create_augroup("CursorHoldHighlightReferences", {}) + vim.api.nvim_create_autocmd("CursorHold", { + group = group, + buffer = ev.buf, + callback = vim.lsp.buf.document_highlight, + }) + vim.api.nvim_create_autocmd("CursorMoved", { + group = group, + buffer = ev.buf, + callback = vim.lsp.buf.clear_references, + }) + end + end +}) + +local function setup_lsp() + local lsp = require "lspconfig" + local capabilities = require "cmp_nvim_lsp".default_capabilities() + local function mkCap(obj) + if not obj then + obj = {} + end + if not obj.capabilities then + obj.capabilities = capabilities + end + return obj + end + lsp.gopls.setup { + capabilities = capabilities, + settings = { gopls = { + usePlaceholders = true, + semanticTokens = true, + } }, + } + lsp.rust_analyzer.setup { + capabilities = capabilities, + settings = { ["rust-analyzer"] = { + cargo = { allFeatures = true }, + check = { command = "clippy" }, + } }, + } + lsp.hls.setup { + capabilities = capabilities, + settings = { haskell = { + formattingProvider = "fourmolu", + } }, + } + lsp.lua_ls.setup { + capabilities = capabilities, + settings = { Lua = { + diagnostics = { globals = { + "vim", + } }, + telemetry = { + enable = false, + }, + } } + } + lsp.templ.setup(mkCap()) + lsp.emmet_ls.setup(mkCap()) + lsp.ts_ls.setup(mkCap()) + lsp.dockerls.setup(mkCap()) + lsp.dockerls.setup(mkCap()) + lsp.docker_compose_language_service.setup(mkCap()) + lsp.terraformls.setup(mkCap()) + lsp.nixd.setup { + capabilities = capabilities, + settings = { nixd = { + formatting = { command = { "nixfmt" } }, + } }, + } + lsp.astro.setup(mkCap()) + lsp.elixirls.setup { capabilities = capabilities, cmd = { "elixir-ls" } } + lsp.csharp_ls.setup(mkCap()) + lsp.zls.setup(mkCap()) + lsp.denols.setup(mkCap()) +end + +-- Plugins +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + local lazyrepo = "https://github.com/folke/lazy.nvim.git" + local out = vim.fn.system({ + "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath, + }) + if vim.v.shell_error ~= 0 then + vim.api.nvim_echo({ + { "Failid to clone lazy.nvim:zn", "ErrorMsg" }, + { out, "WarningMsg" }, + { "\nPress the any key to exit..." }, + }, true, {}) + vim.fn.getchar() + os.exit(1) + end +end +vim.opt.rtp:prepend(lazypath) + +require("lazy").setup({ + { "folke/lazy.nvim", tag = "stable" }, + { + "catppuccin/nvim", + config = function() + require "catppuccin".setup { + background = { + light = "latte", + dark = "mocha", + }, + } + vim.cmd.colorscheme("catppuccin") + end, + priority = 1000, + }, + { + "stevearc/oil.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = true, + lazy = false, + keys = { { "-", vim.cmd.Oil } }, + }, + { + "nvim-treesitter/nvim-treesitter", + config = function() + require("nvim-treesitter.configs").setup { + ensure_installed = { + "vimdoc", + "rust", "go", "c", "zig", + "lua", "python", "haskell", + "fish", "bash", + "typescript", "svelte", "javascript", "css", "astro", "tsx", "prisma", + "nix", + "markdown", "typst", + "terraform", "hcl", + "sql", + "templ", + "html", "php", + "elixir", "heex", + }, + indent = { enable = true }, + highlight = { enable = true }, + } + end, + }, + { + "nvim-telescope/telescope.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + keys = { + { "<leader>f", function() require "telescope.builtin".find_files() end }, + { "<leader>/", function() require "telescope.builtin".live_grep() end }, + { "<leader>l", function() require "telescope.builtin".resume() end }, + { "<leader><space>", function() require "telescope.builtin".buffers() end }, + }, + build = ":TSUpdate", + }, + { + "neovim/nvim-lspconfig", + dependencies = { "hrsh7th/cmp-nvim-lsp" }, + config = setup_lsp, + }, + { + "hrsh7th/nvim-cmp", + dependencies = { + "hrsh7th/cmp-nvim-lsp", + "saadparwaiz1/cmp_luasnip", + "L3MON4D3/LuaSnip", + "hrsh7th/cmp-omni", + }, + config = function() + local cmp = require "cmp" + local luasnip = require "luasnip" + cmp.setup { + completion = { autocomplete = false }, + sources = cmp.config.sources { + { name = "nvim_lsp" }, + { name = "luasnip" }, + { name = "omni" }, + }, + snippet = { + expand = function(args) luasnip.lsp_expand(args.body) end, + }, + mapping = { + ["<c-l>"] = cmp.mapping.confirm({ select = true }), + ["<c-e>"] = cmp.mapping.abort(), + ["<c-b>"] = cmp.mapping.scroll_docs(-4), + ["<c-f>"] = cmp.mapping.scroll_docs(4), + ["<c-n>"] = function(fallback) + if cmp.visible() then + cmp.select_next_item() + else + fallback() + end + end, + ["<c-p>"] = function(fallback) + if cmp.visible() then + cmp.select_prev_item() + else + fallback() + end + end, + }, + } + end, + -- NOTE: If this is lazy, the `mapping`s from above don't + -- work when completing for the first time + lazy = false, + keys = { + { mode = "i", "<c-l>", function() require "cmp".complete() end }, + { mode = { "i", "s" }, "<c-h>", function() require "luasnip".jump(-1) end }, + { mode = { "i", "s" }, "<c-e>", function() require "luasnip".jump(1) end }, + }, + }, + { "wsdjeg/vim-fetch" }, + { + "ggandor/leap.nvim", + keys = { + { "s", function() require "leap".leap {} end }, + { "S", function() require "leap".leap { backward = true } end }, + }, + }, + { "numToStr/Comment.nvim", config = true }, + { "willothy/flatten.nvim", config = true, lazy = false }, + { "folke/todo-comments.nvim", config = true }, + { + "akinsho/bufferline.nvim", + after = "cattppuccin", + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = function() + require("bufferline").setup { + options = { diagnostics = "nvim_lsp" }, + highlights = require("catppuccin.groups.integrations.bufferline").get(), + } + end, + lazy = false, + keys = { + { "<leader>a", function() require "bufferline".go_to(1) end }, + { "<leader>r", function() require "bufferline".go_to(2) end }, + { "<leader>s", function() require "bufferline".go_to(3) end }, + { "<leader>t", function() require "bufferline".go_to(4) end }, + }, + }, + { "kylechui/nvim-surround", event = "VeryLazy", config = true }, + { + "folke/snacks.nvim", + priority = 1000, + lazy = false, + opts = { + input = { enabled = true }, + bigfile = { enabled = true }, + notifier = { enabled = true }, + indent = { enabled = true }, + terminal = { + win = { + keys = { + gf = function() + local cfile = vim.fn.expand("<cfile>") + local line = vim.fn.getline(".") + local match = line:match(vim.pesc(cfile) .. "(:%d+:%d+)") + if match == nil then + match = line:match(vim.pesc(cfile) .. "(:%d+)") + end + if match == nil then + match = "" + end + local f = vim.fn.findfile(cfile, "**") + -- Go to previous window because `:e fname:lineno:colnu` works thanks to wsdjeg/vim-fetch but not when in the terminal window + vim.cmd.wincmd("p") + vim.schedule(function() + vim.cmd.e(f .. match) + end) + end, + }, + }, + }, + }, + keys = { + { "<leader>q", function() Snacks.bufdelete() end }, + { "<leader>g", function() Snacks.lazygit() end }, + { "<leader>b", function() + local t, created = Snacks.terminal.get() + if created then + vim.schedule(function() + local autocmds = vim.api.nvim_get_autocmds({ event = "BufEnter", buffer = t.buf }) + -- Snacks.notify(vim.pretty_print(autocmds)) + vim.api.nvim_del_autocmd( + autocmds[1].id + ) + end) + else + t:show() + t:focus() + vim.cmd.startinsert() + end + end }, + }, + }, +}) + +-- Other +vim.api.nvim_create_user_command("Djul", function(opts) + local buf = vim.api.nvim_get_current_buf() + local lines = vim.api.nvim_buf_get_lines(buf, opts.line1 - 1, opts.line2, false) + for i, line in ipairs(lines) do + line = string.gsub(line, "…", "...") + line = string.gsub(line, "“", '"') + line = string.gsub(line, "”", '"') + line = string.gsub(line, "‘", "'") + line = string.gsub(line, "’", "'") + lines[i] = line + end + vim.api.nvim_buf_set_lines(buf, opts.line1 - 1, opts.line2, false, lines) +end, { range = "%" }) + +local busctl_buffer = "" +vim.system({ "busctl", "--user", "monitor", "org.freedesktop.portal.Desktop", "--json=short" }, { + text = true, + stdout = function(err, data) + if err ~= nil then + Snacks.notify(err) + return + end + busctl_buffer = busctl_buffer .. data + while true do + local lf = busctl_buffer:find("\n") + if lf == nil then break end + local packet = vim.json.decode(busctl_buffer:sub(1, lf - 1)) + busctl_buffer = busctl_buffer:sub(lf + 1) + + if packet.interface ~= "org.freedesktop.portal.Settings" then goto continue end + if packet.path ~= "/org/freedesktop/portal/desktop" then goto continue end + if packet.member ~= "SettingChanged" then goto continue end + if packet.payload.type ~= "ssv" then goto continue end + + if packet.payload.data[1] ~= "org.freedesktop.appearance" then goto continue end + if packet.payload.data[2] ~= "color-scheme" then goto continue end + if packet.payload.data[3].type ~= "u" then goto continue end + local value = packet.payload.data[3].data + vim.schedule(function() set.background = value == 1 and "dark" or "light" end) + ::continue:: + end + end, + detach = true, +}) |