-
-
Notifications
You must be signed in to change notification settings - Fork 40
/
Copy pathutils-bau.lua
333 lines (279 loc) · 9.25 KB
/
utils-bau.lua
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
--- ### Utils-bau for build automation utilities
--- Frontend compatilibity:
--- The parsers in this file return data in a format Telescope can undestand.
--- If you want to support other frontend, write an adapter function
--- to convert the data format returned by the parsers as needed.
local M = {}
local utils = require("compiler.utils")
-- PARSERS
-- Private functions to parse bau files.
-- ============================================================================
---Given a Makefile file, parse all the targets,
---and return them as a table.
---@param path string Path to the Makefile.
---@return table options A table like:
--- { { text: "Make all", value="all", bau = "make"}, { text: "Make hello", value="hello", bau = "make"} ...}
local function get_makefile_opts(path)
local options = {}
-- Open the Makefile for reading
local file = io.open(path, "r")
if file then
local in_target = false
-- Iterate through each line in the Makefile
for line in file:lines() do
-- Check for lines starting with a target rule (e.g., "target: dependencies")
local target = line:match "^(.-):"
if target then
in_target = true
-- Exclude the ":" and add the option to the list with text and value fields
table.insert(
options,
{ text = "Make " .. target, value = target, bau = "make" }
)
elseif in_target then
-- If we're inside a target block, stop adding options
in_target = false
end
end
-- Close the Makefile
file:close()
end
return options
end
---Given a CMakeLists.txt file, parse all the targets,
---and return them as a table.
---@param path string Path to the CMakeLists.txt file.
---@return table options A table like:
--- { { text: "CMake all", value="all", bau = "cmake"}, { text: "CMake hello", value="hello", bau = "cmake"} ...}
local function get_cmake_opts(path)
local options = {}
local file = io.open(path, "r")
if file then
local content = file:read("*all")
file:close()
-- Parse add_executable entries
for target in content:gmatch("add_executable%s*%(%s*([%w_]+)") do
table.insert(
options,
{ text = "CMake " .. target, value = target, bau = "cmake" }
)
end
-- Parse add_custom_target entries
for target in content:gmatch("add_custom_target%s*%(%s*([%w_]+)") do
table.insert(
options,
{ text = "CMake " .. target, value = target, bau = "cmake" }
)
end
end
return options
end
--- Given a Mesonfile, parse all the options,
--- and return them as a table.
--- @param path string Path to the meson.build
--- @return table options A table like:
--- { { text = "Meson hello", value = "hello", description = "Print Hello, World!", bau = "meson" }, ...}
local function get_meson_opts(path)
local options = {}
local file = io.open(path, "r")
if file then
local content = file:read("*all")
file:close()
-- Parse executable entries
for target in content:gmatch("executable%s*%(.-['\"]([%w_]+)['\"]") do
table.insert(
options,
{ text = "Meson " .. target, value = target, bau = "meson" }
)
end
-- Parse custom_target entries
for target in content:gmatch("custom_target%s*%(%s*'([^']+)'") do
table.insert(
options,
{ text = "Meson " .. target, value = target, bau = "meson" }
)
end
end
return options
end
---Given a build.gradle.kts file, parse all the tasks,
---and return them as a table.
---
--- If the file is not found. It will fallback to build.gradle.
---@param path string Path to the build.gradle.kts file.
---@return table options A table like:
--- { { text: "Gradle all", value="all", bau = "gradle"}, { text: "Gradle hello", value="hello", bau = "gradle"} ...}
local function get_gradle_opts(path)
local options = {}
local file = io.open(path, "r")
if not file then
-- If the file with ".kts" extension doesn't exist, try without the extension
local alternative_path = string.gsub(path, "%.kts$", "")
file = io.open(alternative_path, "r")
end
if file then
local in_task = false
local task_name = ""
for line in file:lines() do
-- Parse Kotlin DSL file
local task_match = line:match('tasks%.register%s*%(?%s*"(.-)"%s*%)?%s*{')
if task_match then
in_task = true
task_name = task_match
table.insert(
options,
{ text = "Gradle " .. task_name, value = task_name, bau = "gradle" }
)
elseif in_task then
local task_end = line:match("}")
if task_end then
in_task = false
task_name = ""
end
else
-- Parse Groovy DSL file
task_match = line:match("%s*task%s+([%w_]+)%s*%{")
if task_match then
in_task = true
task_name = task_match
table.insert(
options,
{ text = "Gradle " .. task_name, value = task_name, bau = "gradle" }
)
elseif in_task then
local task_end = line:match("}")
if task_end then
in_task = false
task_name = ""
end
end
end
end
file:close()
end
return options
end
--- Given a package.json file, parse all the targets,
--- and return them as a table.
---
--- let g:NODEJS_PACKAGE_MANAGER can be defined to 'yarn' or 'npm' (default)
---@param path string Path to the package.json file.
---@return table options A table like:
--- { { text: "npm install", value="install", bau = "npm"}, { text: "npm start", value="start", bau = "npm"} ...}
local function get_nodejs_opts(path)
local options = {}
local file = io.open(path, "r")
if file then
local content = file:read "*all"
file:close()
-- parse package.json
local package_json = {}
local success, result = pcall(
function() package_json = vim.fn.json_decode(content) end
)
if not success then
-- Handle the error, such as invalid JSON format
print("Error decoding JSON: " .. result)
return options
end
-- Global: NODEJS_PACKAGE_MANAGER
local success, package_manager =
pcall(vim.api.nvim_get_var, "NODEJS_PACKAGE_MANAGER")
if not success or package_manager == "" then package_manager = "npm" end
-- Add parsed options to table "options"
local scripts = package_json.scripts
if scripts then
-- Hardcode install/uninstall scripts
table.insert(
options,
{
text = package_manager:upper() .. " install",
value = package_manager .. " install",
bau = "nodejs",
}
)
if package_manager == "npm" then
table.insert(
options,
{
text = package_manager:upper() .. " uninstall *",
value = package_manager .. " uninstall *",
bau = "nodejs",
}
)
end
-- Afterwards, add the scripts from package.json
for script, _ in pairs(scripts) do
table.insert(options, {
text = package_manager:upper() .. " " .. script,
value = package_manager .. " run " .. script,
bau = "nodejs",
})
end
end
end
return options
end
local function get_dioxus_opts(path)
local options = {}
local file = io.open(path, "r")
-- Just adds an option to build with dioxus cli
if file then
table.insert(options, { text = "Build Dioxus", value = "placeholder", bau = "dioxus" })
end
return options
end
-- FRONTEND
-- Public functions to call from the frontend.
-- ============================================================================
---Function that call all bau function and combine the result in a table.
---@return table options A table that contain
--- the options of all bau available in the current working directory.
--- Empty table {} if none is found.
function M.get_bau_opts()
local working_dir = vim.fn.getcwd()
local options = {}
-- make
vim.list_extend(options, get_makefile_opts(
working_dir .. utils.os_path("/Makefile")
))
-- cmake
vim.list_extend(options, get_cmake_opts(
working_dir .. utils.os_path("/CMakeLists.txt")
))
-- meson
vim.list_extend(options, get_meson_opts(
working_dir .. utils.os_path("/meson.build")
))
-- gradle
vim.list_extend(options, get_gradle_opts(
working_dir .. utils.os_path("/build.gradle.kts")
))
-- nodejs
vim.list_extend(options, get_nodejs_opts(
working_dir .. utils.os_path("/package.json")
))
-- dioxus
vim.list_extend(options, get_dioxus_opts(
working_dir .. utils.os_path("/Dioxus.toml")
))
return options
end
---Programatically require a bau backend,
--- responsible for running the action selected by the user in the frontend.
---@return table|nil bau The bau backend,
--- or nil, if ./bau/<bau>.lua doesn't exist.
function M.require_bau(bau)
local local_path = debug.getinfo(1, "S").source:sub(2)
local local_path_dir = local_path:match("(.*[/\\])")
local module_file_path = utils.os_path(local_path_dir .. "bau/" .. bau .. ".lua")
local success, bau = pcall(dofile, module_file_path)
if success then
return bau
else
-- local error = "Build automation utilities \"" .. bau .. "\" not supported by the compiler."
-- vim.notify(error, vim.log.levels.INFO, { title = "Build automation utilities unsupported" })
return nil
end
end
return M