forked from pwntester/codeql.nvim
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexplorer.lua
More file actions
196 lines (177 loc) · 4.93 KB
/
Copy pathexplorer.lua
File metadata and controls
196 lines (177 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
local NuiTree = require "nui.tree"
local NuiLine = require "nui.line"
local Split = require "nui.split"
local Tree = require "codeql.tree"
local config = require "codeql.config"
local util = require "codeql.util"
local devicons = require "nvim-web-devicons"
local vim = vim
local M = {}
M.tree = nil
M.split = nil
M.width = 50
M.prepare_node = function(node)
if node.type == "label" then
local line = NuiLine()
for _, p in ipairs(node.name) do
line:append(p[1], p[2])
end
return line
end
local line = NuiLine()
line:append(string.rep(" ", node:get_depth() - 1))
if node:has_children() then
line:append(node:is_expanded() and " " or " ", "SpecialKey")
end
if node.type == "dir" then
line:append(node.name .. "/", "SpecialKey")
else
local name = vim.fn.split(node.name, "\\.")[1]
local ext = vim.fn.split(node.name, "\\.")[2]
local icon, hl = devicons.get_icon(name, ext)
icon = icon or ""
line:append(icon .. " ", hl)
line:append(node.name)
end
return line
end
M.create_tree = function()
M.tree = NuiTree {
winid = M.split.winid,
get_node_id = function(node)
return node.id
end,
prepare_node = M.prepare_node,
}
end
M.create_nodes = function(source_items, level)
level = level or 0
local nodes = {}
local indent = ""
local indent_size = 2
for _ = 1, level do
for _ = 1, indent_size do
indent = indent .. " "
end
end
for _, item in ipairs(source_items) do
local nodeData = {
id = item.id,
name = item.name,
type = item.type,
indent = indent,
}
local node_children = nil
if item.children ~= nil then
node_children = M.create_nodes(item.children, level + 1)
end
local node = NuiTree.Node(nodeData, node_children)
if item._is_expanded then
node:expand()
end
table.insert(nodes, node)
end
return nodes
end
M.create_split = function()
if not util.is_blank(M.split) then
M.width = vim.api.nvim_win_get_width(M.split.winid)
M.split:unmount()
end
local split = Split {
relative = "win",
position = "left",
size = M.width,
win_options = {
number = false,
relativenumber = false,
wrap = false,
winhighlight = "Normal:NormalAlt",
},
buf_options = {
bufhidden = "delete",
buftype = "nowrite",
modifiable = false,
swapfile = false,
filetype = "codeql_explorer",
},
}
split:mount()
local map_options = { noremap = true, nowait = true }
split:map("n", "q", function()
split:unmount()
end, { noremap = true })
split:map("n", "<CR>", function()
local node = M.tree:get_node()
if node.type == "label" then
return
end
local target_winid = require("window-picker").pick_window()
vim.api.nvim_set_current_win(target_winid)
local filename = string.format("%s/%s", config.database.sourceLocationPrefix, node.id)
local bufname = string.format("ql:/%s", filename)
if vim.fn.bufnr(bufname) > -1 then
vim.api.nvim_command(string.format("buffer %s", bufname))
else
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_name(bufnr, bufname)
filename = string.sub(filename, 2)
util.open_from_archive(bufnr, filename, { target_winid = target_winid })
end
end, map_options)
split:map("n", "o", function()
local node = M.tree:get_node()
if node.type == "dir" then
if node:is_expanded() then
if node:collapse() then
M.tree:render()
end
else
if node:expand() then
M.tree:render()
end
end
else
-- make `o` close file's parent
if node.type == "file" then
local parent = M.tree:get_node(node:get_parent_id())
if parent:collapse() then
M.tree:render()
end
end
end
end, map_options)
M.split = split
end
M.draw = function()
local db = config.database
if not db then
util.err_message "Missing database. Use `QL db set` command"
return
else
local files = util.list_from_archive(db.sourceArchiveZip)
local db_name = vim.split(db.path, "/")[#vim.split(db.path, "/") - 1]
local root = Tree:new("root", "root", "dir", {
Tree:new("::header1::", { { "🛢 ", "SpecialKey" }, { db_name } }, "label"),
Tree:new("::header2::", { { "" } }, "label"),
})
for _, file in ipairs(files) do
local segments = vim.fn.split(file, "/")
local current = root
for i, segment in ipairs(segments) do
local sublist = { unpack(segments, 1, i) }
local id = table.concat(sublist, "/")
local type = #segments == i and "file" or "dir"
local node = current(id, segment, type)
current = node
end
end
local flatten_root = root:flatten_directories()
local nui_nodes = M.create_nodes(flatten_root.children)
M.create_split()
M.create_tree()
M.tree:set_nodes(nui_nodes)
M.tree:render()
end
end
return M