nixos: gen 45 @ lilac — 2026-09-18 08:18 26.05.20260814.02e0898 (Yarara) ----- refactoring nvim.nix and adding better java integration
This commit is contained in:
+102
-11
@@ -65,34 +65,126 @@ in
|
|||||||
|
|
||||||
custom_wvkbd
|
custom_wvkbd
|
||||||
|
|
||||||
|
(pkgs.writeShellScriptBin "jroot" ''
|
||||||
|
d="$PWD"
|
||||||
|
while [ "$d" != "/" ]; do
|
||||||
|
if [ -f "$d/.classpath" ]; then printf '%s\n' "$d"; exit 0; fi
|
||||||
|
d="$(dirname "$d")"
|
||||||
|
done
|
||||||
|
echo "jroot: no .classpath found at or above $PWD" >&2
|
||||||
|
exit 1
|
||||||
|
'')
|
||||||
|
|
||||||
|
(pkgs.writeShellScriptBin "jbuild" ''
|
||||||
|
set -euo pipefail
|
||||||
|
# Assign first: `cd "$(jroot)"` would swallow a jroot failure, because
|
||||||
|
# `cd ""` is a successful no-op and set -e never sees the error.
|
||||||
|
ROOT="$(jroot)"
|
||||||
|
cd "$ROOT"
|
||||||
|
mkdir -p bin
|
||||||
|
SOURCES="$(mktemp)"
|
||||||
|
trap 'rm -f "$SOURCES"' EXIT
|
||||||
|
find . -path ./bin -prune -o -name '.*' -prune -o -name '*.java' -print > "$SOURCES"
|
||||||
|
if [ ! -s "$SOURCES" ]; then
|
||||||
|
echo "jbuild: no .java files found under $ROOT" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# bin is deliberately NOT on the compile classpath: every source is passed
|
||||||
|
# explicitly, so a stale .class from a deleted file would silently satisfy
|
||||||
|
# references that ought to fail.
|
||||||
|
javac -g --release 21 -encoding UTF-8 -d bin -cp "lib/*" @"$SOURCES"
|
||||||
|
'')
|
||||||
|
|
||||||
|
(pkgs.writeShellScriptBin "jclean" ''
|
||||||
|
set -euo pipefail
|
||||||
|
ROOT="$(jroot)"
|
||||||
|
rm -rf "$ROOT/bin"
|
||||||
|
echo "cleaned $ROOT/bin"
|
||||||
|
'')
|
||||||
|
|
||||||
|
(pkgs.writeShellScriptBin "jrun" ''
|
||||||
|
set -euo pipefail
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
|
echo "usage: jrun <package.MainClass> [args...]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ROOT="$(jroot)"
|
||||||
|
jbuild
|
||||||
|
cd "$ROOT"
|
||||||
|
MAIN="$1"; shift
|
||||||
|
exec java -cp "bin:lib/*" "$MAIN" "$@"
|
||||||
|
'')
|
||||||
|
|
||||||
|
(pkgs.writeShellScriptBin "jtest" ''
|
||||||
|
set -euo pipefail
|
||||||
|
# sort -V so 1.10.2 beats 1.9.0; plain tail -n1 sorts those the wrong way.
|
||||||
|
JUNIT="$(ls -1 "$HOME"/dev/jars/junit-platform-console-standalone-*.jar 2>/dev/null | sort -V | tail -n1 || true)"
|
||||||
|
if [ -z "$JUNIT" ]; then
|
||||||
|
echo "jtest: no junit-platform-console-standalone jar in ~/dev/jars" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ROOT="$(jroot)"
|
||||||
|
jbuild
|
||||||
|
cd "$ROOT"
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
exec java -jar "$JUNIT" execute --class-path "bin:lib/*" --scan-class-path --details=tree
|
||||||
|
fi
|
||||||
|
ARGS=""
|
||||||
|
for pkg in "$@"; do
|
||||||
|
ARGS="$ARGS --select-package $pkg"
|
||||||
|
done
|
||||||
|
exec java -jar "$JUNIT" execute --class-path "bin:lib/*" $ARGS --details=tree
|
||||||
|
'')
|
||||||
|
|
||||||
(pkgs.writeShellScriptBin "fkill" ''
|
(pkgs.writeShellScriptBin "fkill" ''
|
||||||
if [ -z "$1" ]; then
|
set -eu
|
||||||
echo "Need the name of one application"
|
if [ $# -lt 1 ]; then
|
||||||
echo "eg. fkill google-chrome"
|
echo "usage: fkill <process-name>" >&2
|
||||||
|
echo "eg. fkill firefox" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PROGRAM=$1
|
PROGRAM="$1"
|
||||||
|
|
||||||
ps aux | grep $PROGRAM | awk '{print $2}' | xargs kill
|
if ! pgrep -x -- "$PROGRAM" >/dev/null 2>&1; then
|
||||||
|
echo "fkill: no process named '$PROGRAM'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
pgrep -a -x -- "$PROGRAM"
|
||||||
|
printf 'Kill these? [y/N] '
|
||||||
|
read -r reply
|
||||||
|
case "$reply" in
|
||||||
|
[yY]*) pkill -x -- "$PROGRAM" ;;
|
||||||
|
*) echo "aborted" ;;
|
||||||
|
esac
|
||||||
'')
|
'')
|
||||||
|
|
||||||
(pkgs.writeShellScriptBin "find-open-port" ''
|
(pkgs.writeShellScriptBin "find-open-port" ''
|
||||||
if [ -z "$1" ]; then
|
set -u
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
echo "Please provide an application name, project directory, or other identifier."
|
echo "Please provide an application name, project directory, or other identifier."
|
||||||
echo " Usage: find-open-port $HOME/dev/some-project"
|
echo ' Usage: find-open-port $HOME/dev/some-project'
|
||||||
echo " Usage: find-open-port some-app"
|
echo " Usage: find-open-port some-app"
|
||||||
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
APP_NAME=$1
|
APP_NAME="$1"
|
||||||
REGISTRY_FILE=$HOME/.dotfiles/ports.registry
|
REGISTRY_FILE="$HOME/.dotfiles/ports.registry"
|
||||||
|
|
||||||
MIN_PORT=8000
|
MIN_PORT=8000
|
||||||
MAX_PORT=8999
|
MAX_PORT=8999
|
||||||
MAX_RETRIES=50
|
MAX_RETRIES=50
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$REGISTRY_FILE")"
|
||||||
|
|
||||||
|
if [ -f "$REGISTRY_FILE" ] && grep -q "^$APP_NAME : " "$REGISTRY_FILE"; then
|
||||||
|
echo "Already registered:"
|
||||||
|
grep "^$APP_NAME : " "$REGISTRY_FILE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Searching for available port between $MIN_PORT and $MAX_PORT for $APP_NAME..."
|
echo "Searching for available port between $MIN_PORT and $MAX_PORT for $APP_NAME..."
|
||||||
|
|
||||||
for ((i=1; i<=MAX_RETRIES; i++)); do
|
for ((i=1; i<=MAX_RETRIES; i++)); do
|
||||||
@@ -163,4 +255,3 @@ in
|
|||||||
|
|
||||||
home.stateVersion = "26.05"; # DO NOT CHANGE
|
home.stateVersion = "26.05"; # DO NOT CHANGE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+76
-26
@@ -1,5 +1,8 @@
|
|||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
javaDebug = pkgs.vscode-extensions.vscjava.vscode-java-debug;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
programs.neovim = {
|
programs.neovim = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -27,9 +30,8 @@
|
|||||||
vim.opt.updatetime = 50
|
vim.opt.updatetime = 50
|
||||||
vim.opt.foldmethod = "indent"
|
vim.opt.foldmethod = "indent"
|
||||||
vim.opt.foldlevel = 99
|
vim.opt.foldlevel = 99
|
||||||
|
|
||||||
vim.g.mapleader = " "
|
vim.g.mapleader = " "
|
||||||
vim.keymap.set("n", "<leader>", ":")
|
|
||||||
vim.keymap.set("n", "<leader>w", "<cmd>w<CR>", { silent = true })
|
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>q", "<cmd>q<CR>", { silent = true })
|
||||||
vim.keymap.set("n", "<leader>wq", "<cmd>wq<CR>", { silent = true })
|
vim.keymap.set("n", "<leader>wq", "<cmd>wq<CR>", { silent = true })
|
||||||
@@ -67,7 +69,7 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
require("lualine").setup({
|
require("lualine").setup({
|
||||||
ons = { theme = "auto" },
|
options = { theme = "auto" },
|
||||||
})
|
})
|
||||||
|
|
||||||
require("neocord").setup({
|
require("neocord").setup({
|
||||||
@@ -86,7 +88,14 @@
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
-- Java indentation must match Eclipse's formatter, not your 2-space default.
|
-- Indent is left off deliberately: treesitter's Java indent fights the
|
||||||
|
-- Eclipse-matching tab settings applied in the FileType autocmd below.
|
||||||
|
require("nvim-treesitter.configs").setup({
|
||||||
|
highlight = { enable = true },
|
||||||
|
indent = { enable = false },
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Java indentation must match Eclipse's formatter, not the 2-space default.
|
||||||
vim.api.nvim_create_autocmd("FileType", {
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
pattern = "java",
|
pattern = "java",
|
||||||
callback = function()
|
callback = function()
|
||||||
@@ -117,24 +126,41 @@
|
|||||||
|
|
||||||
local capabilities = require("cmp_nvim_lsp").default_capabilities()
|
local capabilities = require("cmp_nvim_lsp").default_capabilities()
|
||||||
|
|
||||||
-- .project and .classpath come first so a repo containing several
|
local bundles = vim.fn.glob(
|
||||||
-- assignments resolves to the assignment, not the repo root.
|
"${javaDebug}/share/vscode/extensions/vscjava.vscode-java-debug/server/com.microsoft.java.debug.plugin-*.jar",
|
||||||
local root_markers = { ".project", ".classpath", "pom.xml", "build.gradle", ".git" }
|
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
|
||||||
|
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 function start_jdtls()
|
||||||
local jdtls = require("jdtls")
|
local jdtls = require("jdtls")
|
||||||
local root_dir = require("jdtls.setup").find_root(root_markers)
|
local root_dir = find_project_root()
|
||||||
if not root_dir or root_dir == "" then return end
|
|
||||||
|
|
||||||
local project_name = vim.fn.fnamemodify(root_dir, ":p:h:t")
|
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 workspace = vim.fn.stdpath("cache") .. "/jdtls-workspaces/" .. project_name
|
||||||
|
|
||||||
local java_settings = {
|
local java_settings = {
|
||||||
configuration = {
|
configuration = {
|
||||||
updateBuildConfiguration = "interactive",
|
updateBuildConfiguration = "automatic",
|
||||||
runtimes = {
|
|
||||||
{ name = "JavaSE-21", path = os.getenv("JAVA_HOME"), default = true },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
-- Keep a stray pom.xml from overriding the Eclipse project model.
|
-- Keep a stray pom.xml from overriding the Eclipse project model.
|
||||||
-- Flip these on if a course actually requires Maven or Gradle.
|
-- Flip these on if a course actually requires Maven or Gradle.
|
||||||
@@ -142,10 +168,20 @@
|
|||||||
maven = { enabled = false },
|
maven = { enabled = false },
|
||||||
gradle = { enabled = false },
|
gradle = { enabled = false },
|
||||||
},
|
},
|
||||||
|
project = {
|
||||||
|
outputPath = "bin",
|
||||||
|
referencedLibraries = { "lib/**/*.jar" },
|
||||||
|
},
|
||||||
signatureHelp = { enabled = true },
|
signatureHelp = { enabled = true },
|
||||||
eclipse = { downloadSources = 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.
|
-- If the repo carries an exported Eclipse formatter profile, use it verbatim.
|
||||||
local formatter = root_dir .. "/.settings/eclipse-formatter.xml"
|
local formatter = root_dir .. "/.settings/eclipse-formatter.xml"
|
||||||
if vim.uv.fs_stat(formatter) then
|
if vim.uv.fs_stat(formatter) then
|
||||||
@@ -157,8 +193,14 @@
|
|||||||
root_dir = root_dir,
|
root_dir = root_dir,
|
||||||
capabilities = capabilities,
|
capabilities = capabilities,
|
||||||
settings = { java = java_settings },
|
settings = { java = java_settings },
|
||||||
init_options = { bundles = {} },
|
init_options = { bundles = bundles },
|
||||||
on_attach = function(_, bufnr)
|
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
|
local map = function(k, f) vim.keymap.set("n", k, f, { buffer = bufnr, silent = true }) end
|
||||||
map("gd", vim.lsp.buf.definition)
|
map("gd", vim.lsp.buf.definition)
|
||||||
map("gr", vim.lsp.buf.references)
|
map("gr", vim.lsp.buf.references)
|
||||||
@@ -176,15 +218,25 @@
|
|||||||
callback = start_jdtls,
|
callback = start_jdtls,
|
||||||
})
|
})
|
||||||
|
|
||||||
require("neotest").setup({
|
local dap, dapui = require("dap"), require("dapui")
|
||||||
adapters = {
|
dapui.setup()
|
||||||
require("neotest-java")({
|
require("nvim-dap-virtual-text").setup()
|
||||||
junit_jar = vim.uv.os_homedir() .. "/dev/jars/junit-*.jar",
|
|
||||||
-- jvm_args = { "-Xmx512m" },
|
dap.listeners.after.event_initialized["dapui"] = function() dapui.open() end
|
||||||
incremental_build = true,
|
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; [
|
plugins = with pkgs.vimPlugins; [
|
||||||
@@ -197,11 +249,9 @@
|
|||||||
{ plugin = gitsigns-nvim; }
|
{ plugin = gitsigns-nvim; }
|
||||||
|
|
||||||
{ plugin = nvim-jdtls; }
|
{ plugin = nvim-jdtls; }
|
||||||
{ plugin = nvim-nio; }
|
|
||||||
{ plugin = neotest; }
|
|
||||||
{ plugin = neotest-java; }
|
|
||||||
{ plugin = nvim-dap; }
|
{ plugin = nvim-dap; }
|
||||||
{ plugin = nvim-dap-ui; }
|
{ plugin = nvim-dap-ui; }
|
||||||
|
{ plugin = nvim-nio; }
|
||||||
{ plugin = nvim-dap-virtual-text; }
|
{ plugin = nvim-dap-virtual-text; }
|
||||||
{ plugin = nvim-cmp; }
|
{ plugin = nvim-cmp; }
|
||||||
{ plugin = cmp-nvim-lsp; }
|
{ plugin = cmp-nvim-lsp; }
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
trap "rm -f '$ERRFILE'" EXIT
|
trap "rm -f '$ERRFILE'" EXIT
|
||||||
|
|
||||||
echo "Building NixOS..."
|
echo "Building NixOS..."
|
||||||
|
cd $DOTFILES && git stage -A
|
||||||
sudo nixos-rebuild switch --flake "$DOTFILES#$HOST" 2>&1 | tee "$ERRFILE"
|
sudo nixos-rebuild switch --flake "$DOTFILES#$HOST" 2>&1 | tee "$ERRFILE"
|
||||||
STATUS=''${PIPESTATUS[0]}
|
STATUS=''${PIPESTATUS[0]}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user