Skip to content

Commit 1949e65

Browse files
committed
init
0 parents  commit 1949e65

File tree

17 files changed

+1553
-0
lines changed

17 files changed

+1553
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.luarc.json

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Java Projects
2+
3+
- 使用 [symbols-outline](https://github.com/simrat39/symbols-outline.nvim) 代码实现预览
4+
- [vscode-java-dependency](https://github.com/Microsoft/vscode-java-dependency) 提供数据支持

lua/java-deps.lua

Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
local context = require("java-deps.context")
2+
local parser = require("java-deps.parser")
3+
local providers = require("java-deps.providers.init")
4+
local lsp_command = require("java-deps.lsp-command")
5+
local ui = require("java-deps.ui")
6+
local writer = require("java-deps.writer")
7+
local config = require("java-deps.config")
8+
local utils = require("java-deps.utils.init")
9+
local View = require("java-deps.view")
10+
local folding = require("java-deps.folding")
11+
local node_kind = require("java-deps.symbols").node_kind
12+
local t_utils = require("java-deps.utils.table")
13+
14+
local M = {
15+
view = nil,
16+
-------------------------
17+
-- STATE
18+
-------------------------
19+
state = {
20+
preview_buf = nil,
21+
preview_win = nil,
22+
hover_buf = nil,
23+
hover_win = nil,
24+
flattened_outline_items = {},
25+
code_buf = nil,
26+
code_win = nil,
27+
outline_items = nil,
28+
},
29+
}
30+
31+
local function setup_global_autocmd()
32+
if config.options.highlight_hovered_item or config.options.auto_unfold_hover then
33+
vim.api.nvim_create_autocmd("CursorHold", {
34+
pattern = "*",
35+
callback = function()
36+
M._highlight_current_item(nil)
37+
end,
38+
})
39+
end
40+
41+
vim.api.nvim_create_autocmd("WinEnter", {
42+
pattern = "*",
43+
callback = require("java-deps.preview").close,
44+
})
45+
end
46+
47+
local function setup_buffer_autocmd(buf)
48+
if config.options.auto_preview then
49+
vim.api.nvim_create_autocmd("CursorHold", {
50+
buffer = buf,
51+
callback = require("java-deps.preview").show,
52+
})
53+
else
54+
vim.api.nvim_create_autocmd("CursorMoved", {
55+
buffer = buf,
56+
callback = require("java-deps.preview").close,
57+
})
58+
end
59+
end
60+
61+
local function wipe_state()
62+
M.state = { outline_items = {}, flattened_outline_items = {}, code_win = 0, code_buf = 0 }
63+
end
64+
65+
local function _update_lines()
66+
M.state.flattened_outline_items = parser.flatten(M.state.outline_items)
67+
writer.parse_and_write(M.view.bufnr, M.state.flattened_outline_items)
68+
end
69+
70+
function M._current_node()
71+
local current_line = vim.api.nvim_win_get_cursor(M.view.winnr)[1]
72+
return M.state.flattened_outline_items[current_line]
73+
end
74+
75+
local function goto_location(change_focus)
76+
local node = M._current_node()
77+
vim.api.nvim_win_set_cursor(M.state.code_win, { node.line + 1, node.character })
78+
if change_focus then
79+
vim.fn.win_gotoid(M.state.code_win)
80+
end
81+
if config.options.auto_close then
82+
M.close_outline()
83+
end
84+
end
85+
86+
local function package_handler(node)
87+
if not folding.is_foldable(node) then
88+
return
89+
end
90+
if M.view:is_open() then
91+
local children = {}
92+
local response = lsp_command.get_package_data(M.state.code_buf, node)
93+
if response == nil or type(response) ~= "table" then
94+
return
95+
end
96+
for _, value in ipairs(response) do
97+
if node_kind.CONTAINER == value.kind then
98+
if value.entryKind == value.kind then
99+
value.parent = node
100+
local c = lsp_command.get_package_data(M.state.code_buf, value)
101+
if c and c[1] then
102+
table.insert(children, c[1])
103+
end
104+
else
105+
table.insert(children, value)
106+
end
107+
else
108+
table.insert(children, value)
109+
end
110+
end
111+
112+
local child_hir = t_utils.array_copy(node.hierarchy)
113+
table.insert(child_hir, node.isLast)
114+
node.children = parser.parse(children, node.depth + 1, child_hir, node)
115+
return children
116+
end
117+
end
118+
119+
local function open_file(node)
120+
node = node or M._current_node()
121+
-- open_file
122+
local fname = node.uri
123+
if vim.startswith(fname, "file:") then
124+
vim.fn.win_gotoid(M.state.code_win)
125+
fname = string.sub(node.path, 2)
126+
local cmd = "edit " .. fname
127+
vim.cmd(cmd)
128+
if config.options.auto_close then
129+
M.close_outline()
130+
end
131+
end
132+
end
133+
134+
function M._set_folded_or_open(open, move_cursor, node_index)
135+
local node = M.state.flattened_outline_items[node_index] or M._current_node()
136+
local folded = false
137+
if node.folded ~= nil then
138+
folded = not node.folded
139+
end
140+
if node.kind == node_kind.FILE or node.kind == node_kind.PRIMARYTYPE then
141+
if move_cursor then
142+
vim.api.nvim_win_set_cursor(M.view.winnr, { node_index, 0 })
143+
end
144+
if open then
145+
open_file(node)
146+
end
147+
else
148+
M._set_folded(folded, move_cursor, node_index)
149+
end
150+
end
151+
function M._set_folded(folded, move_cursor, node_index)
152+
local node = M.state.flattened_outline_items[node_index] or M._current_node()
153+
if folding.is_foldable(node) then
154+
node.folded = folded
155+
156+
if move_cursor then
157+
vim.api.nvim_win_set_cursor(M.view.winnr, { node_index, 0 })
158+
end
159+
160+
package_handler(node)
161+
_update_lines()
162+
elseif node.parent then
163+
local parent_node = M.state.flattened_outline_items[node.parent.line_in_outline]
164+
165+
if parent_node then
166+
M._set_folded(folded, not parent_node.folded and folded, parent_node.line_in_outline)
167+
end
168+
end
169+
end
170+
171+
function M._set_all_folded(folded, nodes)
172+
nodes = nodes or M.state.outline_items
173+
174+
for _, node in ipairs(nodes) do
175+
node.folded = folded
176+
if node.children then
177+
M._set_all_folded(folded, node.children)
178+
end
179+
end
180+
181+
_update_lines()
182+
end
183+
184+
function M._highlight_current_item(winnr)
185+
local has_provider = providers.has_provider()
186+
187+
local is_current_buffer_the_outline = M.view.bufnr == vim.api.nvim_get_current_buf()
188+
189+
local doesnt_have_outline_buf = not M.view.bufnr
190+
191+
local should_exit = not has_provider or doesnt_have_outline_buf or is_current_buffer_the_outline
192+
193+
-- Make a special case if we have a window number
194+
-- Because we might use this to manually focus so we dont want to quit this
195+
-- function
196+
if winnr then
197+
should_exit = false
198+
end
199+
200+
if should_exit then
201+
return
202+
end
203+
204+
local win = winnr or vim.api.nvim_get_current_win()
205+
206+
local hovered_line = vim.api.nvim_win_get_cursor(win)[1] - 1
207+
208+
local leaf_node = nil
209+
210+
local cb = function(value)
211+
value.hovered = nil
212+
213+
if value.line == hovered_line then
214+
value.hovered = true
215+
leaf_node = value
216+
end
217+
end
218+
219+
utils.items_dfs(cb, M.state.outline_items)
220+
221+
_update_lines()
222+
223+
if leaf_node then
224+
for index, node in ipairs(M.state.flattened_outline_items) do
225+
if node == leaf_node then
226+
vim.api.nvim_win_set_cursor(M.view.winnr, { index, 1 })
227+
break
228+
end
229+
end
230+
end
231+
end
232+
233+
local function setup_keymaps(bufnr)
234+
local map = function(...)
235+
utils.nmap(bufnr, ...)
236+
end
237+
-- show help
238+
map(config.options.keymaps.show_help, require("java-deps.config").show_help)
239+
-- close outline
240+
map(config.options.keymaps.close, function()
241+
M.view:close()
242+
end)
243+
-- open_file
244+
map(config.options.keymaps.open_file, function()
245+
M._set_folded_or_open(true)
246+
end)
247+
-- fold selection
248+
map(config.options.keymaps.fold, function()
249+
M._set_folded(true)
250+
end)
251+
-- unfold selection
252+
map(config.options.keymaps.unfold, function()
253+
M._set_folded(false)
254+
end)
255+
-- fold all
256+
map(config.options.keymaps.fold_all, function()
257+
M._set_all_folded(true)
258+
end)
259+
-- unfold all
260+
map(config.options.keymaps.unfold_all, function()
261+
M._set_all_folded(false)
262+
end)
263+
-- fold reset
264+
map(config.options.keymaps.fold_reset, function()
265+
M._set_all_folded(nil)
266+
end)
267+
end
268+
269+
local function handler(response)
270+
if response == nil or type(response) ~= "table" then
271+
return
272+
end
273+
274+
M.state.code_win = vim.api.nvim_get_current_win()
275+
276+
M.view:setup_view()
277+
-- clear state when buffer is closed
278+
vim.api.nvim_buf_attach(M.view.bufnr, false, {
279+
on_detach = function(_, _)
280+
wipe_state()
281+
end,
282+
})
283+
284+
setup_keymaps(M.view.bufnr)
285+
setup_buffer_autocmd(M.state.code_buf)
286+
287+
local items = parser.parse(response)
288+
289+
M.state.outline_items = items
290+
M.state.flattened_outline_items = parser.flatten(items)
291+
292+
writer.parse_and_write(M.view.bufnr, M.state.flattened_outline_items)
293+
294+
M._highlight_current_item(M.state.code_win)
295+
end
296+
297+
function M.toggle_outline()
298+
if M.view:is_open() then
299+
M.close_outline()
300+
else
301+
M.open_outline()
302+
end
303+
end
304+
305+
local function resolve_path(path)
306+
local resp = lsp_command.resolve_path(M.state.code_buf, path)
307+
local function find_root(node)
308+
for _, value in ipairs(M.state.flattened_outline_items) do
309+
if value.kind == node.kind then
310+
if node.kind == 5 then
311+
if value.name == node.name then
312+
return value
313+
end
314+
elseif node.kind == 6 then
315+
if value.uri == node.uri then
316+
return value
317+
end
318+
elseif node.path ~= nil and value.path == node.path then
319+
return value
320+
end
321+
end
322+
end
323+
end
324+
if resp ~= nil then
325+
for _, value in ipairs(resp) do
326+
local node = find_root(value)
327+
if node ~= nil then
328+
M._set_folded_or_open(false, true, node.line_in_outline)
329+
end
330+
end
331+
end
332+
end
333+
334+
function M.open_outline()
335+
if not M.view:is_open() then
336+
M.state.code_buf = vim.api.nvim_get_current_buf()
337+
local resp = lsp_command.get_projects(M.state.code_buf, context.current_config().root_uri)
338+
local path = vim.uri_from_bufnr(M.state.code_buf)
339+
handler(resp)
340+
resolve_path(path)
341+
end
342+
end
343+
344+
function M.close_outline()
345+
M.view:close()
346+
end
347+
348+
function M.setup(opts)
349+
config.setup(opts)
350+
ui.setup_highlights()
351+
352+
M.view = View:new()
353+
setup_global_autocmd()
354+
end
355+
356+
M.attach = function(client, buf, root_dir)
357+
context.attach(client, buf, root_dir)
358+
end
359+
360+
return M

0 commit comments

Comments
 (0)