{ config, pkgs, ... }: { programs.neovim = { enable = true; viAlias = true; vimAlias = true; defaultEditor = true; initLua = '' vim.opt.number = true vim.opt.relativenumber = true vim.opt.tabstop = 2 vim.opt.softtabstop = 2 vim.opt.expandtab = true vim.opt.shiftwidth = 2 vim.opt.smartindent = true vim.opt.wrap = false vim.opt.swapfile = false vim.opt.backup = false vim.opt.undofile = false vim.opt.hlsearch = false vim.opt.incsearch = true vim.opt.termguicolors = true vim.opt.clipboard = "unnamedplus" vim.opt.scrolloff = 999 vim.opt.updatetime = 50 vim.opt.foldmethod = "indent" vim.opt.foldlevel = 99 vim.g.mapleader = " " vim.keymap.set("n", "", ":") vim.keymap.set("n", "w", "w", { silent = true }) vim.keymap.set("n", "q", "q", { silent = true }) vim.keymap.set("n", "wq", "wq", { silent = true }) vim.keymap.set("n", "x", "!chmod +x %", { silent = true }) vim.keymap.set("n", "Q", "") vim.keymap.set("n", "o", "o") vim.keymap.set("n", "O", "O") vim.keymap.set("i", "jj", "") local is_dark = vim.o.background ~= "light" require("cyberdream").setup({ transparent = is_dark, variant = is_dark and "dark" or "light", terminal_colors = true, }) vim.cmd.colorscheme("cyberdream") require("nvim-tree").setup({ view = { width = 30 }, renderer = { group_empty = true }, filters = { dotfiles = false }, }) require("bufferline").setup({ options = { offsets = { { filetype = "NvimTree", text = "Files", highlight = "Directory", separator = true, }, }, }, }) require("lualine").setup({ ons = { theme = "auto" }, }) require("neocord").setup({ logo = "auto", logo_tooltip = "Neovim", main_image = "language", show_time = true, global_timer = true, }) require("gitsigns").setup({ signs = { add = { text = "+" }, change = { text = "~" }, delete = { text = "_" }, }, }) -- Java indentation must match Eclipse's formatter, not your 2-space default. vim.api.nvim_create_autocmd("FileType", { pattern = "java", callback = function() vim.bo.expandtab = false vim.bo.tabstop = 4 vim.bo.shiftwidth = 4 vim.bo.softtabstop = 4 end, }) local cmp = require("cmp") local luasnip = require("luasnip") cmp.setup({ snippet = { expand = function(a) luasnip.lsp_expand(a.body) end }, mapping = cmp.mapping.preset.insert({ [""] = cmp.mapping.complete(), [""] = cmp.mapping.confirm({ select = false }), [""] = cmp.mapping.select_next_item(), [""] = cmp.mapping.select_prev_item(), }), sources = { { name = "nvim_lsp" }, { name = "luasnip" }, { name = "buffer" }, { name = "path" }, }, }) local capabilities = require("cmp_nvim_lsp").default_capabilities() -- .project and .classpath come first so a repo containing several -- assignments resolves to the assignment, not the repo root. local root_markers = { ".project", ".classpath", "pom.xml", "build.gradle", ".git" } local function start_jdtls() local jdtls = require("jdtls") local root_dir = require("jdtls.setup").find_root(root_markers) if not root_dir or root_dir == "" then return end local project_name = vim.fn.fnamemodify(root_dir, ":p:h:t") local workspace = vim.fn.stdpath("cache") .. "/jdtls-workspaces/" .. project_name local java_settings = { configuration = { updateBuildConfiguration = "interactive", runtimes = { { name = "JavaSE-21", path = os.getenv("JAVA_HOME"), default = true }, }, }, -- Keep a stray pom.xml from overriding the Eclipse project model. -- Flip these on if a course actually requires Maven or Gradle. import = { maven = { enabled = false }, gradle = { enabled = false }, }, signatureHelp = { enabled = true }, eclipse = { downloadSources = true }, } -- If the repo carries an exported Eclipse formatter profile, use it verbatim. local formatter = root_dir .. "/.settings/eclipse-formatter.xml" if vim.uv.fs_stat(formatter) then java_settings.format = { settings = { url = formatter } } end jdtls.start_or_attach({ cmd = { "jdtls", "-data", workspace }, root_dir = root_dir, capabilities = capabilities, settings = { java = java_settings }, init_options = { bundles = {} }, on_attach = function(_, bufnr) local map = function(k, f) vim.keymap.set("n", k, f, { buffer = bufnr, silent = true }) end map("gd", vim.lsp.buf.definition) map("gr", vim.lsp.buf.references) map("K", vim.lsp.buf.hover) map("rn", vim.lsp.buf.rename) map("ca", vim.lsp.buf.code_action) map("f", function() vim.lsp.buf.format({ async = true }) end) map("oi", require("jdtls").organize_imports) end, }) end vim.api.nvim_create_autocmd("FileType", { pattern = "java", callback = start_jdtls, }) require("neotest").setup({ adapters = { require("neotest-java")({ junit_jar = stdpath("home")/dev/jars/junit-*.jar, -- jvm_args = { "-Xmx512m" }, incremental_build = true, }), }, }) ''; plugins = with pkgs.vimPlugins; [ { plugin = cyberdream-nvim; } { plugin = nvim-web-devicons; } { plugin = nvim-tree-lua; } { plugin = bufferline-nvim; } { plugin = lualine-nvim; } { plugin = neocord; } { plugin = gitsigns-nvim; } { plugin = nvim-jdtls; } { plugin = nvim-nio; } { plugin = neotest; } { plugin = neotest-java; } { plugin = nvim-dap; } { plugin = nvim-dap-ui; } { plugin = nvim-dap-virtual-text; } { plugin = nvim-cmp; } { plugin = cmp-nvim-lsp; } { plugin = cmp-buffer; } { plugin = cmp-path; } { plugin = luasnip; } { plugin = cmp_luasnip; } { plugin = (nvim-treesitter.withPlugins (p: [ p.java p.xml p.nix p.lua ])); } ]; }; }