updating with .md viewer

This commit is contained in:
Joe Sinopoli 2026-04-04 00:53:56 -04:00
parent 4bb0089b39
commit 4483ac6a6d
5 changed files with 713 additions and 4 deletions

View File

@ -562,6 +562,16 @@ require('lazy').setup({
-- or a suggestion from your LSP for this to activate.
map('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction', { 'n', 'x' })
-- Organize imports (Python via Pyright code actions)
map('<leader>co', function()
vim.lsp.buf.code_action({
context = {
only = { 'source.organizeImports' },
},
apply = true,
})
end, '[C]ode [O]rganize Imports')
-- WARN: This is not Goto Definition, this is Goto Declaration.
-- For example, in C this would take you to the header.
map('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
@ -673,8 +683,21 @@ require('lazy').setup({
local servers = {
-- clangd = {},
-- gopls = {},
pyright = {},
jdtls = {},
pyright = {
settings = {
python = {
analysis = {
autoSearchPaths = true,
useLibraryCodeForTypes = true,
diagnosticMode = 'workspace',
typeCheckingMode = 'basic',
autoImportCompletions = true,
},
},
},
},
-- NOTE: jdtls is configured separately via nvim-jdtls plugin (see custom/plugins/jdtls.lua)
-- Do not configure it here as it requires special handling
-- rust_analyzer = {},
-- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs
--
@ -717,6 +740,11 @@ require('lazy').setup({
local ensure_installed = vim.tbl_keys(servers or {})
vim.list_extend(ensure_installed, {
'stylua', -- Used to format Lua code
'jdtls', -- Java language server
'java-debug-adapter', -- Java debugger
'java-test', -- Java test runner
'isort', -- Python import organizer
'black', -- Python formatter
})
require('mason-tool-installer').setup { ensure_installed = ensure_installed }
@ -725,6 +753,10 @@ require('lazy').setup({
automatic_installation = false,
handlers = {
function(server_name)
-- Skip jdtls as it's configured separately via nvim-jdtls plugin
if server_name == 'jdtls' then
return
end
local server = servers[server_name] or {}
-- This handles overriding only values explicitly passed
-- by the server configuration above. Useful when disabling
@ -772,7 +804,7 @@ require('lazy').setup({
formatters_by_ft = {
lua = { 'stylua' },
-- Conform can also run multiple formatters sequentially
-- python = { "isort", "black" },
python = { "isort", "black" },
--
-- You can use 'stop_after_first' to run the first available formatter from the list
-- javascript = { "prettierd", "prettier", stop_after_first = true },
@ -1006,7 +1038,7 @@ require('lazy').setup({
-- This is the easiest way to modularize your config.
--
-- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going.
-- { import = 'custom.plugins' },
{ import = 'custom.plugins' },
--
-- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec`
-- Or use telescope!

195
lua/custom/maven.lua Normal file
View File

@ -0,0 +1,195 @@
-- Maven command runner with UI
local M = {}
-- Store last command for quick re-run
M.last_command = nil
-- Common Maven phases and goals
M.maven_commands = {
-- Lifecycle Phases
{ name = "clean", desc = "Clean the project (remove target/)" },
{ name = "validate", desc = "Validate project structure" },
{ name = "compile", desc = "Compile source code" },
{ name = "test", desc = "Run unit tests" },
{ name = "test-compile", desc = "Compile test sources" },
{ name = "package", desc = "Package compiled code (JAR/WAR)" },
{ name = "verify", desc = "Run integration tests" },
{ name = "install", desc = "Install package to local repository" },
{ name = "deploy", desc = "Deploy to remote repository" },
-- Common Combined Commands
{ name = "clean compile", desc = "Clean and compile" },
{ name = "clean test", desc = "Clean and test" },
{ name = "clean package", desc = "Clean and package" },
{ name = "clean install", desc = "Clean and install" },
-- Plugin Goals
{ name = "dependency:tree", desc = "Display dependency tree" },
{ name = "dependency:analyze", desc = "Analyze dependencies" },
{ name = "versions:display-dependency-updates", desc = "Check for dependency updates" },
{ name = "help:effective-pom", desc = "Show effective POM" },
-- Spring Boot specific (if applicable)
{ name = "spring-boot:run", desc = "Run Spring Boot application" },
-- Testing specific
{ name = "test -Dtest=", desc = "Run specific test class (specify after =)", custom_input = true },
{ name = "test -Dtest=*Test", desc = "Run all test classes" },
{ name = "surefire-report:report", desc = "Generate test report" },
}
-- Execute Maven command
function M.execute_maven(cmd, opts)
opts = opts or {}
-- Check if mvn exists
local mvn_cmd = vim.fn.executable("mvn") == 1 and "mvn" or nil
if not mvn_cmd then
vim.notify("Maven (mvn) not found in PATH. Install with: brew install maven", vim.log.levels.ERROR)
return
end
-- Store last command
M.last_command = cmd
-- Determine if we're in a Maven project
local pom_exists = vim.fn.filereadable(vim.fn.getcwd() .. "/pom.xml") == 1
if not pom_exists then
vim.notify("No pom.xml found in current directory: " .. vim.fn.getcwd(), vim.log.levels.WARN)
local proceed = vim.fn.confirm("Run Maven anyway?", "&Yes\n&No", 2)
if proceed ~= 1 then
return
end
end
local full_cmd = "mvn " .. cmd
-- Choose display method based on preference
if opts.background then
-- Run in background, show in quickfix
vim.notify("Running: " .. full_cmd, vim.log.levels.INFO)
vim.fn.setqflist({}, 'r', { title = full_cmd, lines = {} })
vim.cmd("copen")
vim.fn.jobstart(full_cmd, {
on_stdout = function(_, data)
if data then
vim.fn.setqflist({}, 'a', { lines = data })
end
end,
on_stderr = function(_, data)
if data then
vim.fn.setqflist({}, 'a', { lines = data })
end
end,
on_exit = function(_, exit_code)
if exit_code == 0 then
vim.notify("Maven command completed successfully", vim.log.levels.INFO)
else
vim.notify("Maven command failed with exit code: " .. exit_code, vim.log.levels.ERROR)
end
end,
})
else
-- Run in terminal split
vim.cmd("botright 15split | terminal " .. full_cmd)
vim.cmd("startinsert")
end
end
-- Show Maven menu using vim.ui.select
function M.show_menu()
local choices = {}
for i, cmd in ipairs(M.maven_commands) do
choices[i] = string.format("%-40s | %s", cmd.name, cmd.desc)
end
vim.ui.select(choices, {
prompt = "Select Maven command:",
format_item = function(item)
return item
end,
}, function(choice, idx)
if not choice then
return
end
local selected = M.maven_commands[idx]
-- Handle custom input commands
if selected.custom_input then
vim.ui.input({
prompt = "Enter Maven command: ",
default = selected.name,
}, function(input)
if input and input ~= "" then
M.execute_maven(input)
end
end)
else
M.execute_maven(selected.name)
end
end)
end
-- Run last Maven command
function M.run_last()
if M.last_command then
vim.notify("Re-running: mvn " .. M.last_command, vim.log.levels.INFO)
M.execute_maven(M.last_command)
else
vim.notify("No previous Maven command to run", vim.log.levels.WARN)
M.show_menu()
end
end
-- Quick command to run specific test
function M.run_test(test_name)
if test_name then
M.execute_maven("test -Dtest=" .. test_name)
else
-- Try to infer test name from current file
local current_file = vim.fn.expand("%:t:r") -- filename without extension
if current_file:match("Test$") or current_file:match("Tests$") then
vim.ui.input({
prompt = "Test class name:",
default = current_file,
}, function(input)
if input and input ~= "" then
M.execute_maven("test -Dtest=" .. input)
end
end)
else
M.execute_maven("test")
end
end
end
-- User command to run Maven
vim.api.nvim_create_user_command("Maven", function(opts)
if opts.args and opts.args ~= "" then
M.execute_maven(opts.args)
else
M.show_menu()
end
end, {
nargs = "*",
desc = "Run Maven command",
complete = function()
local completions = {}
for _, cmd in ipairs(M.maven_commands) do
table.insert(completions, cmd.name)
end
return completions
end,
})
-- User command to run tests
vim.api.nvim_create_user_command("MavenTest", function(opts)
M.run_test(opts.args ~= "" and opts.args or nil)
end, {
nargs = "?",
desc = "Run Maven tests",
})
return M

View File

@ -0,0 +1,239 @@
-- Custom DAP configuration for Python and Java
return {
-- Main DAP plugin
{
"mfussenegger/nvim-dap",
dependencies = {
"williamboman/mason.nvim",
"jay-babu/mason-nvim-dap.nvim",
},
keys = {
-- Basic debugging keymaps
{
"<F5>",
function()
require("dap").continue()
end,
desc = "Debug: Start/Continue",
},
{
"<F1>",
function()
require("dap").step_into()
end,
desc = "Debug: Step Into",
},
{
"<F2>",
function()
require("dap").step_over()
end,
desc = "Debug: Step Over",
},
{
"<F3>",
function()
require("dap").step_out()
end,
desc = "Debug: Step Out",
},
{
"<leader>b",
function()
require("dap").toggle_breakpoint()
end,
desc = "Debug: Toggle Breakpoint",
},
{
"<leader>B",
function()
require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: "))
end,
desc = "Debug: Set Conditional Breakpoint",
},
-- Additional keymaps
{
"<leader>dc",
function()
require("dap").continue()
end,
desc = "Debug: Continue",
},
{
"<leader>dr",
function()
require("dap").repl.toggle()
end,
desc = "Debug: Toggle REPL",
},
{
"<leader>dl",
function()
require("dap").run_last()
end,
desc = "Debug: Run Last",
},
{
"<leader>dt",
function()
require("dap").terminate()
end,
desc = "Debug: Terminate",
},
},
config = function()
local dap = require("dap")
-- Mason DAP setup - auto-install debuggers
require("mason-nvim-dap").setup({
automatic_installation = true,
ensure_installed = {
"python",
"javadbg",
"javatest",
},
handlers = {},
})
-- Set up breakpoint icons
local icons = vim.g.have_nerd_font
and { Breakpoint = "", BreakpointCondition = "", BreakpointRejected = "", LogPoint = "", Stopped = "" }
or { Breakpoint = "", BreakpointCondition = "", BreakpointRejected = "", LogPoint = "", Stopped = "" }
for type, icon in pairs(icons) do
local hl = (type == "Stopped") and "DapStop" or "DapBreak"
vim.fn.sign_define("Dap" .. type, { text = icon, texthl = hl, numhl = hl })
end
end,
},
-- Python DAP support
{
"mfussenegger/nvim-dap-python",
ft = "python",
dependencies = {
"mfussenegger/nvim-dap",
},
config = function()
-- Find python path - prefer virtual environment
local python_path = function()
local cwd = vim.fn.getcwd()
if vim.fn.executable(cwd .. "/venv/bin/python") == 1 then
return cwd .. "/venv/bin/python"
elseif vim.fn.executable(cwd .. "/.venv/bin/python") == 1 then
return cwd .. "/.venv/bin/python"
else
return "python3"
end
end
require("dap-python").setup(python_path())
-- Add custom configurations
table.insert(require("dap").configurations.python, {
type = "python",
request = "launch",
name = "Launch file with arguments",
program = "${file}",
args = function()
local args_string = vim.fn.input("Arguments: ")
return vim.split(args_string, " +")
end,
})
table.insert(require("dap").configurations.python, {
type = "python",
request = "launch",
name = "Django",
program = vim.fn.getcwd() .. "/manage.py",
args = { "runserver", "--noreload" },
})
end,
},
-- Java DAP support is handled by nvim-jdtls (see jdtls.lua)
-- No separate configuration needed here
-- Enhanced UI for debugging
{
"rcarriga/nvim-dap-ui",
dependencies = { "mfussenegger/nvim-dap", "nvim-neotest/nvim-nio" },
keys = {
{
"<F7>",
function()
require("dapui").toggle()
end,
desc = "Debug: Toggle UI",
},
{
"<leader>du",
function()
require("dapui").toggle()
end,
desc = "Debug: Toggle UI",
},
},
config = function()
local dapui = require("dapui")
local dap = require("dap")
-- Configure UI
dapui.setup({
layouts = {
{
elements = {
{ id = "scopes", size = 0.25 },
{ id = "breakpoints", size = 0.25 },
{ id = "stacks", size = 0.25 },
{ id = "watches", size = 0.25 },
},
position = "left",
size = 40,
},
{
elements = {
{ id = "repl", size = 0.5 },
{ id = "console", size = 0.5 },
},
position = "bottom",
size = 10,
},
},
icons = vim.g.have_nerd_font and {
expanded = "",
collapsed = "",
current_frame = "",
} or {
expanded = "",
collapsed = "",
current_frame = "*",
},
controls = {
icons = {
pause = "",
play = "",
step_into = "",
step_over = "",
step_out = "",
step_back = "b",
run_last = "▶▶",
terminate = "",
disconnect = "",
},
},
})
-- Auto open/close UI
dap.listeners.after.event_initialized["dapui_config"] = function()
dapui.open()
end
dap.listeners.before.event_terminated["dapui_config"] = function()
dapui.close()
end
dap.listeners.before.event_exited["dapui_config"] = function()
dapui.close()
end
end,
},
}

View File

@ -0,0 +1,221 @@
-- Java LSP configuration using nvim-jdtls
-- This provides better Java support including auto-imports, code actions, etc.
return {
"mfussenegger/nvim-jdtls",
ft = "java",
dependencies = {
"mfussenegger/nvim-dap",
"williamboman/mason.nvim",
},
config = function()
-- This function will be called when a Java file is opened
local function setup_jdtls()
local jdtls = require("jdtls")
-- Find the Mason installation path
local mason_registry = require("mason-registry")
local jdtls_path = mason_registry.get_package("jdtls"):get_install_path()
-- Find the appropriate jar file (the launcher)
local jar_patterns = {
jdtls_path .. "/plugins/org.eclipse.equinox.launcher_*.jar",
}
local jar_path = nil
for _, pattern in ipairs(jar_patterns) do
local matches = vim.fn.glob(pattern, true, true)
if #matches > 0 then
jar_path = matches[1]
break
end
end
if not jar_path then
vim.notify("Could not find JDTLS launcher jar", vim.log.levels.ERROR)
return
end
-- Determine the OS-specific configuration
local os_config = "linux"
if vim.fn.has("mac") == 1 then
os_config = "mac"
elseif vim.fn.has("win32") == 1 then
os_config = "win"
end
-- Data directory for this workspace
local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:t")
local workspace_dir = vim.fn.stdpath("data") .. "/jdtls-workspace/" .. project_name
-- Get the Java debug adapter bundles
local bundles = {}
local java_debug_path = mason_registry.get_package("java-debug-adapter"):get_install_path()
-- Add java-debug adapter (required for debugging)
vim.list_extend(bundles, vim.fn.glob(java_debug_path .. "/extension/server/com.microsoft.java.debug.plugin-*.jar", true, true))
-- NOTE: java-test bundles disabled due to org.objectweb.asm dependency conflict
-- To run tests, use: mvn test or gradle test from command line
-- local java_test_path = mason_registry.get_package("java-test"):get_install_path()
-- vim.list_extend(bundles, vim.fn.glob(java_test_path .. "/extension/server/*.jar", true, true))
-- Find Lombok jar
local lombok_path = jdtls_path .. "/lombok.jar"
-- LSP settings for Java
local extendedClientCapabilities = jdtls.extendedClientCapabilities
extendedClientCapabilities.resolveAdditionalTextEditsSupport = true
-- Build cmd array with Lombok support
local cmd = {
"java",
"-Declipse.application=org.eclipse.jdt.ls.core.id1",
"-Dosgi.bundles.defaultStartLevel=4",
"-Declipse.product=org.eclipse.jdt.ls.core.product",
"-Dlog.protocol=true",
"-Dlog.level=ALL",
"-Xmx1g",
"--add-modules=ALL-SYSTEM",
"--add-opens", "java.base/java.util=ALL-UNNAMED",
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
}
-- Add Lombok agent if jar exists
if vim.fn.filereadable(lombok_path) == 1 then
table.insert(cmd, "-javaagent:" .. lombok_path)
end
-- Add jar and configuration
table.insert(cmd, "-jar")
table.insert(cmd, jar_path)
table.insert(cmd, "-configuration")
table.insert(cmd, jdtls_path .. "/config_" .. os_config)
table.insert(cmd, "-data")
table.insert(cmd, workspace_dir)
local config = {
cmd = cmd,
root_dir = require("jdtls.setup").find_root({".git", "mvnw", "gradlew", "pom.xml", "build.gradle"}),
settings = {
java = {
eclipse = {
downloadSources = true,
},
configuration = {
updateBuildConfiguration = "interactive",
},
maven = {
downloadSources = true,
},
implementationsCodeLens = {
enabled = true,
},
referencesCodeLens = {
enabled = true,
},
references = {
includeDecompiledSources = true,
},
format = {
enabled = true,
},
-- Enable auto-import completion
completion = {
favoriteStaticMembers = {
"org.junit.jupiter.api.Assertions.*",
"org.junit.Assert.*",
"org.mockito.Mockito.*",
"org.mockito.ArgumentMatchers.*",
},
importOrder = {
"java",
"javax",
"com",
"org",
},
},
sources = {
organizeImports = {
starThreshold = 9999,
staticStarThreshold = 9999,
},
},
codeGeneration = {
toString = {
template = "${object.className}{${member.name()}=${member.value}, ${otherMembers}}",
},
useBlocks = true,
},
},
signatureHelp = { enabled = true },
extendedClientCapabilities = extendedClientCapabilities,
},
init_options = {
bundles = bundles,
},
on_attach = function(client, bufnr)
-- Enable completion triggered by <c-x><c-o>
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
-- JDTLS-specific keybindings
local opts = { buffer = bufnr, noremap = true, silent = true }
-- Organize imports
vim.keymap.set("n", "<leader>co", function()
require("jdtls").organize_imports()
end, vim.tbl_extend("force", opts, { desc = "LSP: [C]ode [O]rganize Imports" }))
-- Extract variable
vim.keymap.set("n", "<leader>cv", function()
require("jdtls").extract_variable()
end, vim.tbl_extend("force", opts, { desc = "LSP: [C]ode Extract [V]ariable" }))
vim.keymap.set("v", "<leader>cv", function()
require("jdtls").extract_variable(true)
end, vim.tbl_extend("force", opts, { desc = "LSP: [C]ode Extract [V]ariable" }))
-- Extract constant
vim.keymap.set("n", "<leader>cc", function()
require("jdtls").extract_constant()
end, vim.tbl_extend("force", opts, { desc = "LSP: [C]ode Extract [C]onstant" }))
vim.keymap.set("v", "<leader>cc", function()
require("jdtls").extract_constant(true)
end, vim.tbl_extend("force", opts, { desc = "LSP: [C]ode Extract [C]onstant" }))
-- Extract method
vim.keymap.set("v", "<leader>cm", function()
require("jdtls").extract_method(true)
end, vim.tbl_extend("force", opts, { desc = "LSP: [C]ode Extract [M]ethod" }))
-- Test class/method (disabled - java-test bundles not loaded)
-- Use command line instead: mvn test -Dtest=ClassName or mvn test -Dtest=ClassName#methodName
-- vim.keymap.set("n", "<leader>tn", function()
-- require("jdtls").test_nearest_method()
-- end, vim.tbl_extend("force", opts, { desc = "LSP: [T]est [N]earest Method" }))
--
-- vim.keymap.set("n", "<leader>tc", function()
-- require("jdtls").test_class()
-- end, vim.tbl_extend("force", opts, { desc = "LSP: [T]est [C]lass" }))
-- DAP setup
jdtls.setup_dap({ hotcodereplace = "auto" })
require("jdtls.dap").setup_dap_main_class_configs()
end,
}
-- Start or attach to the language server
jdtls.start_or_attach(config)
end
-- Set up an autocommand to start JDTLS when opening Java files
vim.api.nvim_create_autocmd("FileType", {
pattern = "java",
callback = setup_jdtls,
})
end,
}

View File

@ -0,0 +1,22 @@
-- Maven Runner - UI for running Maven phases and goals
return {
"mfussenegger/nvim-jdtls",
keys = {
{
"<leader>m",
function()
require("custom.maven").show_menu()
end,
desc = "Maven: Show Menu",
ft = "java",
},
{
"<leader>mr",
function()
require("custom.maven").run_last()
end,
desc = "Maven: Run Last Command",
ft = "java",
},
},
}