290 lines
9.7 KiB
Nix
290 lines
9.7 KiB
Nix
{ config, pkgs, ... }:
|
|
|
|
let
|
|
javaDebug = pkgs.vscode-extensions.vscjava.vscode-java-debug;
|
|
in
|
|
{
|
|
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", "<leader>w", "<cmd>w<CR>", { silent = true })
|
|
vim.keymap.set("n", "<leader>q", "<cmd>q<CR>", { silent = true })
|
|
vim.keymap.set("n", "<leader>wq", "<cmd>wq<CR>", { silent = true })
|
|
vim.keymap.set("n", "<leader>x", "<cmd>!chmod +x %<CR>", { silent = true })
|
|
vim.keymap.set("n", "Q", "<nop>")
|
|
vim.keymap.set("n", "o", "o<esc>")
|
|
vim.keymap.set("n", "O", "O<esc>")
|
|
vim.keymap.set("i", "jj", "<esc>")
|
|
|
|
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({
|
|
options = { 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 = "_" },
|
|
},
|
|
})
|
|
|
|
-- nvim-treesitter no longer exposes a configs module; highlighting is
|
|
-- started per buffer. Indent is deliberately left alone so treesitter
|
|
-- doesn't fight the Eclipse-matching tab settings below.
|
|
vim.api.nvim_create_autocmd("FileType", {
|
|
pattern = { "java", "xml", "nix", "lua", "rs" },
|
|
callback = function(args)
|
|
pcall(vim.treesitter.start, args.buf)
|
|
end,
|
|
})
|
|
|
|
-- Java indentation must match Eclipse's formatter, not the 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({
|
|
["<C-Space>"] = cmp.mapping.complete(),
|
|
["<CR>"] = cmp.mapping.confirm({ select = false }),
|
|
["<C-n>"] = cmp.mapping.select_next_item(),
|
|
["<C-p>"] = cmp.mapping.select_prev_item(),
|
|
}),
|
|
sources = {
|
|
{ name = "nvim_lsp" },
|
|
{ name = "luasnip" },
|
|
{ name = "buffer" },
|
|
{ name = "path" },
|
|
},
|
|
})
|
|
|
|
local capabilities = require("cmp_nvim_lsp").default_capabilities()
|
|
|
|
local bundles = vim.fn.glob(
|
|
"${javaDebug}/share/vscode/extensions/vscjava.vscode-java-debug/server/com.microsoft.java.debug.plugin-*.jar",
|
|
true, true)
|
|
if #bundles == 0 then
|
|
vim.notify("java-debug bundle not found - Java debugging disabled", vim.log.levels.WARN)
|
|
end
|
|
|
|
local java_home = os.getenv("JAVA_HOME")
|
|
if not java_home then
|
|
local javac = vim.fn.exepath("javac")
|
|
if javac ~= "" then
|
|
java_home = vim.fn.fnamemodify(vim.fn.resolve(javac), ":h:h")
|
|
end
|
|
end
|
|
if not java_home then
|
|
vim.notify("No JAVA_HOME and no javac on PATH - jdtls will guess a runtime", vim.log.levels.WARN)
|
|
end
|
|
if not java_home then
|
|
vim.notify("JAVA_HOME unset - jdtls will guess a runtime", vim.log.levels.WARN)
|
|
end
|
|
|
|
-- Eclipse metadata wins over build files, build files over .git, and the
|
|
-- file's own directory is the last resort so bare folders still attach.
|
|
local function find_project_root()
|
|
local setup = require("jdtls.setup")
|
|
return setup.find_root({ ".project", ".classpath" })
|
|
or setup.find_root({ "pom.xml", "build.gradle", "build.gradle.kts" })
|
|
or setup.find_root({ ".git" })
|
|
or vim.fn.expand("%:p:h")
|
|
end
|
|
|
|
local dap_configured = false
|
|
|
|
local function start_jdtls()
|
|
local jdtls = require("jdtls")
|
|
local root_dir = find_project_root()
|
|
|
|
local project_name = vim.fn.fnamemodify(root_dir, ":p:h:t")
|
|
.. "-" .. vim.fn.sha256(root_dir):sub(1, 8)
|
|
local workspace = vim.fn.stdpath("cache") .. "/jdtls-workspaces/" .. project_name
|
|
|
|
local java_settings = {
|
|
configuration = {
|
|
updateBuildConfiguration = "automatic",
|
|
},
|
|
-- 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 },
|
|
},
|
|
project = {
|
|
outputPath = "bin",
|
|
referencedLibraries = { "lib/**/*.jar" },
|
|
},
|
|
signatureHelp = { enabled = true },
|
|
eclipse = { downloadSources = true },
|
|
}
|
|
|
|
if java_home then
|
|
java_settings.configuration.runtimes = {
|
|
{ name = "JavaSE-21", path = java_home, default = true },
|
|
}
|
|
end
|
|
|
|
-- 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 = bundles },
|
|
on_attach = function(_, bufnr)
|
|
require("jdtls").setup_dap({ hotcodereplace = "auto" })
|
|
if not dap_configured then
|
|
dap_configured = true
|
|
require("jdtls.dap").setup_dap_main_class_configs()
|
|
end
|
|
|
|
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("<leader>rn", vim.lsp.buf.rename)
|
|
map("<leader>ca", vim.lsp.buf.code_action)
|
|
map("<leader>f", function() vim.lsp.buf.format({ async = true }) end)
|
|
map("<leader>oi", require("jdtls").organize_imports)
|
|
end,
|
|
})
|
|
end
|
|
|
|
vim.api.nvim_create_autocmd("FileType", {
|
|
pattern = "java",
|
|
callback = start_jdtls,
|
|
})
|
|
|
|
local dap, dapui = require("dap"), require("dapui")
|
|
dapui.setup()
|
|
require("nvim-dap-virtual-text").setup()
|
|
|
|
-- `jtest --debug` suspends the test JVM waiting on :5005; this lets
|
|
-- <leader>dc attach to it directly from the config picker.
|
|
dap.configurations.java = dap.configurations.java or {}
|
|
table.insert(dap.configurations.java, {
|
|
type = "java",
|
|
request = "attach",
|
|
name = "Attach to jtest (:5005)",
|
|
hostName = "127.0.0.1",
|
|
port = 5005,
|
|
})
|
|
|
|
dap.listeners.after.event_initialized["dapui"] = function() dapui.open() end
|
|
dap.listeners.before.event_terminated["dapui"] = function() dapui.close() end
|
|
dap.listeners.before.event_exited["dapui"] = function() dapui.close() end
|
|
|
|
vim.keymap.set("n", "<leader>db", dap.toggle_breakpoint)
|
|
vim.keymap.set("n", "<leader>dB", function()
|
|
dap.set_breakpoint(vim.fn.input("Condition: "))
|
|
end)
|
|
vim.keymap.set("n", "<leader>dc", dap.continue)
|
|
vim.keymap.set("n", "<leader>dn", dap.step_over)
|
|
vim.keymap.set("n", "<leader>di", dap.step_into)
|
|
vim.keymap.set("n", "<leader>du", dap.step_out)
|
|
vim.keymap.set("n", "<leader>dr", dap.repl.toggle)
|
|
vim.keymap.set("n", "<leader>dq", dap.terminate)
|
|
vim.keymap.set({ "n", "v" }, "<leader>de", function() dapui.eval() end)
|
|
'';
|
|
|
|
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-dap; }
|
|
{ plugin = nvim-dap-ui; }
|
|
{ plugin = nvim-nio; }
|
|
{ plugin = nvim-dap-virtual-text; }
|
|
{ plugin = nvim-cmp; }
|
|
{ plugin = cmp-nvim-lsp; }
|
|
{ plugin = cmp-buffer; }
|
|
{ plugin = cmp-path; }
|
|
{ plugin = luasnip; }
|
|
{ plugin = cmp_luasnip; }
|
|
{ plugin = rustaceanvim; }
|
|
{ plugin = (nvim-treesitter.withPlugins (p: [ p.java p.xml p.nix p.lua p.rust ])); }
|
|
];
|
|
};
|
|
}
|