Skip to content

Commit db82708

Browse files
committed
feat: unified setup(opts), async vim.ui dialogs
- setup(opts) becomes the single config entry point; options bridge to legacy g:jc_* variables which still work as fallback - shared jc.ui.ask_for (vim.ui.input) with per-project memory replaces the duplicated blocking ask_for in dap and vimspector - dap attach validates host and port range - vimspector config chooser uses vim.ui.select - choose_imports stays on blocking input: the synchronous executeClientCommand handler must return the candidate to jdtls
1 parent 72ab33b commit db82708

6 files changed

Lines changed: 134 additions & 83 deletions

File tree

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,23 @@ return {
5454

5555
## Configurations
5656

57-
`g:jc_default_mappings` – apply default mappings (default: 1)
57+
All options go through `setup(opts)` (or the `opts` table of your plugin
58+
manager):
5859

59-
`g:jc_autoformat_on_save` – execute code autoformatting on file save (default: 1)
60+
```lua
61+
require("jc").setup({
62+
keys_prefix = "<leader>j", -- prefix for the default mappings
63+
default_mappings = true, -- install default mappings on attach
64+
autoformat_on_save = false, -- format java buffers on save
65+
debug_backend = nil, -- "dap" | "vimspector" | nil (auto-detect)
66+
basedir = nil, -- data dir, default ~/.local/share/jc.nvim
67+
on_attach = nil, -- function(client, bufnr) extra hook
68+
})
69+
```
70+
71+
The legacy `g:jc_default_mappings`, `g:jc_autoformat_on_save`,
72+
`g:jc_debug_backend` and `g:jc_basedir` variables still work as a
73+
fallback when the corresponding option is not passed to `setup`.
6074

6175
## Commands
6276

lua/jc.lua

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ local default_config = {
77
keys_prefix = "<leader>j",
88
}
99

10+
-- setup(opts) is the single configuration entry point; these opts are
11+
-- bridged to the legacy g:jc_* variables that vimscript parts and older
12+
-- configs still read
13+
local g_bridge = {
14+
default_mappings = "jc_default_mappings",
15+
autoformat_on_save = "jc_autoformat_on_save",
16+
debug_backend = "jc_debug_backend",
17+
basedir = "jc_basedir",
18+
}
19+
1020
M.config = vim.deepcopy(default_config)
1121

1222
local did_setup = false
@@ -40,6 +50,12 @@ function M.setup(args)
4050
user_on_attach = args.on_attach
4151
args.on_attach = nil
4252
end
53+
for opt, gvar in pairs(g_bridge) do
54+
if args[opt] ~= nil then
55+
vim.g[gvar] = args[opt]
56+
args[opt] = nil
57+
end
58+
end
4359
M.config = vim.tbl_deep_extend("keep", args, default_config)
4460

4561
resolve_jol_path()

lua/jc/dap.lua

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,11 @@
77
-- `vscode.java.startDebugSession` and connect a plain `server` adapter, then
88
-- send a JDWP attach (hostName/port = the running JVM).
99
local M = {}
10-
local settings = require("jc.settings")
1110
local lsp = require("jc.lsp")
11+
local ui = require("jc.ui")
1212

1313
local ADAPTER = "jc_java_attach"
1414

15-
local function ask_for(name, default)
16-
local default_result = settings.read_project("debug-" .. name, default)
17-
local result = vim.fn.input("Debug " .. name .. " (" .. default_result .. "): ")
18-
if #result == 0 then
19-
result = default_result
20-
elseif result ~= default_result then
21-
settings.write_project("debug-" .. name, result)
22-
end
23-
return result
24-
end
25-
2615
-- register an adapter that resolves the java-debug session port on demand
2716
local function ensure_adapter(dap)
2817
dap.adapters[ADAPTER] = function(callback)
@@ -38,6 +27,8 @@ local function ensure_adapter(dap)
3827
end
3928
end
4029

30+
local do_attach
31+
4132
-- best-effort project name (java-debug needs it to bind breakpoints/sources)
4233
local function resolve_project(callback)
4334
lsp.executeCommand({ command = "vscode.java.resolveMainClass" }, function(response)
@@ -58,12 +49,23 @@ function M.debug_attach()
5849
return
5950
end
6051
ensure_adapter(dap)
61-
local host = ask_for("host", "127.0.0.1")
62-
local port = tonumber(ask_for("port", "5005"))
63-
if not port then
64-
vim.notify("jc.dap: invalid port", vim.log.levels.ERROR)
65-
return
66-
end
52+
ui.ask_for("host", "127.0.0.1", function(host)
53+
if not host:match("^[%w%.%-_]+$") then
54+
vim.notify("jc.dap: invalid host: " .. host, vim.log.levels.ERROR)
55+
return
56+
end
57+
ui.ask_for("port", "5005", function(port_input)
58+
local port = tonumber(port_input)
59+
if not port or port < 1 or port > 65535 then
60+
vim.notify("jc.dap: invalid port: " .. port_input, vim.log.levels.ERROR)
61+
return
62+
end
63+
do_attach(dap, host, port)
64+
end)
65+
end)
66+
end
67+
68+
function do_attach(dap, host, port)
6769
resolve_project(function(project_name)
6870
dap.run({
6971
type = ADAPTER,

lua/jc/jdtls.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ local function choose_imports(params, _)
3333
for _, name in ipairs(to_forget) do
3434
regulars:remove(name)
3535
end
36+
-- blocking input is intentional: this runs inside the synchronous
37+
-- workspace/executeClientCommand handler and must return the chosen
38+
-- candidate to jdtls; async vim.ui.select can't do that
3639
local choice = tonumber(vim.fn.input(prompt .. "Your choice: "))
3740

3841
if candidates[choice] ~= nil then

lua/jc/ui.lua

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
local settings = require("jc.settings")
2+
3+
local M = {}
4+
5+
-- ask for a value, remembering the answer per project
6+
-- (shared by the dap and vimspector debug backends); async via vim.ui.input
7+
function M.ask_for(name, default, callback)
8+
local remembered = settings.read_project("debug-" .. name, default)
9+
vim.ui.input({ prompt = "Debug " .. name .. " (" .. remembered .. "): " }, function(result)
10+
if result == nil then
11+
return -- cancelled
12+
end
13+
if #result == 0 then
14+
result = remembered
15+
elseif result ~= remembered then
16+
settings.write_project("debug-" .. name, result)
17+
end
18+
callback(result)
19+
end)
20+
end
21+
22+
return M

lua/jc/vimspector.lua

Lines changed: 57 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
local M = {}
2-
local settings = require("jc.settings")
32
local lsp = require("jc.lsp")
4-
5-
local function ask_for(name, default)
6-
local default_result = settings.read_project("debug-" .. name, default)
7-
local result = vim.fn.input("Debug " .. name .. " (" .. default_result .. "): ")
8-
if #result == 0 then
9-
result = default_result
10-
elseif result ~= default_result then
11-
settings.write_project("debug-" .. name, result)
12-
end
13-
return result
14-
end
3+
local ui = require("jc.ui")
154

165
local function resolve_main_class(callback)
176
lsp.executeCommand({ command = "vscode.java.resolveMainClass" }, function(response)
@@ -50,71 +39,76 @@ function M.debug_launch()
5039
else
5140
classpaths = classpaths[2]
5241
end
53-
lsp.executeCommand({ command = "vscode.java.startDebugSession" }, function(response)
54-
vim.fn["vimspector#LaunchWithConfigurations"]({
55-
attach = {
56-
adapter = {
57-
name = "vscode-java",
58-
port = response,
59-
},
60-
configuration = {
61-
request = "launch",
62-
mainClass = main_class,
63-
args = ask_for("arguments", ""),
64-
classPaths = classpaths,
65-
console = "integratedTerminal",
66-
},
67-
breakpoints = {
68-
exception = {
69-
caught = "N",
70-
uncaught = "N",
42+
ui.ask_for("arguments", "", function(arguments)
43+
lsp.executeCommand({ command = "vscode.java.startDebugSession" }, function(response)
44+
vim.fn["vimspector#LaunchWithConfigurations"]({
45+
attach = {
46+
adapter = {
47+
name = "vscode-java",
48+
port = response,
49+
},
50+
configuration = {
51+
request = "launch",
52+
mainClass = main_class,
53+
args = arguments,
54+
classPaths = classpaths,
55+
console = "integratedTerminal",
56+
},
57+
breakpoints = {
58+
exception = {
59+
caught = "N",
60+
uncaught = "N",
61+
},
7162
},
7263
},
73-
},
74-
})
64+
})
65+
end)
7566
end)
7667
end)
7768
end)
7869
end
7970

8071
function M.debug_attach()
81-
lsp.executeCommand({ command = "vscode.java.startDebugSession" }, function(response)
82-
if type(response) == "number" then
83-
vim.fn["vimspector#LaunchWithConfigurations"]({
84-
attach = {
85-
adapter = {
86-
name = "vscode-java",
87-
port = response,
88-
},
89-
configuration = {
90-
request = "attach",
91-
host = ask_for("host", "127.0.0.1"),
92-
port = ask_for("port", "9000"),
93-
},
94-
breakpoints = {
95-
exception = {
96-
caught = "N",
97-
uncaught = "N",
72+
ui.ask_for("host", "127.0.0.1", function(host)
73+
ui.ask_for("port", "9000", function(port)
74+
lsp.executeCommand({ command = "vscode.java.startDebugSession" }, function(response)
75+
if type(response) == "number" then
76+
vim.fn["vimspector#LaunchWithConfigurations"]({
77+
attach = {
78+
adapter = {
79+
name = "vscode-java",
80+
port = response,
81+
},
82+
configuration = {
83+
request = "attach",
84+
host = host,
85+
port = port,
86+
},
87+
breakpoints = {
88+
exception = {
89+
caught = "N",
90+
uncaught = "N",
91+
},
92+
},
9893
},
99-
},
100-
},
101-
})
102-
else
103-
vim.notify(vim.inspect(response), vim.log.levels.WARN)
104-
end
94+
})
95+
else
96+
vim.notify(vim.inspect(response), vim.log.levels.WARN)
97+
end
98+
end)
99+
end)
105100
end)
106101
end
107102

108103
function M.debug_choose_configuration()
109-
local prompt = "Choose vimspector configuration:\n"
110104
local configs = vim.fn["vimspector#GetConfigurations"]()
111-
for i, config in ipairs(configs) do
112-
prompt = prompt .. i .. ". " .. config .. "\n"
113-
end
114-
prompt = prompt .. "Your choice: "
115-
local choice = tonumber(vim.fn.input(prompt))
116-
lsp.executeCommand({ command = "vscode.java.startDebugSession" }, function(response)
117-
vim.fn["vimspector#LaunchWithSettings"]({ configuration = configs[choice], AdapterPort = response })
105+
vim.ui.select(configs, { prompt = "Choose vimspector configuration:" }, function(choice)
106+
if not choice then
107+
return
108+
end
109+
lsp.executeCommand({ command = "vscode.java.startDebugSession" }, function(response)
110+
vim.fn["vimspector#LaunchWithSettings"]({ configuration = choice, AdapterPort = response })
111+
end)
118112
end)
119113
end
120114

0 commit comments

Comments
 (0)