Skip to content

Commit ac9499a

Browse files
authored
Merge pull request #8 from mc-cc-scripts/issue-4/autocomplete
add autocomplete
2 parents 756d6cc + c2a63ae commit ac9499a

File tree

2 files changed

+220
-4
lines changed

2 files changed

+220
-4
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ Shows all installed scripts.
3737
Shows all available configurations.
3838
- `<name>`: Shows the value of a specific configuration.
3939
- `<name> <value>`: Updates the value of a specific configuration.
40+
## refresh
41+
Downloads the names of all programs and libraries of the official repository.
42+
Refreshes autocomplete.
4043
## help
4144
Shows all available commands and their description.
4245
- `<name>`: Shows the description of a command by name.

scm.lua

Lines changed: 217 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ scm.config = {
1212
["programSuffix"] = "-prog",
1313
["librarySuffix"] = "-lib",
1414
["infoFile"] = "files.txt", -- provides the structure of a git repo (paths to all files)
15+
["apiGithubGetRepos"] = "https://api.github.com/orgs/mc-cc-scripts/repos?type=all&per_page=100&page=1",
1516
-- Local Settings
1617
["installScript"] = "1kKZ8zTS",
1718
["rootDirectory"] = "",
@@ -24,7 +25,10 @@ scm.config = {
2425
["printPrefix"] = "[scm] ",
2526
["logDate"] = false,
2627
["writeLogFile"] = false,
27-
["logFilePath"] = "logs/scm-log.txt"
28+
["logFilePath"] = "logs/scm-log.txt",
29+
["repoScriptsFile"] = "scm-repo-scripts.txt", -- will be saved in configDirectory as well
30+
["allowCLIPrefix"] = true,
31+
["cliPrefix"] = false
2832
}
2933
----------------
3034

@@ -130,6 +134,16 @@ $ config <name> <value>
130134
Updates the configuration
131135
]]
132136
},
137+
["refresh"] = {
138+
func = function (args)
139+
scm:refreshAutocomplete()
140+
end,
141+
description = [[
142+
$ refresh
143+
Downloads the names of all programs and libraries of the official repository.
144+
Refreshes autocomplete.
145+
]]
146+
},
133147
["help"] = {
134148
---@param args table
135149
func = function (args)
@@ -152,6 +166,142 @@ $ help <name>
152166
}
153167
}
154168

169+
function scm:refreshRepoScripts ()
170+
self:log("Downloading program and library names from GitHub...")
171+
local repoScripts = {}
172+
173+
local programs = {}
174+
local libraries = {}
175+
176+
local request = http.get(self.config["apiGithubGetRepos"])
177+
if request then
178+
local response = request.readAll()
179+
request.close()
180+
181+
local responseTable = textutils.unserializeJSON(response)
182+
183+
local programSuffix = self.config["programSuffix"]
184+
local librarySuffix = self.config["librarySuffix"]
185+
186+
for i = 1, #responseTable, 1 do
187+
local scriptName = responseTable[i]["name"]
188+
if string.sub(scriptName, -string.len(programSuffix)) == programSuffix then
189+
programs[
190+
string.sub(scriptName, 0, string.len(scriptName)-string.len(programSuffix))
191+
] = {}
192+
elseif string.sub(scriptName, -string.len(librarySuffix)) == librarySuffix then
193+
libraries[
194+
string.sub(scriptName, 0, string.len(scriptName)-string.len(librarySuffix))
195+
] = {}
196+
end
197+
end
198+
scm:log("Done")
199+
else
200+
scm:log("Download failed")
201+
end
202+
203+
self.commands["add"]["args"] = programs
204+
self.commands["require"]["args"] = libraries
205+
206+
repoScripts["libraries"] = libraries
207+
repoScripts["programs"] = programs
208+
209+
local file = fs.open(self.config["configDirectory"] .. self.config["repoScriptsFile"], "w")
210+
if file then
211+
file.write(textutils.serializeJSON(repoScripts))
212+
file.close()
213+
end
214+
end
215+
216+
function scm:loadRepoScripts ()
217+
local file = fs.open(self.config["configDirectory"] .. self.config["repoScriptsFile"], "r")
218+
219+
if not file then
220+
self:refreshRepoScripts()
221+
else
222+
local repoScripts = textutils.unserializeJSON(file.readAll()) or nil
223+
if repoScripts then
224+
self.commands["add"]["args"] = repoScripts["programs"]
225+
self.commands["require"]["args"] = repoScripts["libraries"]
226+
end
227+
228+
file.close()
229+
end
230+
end
231+
232+
function scm:prepareAutocomplete ()
233+
-- prepare update and remove
234+
scm:loadScripts()
235+
local installedScripts = {}
236+
for i = 1, #self.scripts, 1 do
237+
installedScripts[self.scripts[i].name] = {}
238+
end
239+
installedScripts["all"] = {}
240+
241+
self.commands["update"]["args"] = installedScripts
242+
self.commands["remove"]["args"] = installedScripts
243+
244+
-- prepare add and require
245+
self:loadRepoScripts()
246+
247+
-- prepare config
248+
local availableConfigs = {}
249+
250+
for k, _ in pairs(self.config) do
251+
availableConfigs[k] = {}
252+
end
253+
254+
self.commands["config"]["args"] = availableConfigs
255+
256+
-- prepare help
257+
local availableCommands = {}
258+
259+
for k, _ in pairs(self.commands) do
260+
availableCommands[k] = {}
261+
end
262+
263+
self.commands["help"]["args"] = availableCommands
264+
end
265+
266+
---@param shell table
267+
---@param index integer
268+
---@param argument string
269+
---@param previous table
270+
---@return table | nil
271+
local function completionFunction (shell, index, argument, previous)
272+
local commands = {}
273+
for k, _ in pairs(scm.commands) do
274+
commands[k] = scm.commands[k]["args"] or {}
275+
end
276+
277+
local currArg = commands
278+
for i = 2, #previous do
279+
if currArg[previous[i]] then
280+
currArg = currArg[previous[i]]
281+
else
282+
return nil
283+
end
284+
end
285+
286+
local results = {}
287+
for word, _ in pairs(currArg) do
288+
if word:sub(1, #argument) == argument then
289+
results[#results+1] = word:sub(#argument + 1)
290+
end
291+
end
292+
return results;
293+
end
294+
295+
local function updateAutocomplete ()
296+
shell.setCompletionFunction("scm", completionFunction)
297+
end
298+
299+
function scm:refreshAutocomplete ()
300+
scm:refreshRepoScripts()
301+
scm:prepareAutocomplete()
302+
updateAutocomplete()
303+
end
304+
155305
---@param message string
156306
function scm:log (message)
157307
local datetime = ""
@@ -392,21 +542,30 @@ function scm:addScript (sourceObject, success)
392542
if self.scripts[i].source[sourceObject.sourceName] then
393543
self.scripts[i].source[sourceObject.sourceName] = sourceObject.source[sourceObject.sourceName]
394544
self:saveScripts()
395-
545+
396546
return true
397547
end
398548
end
399549
end
400550

401551
if not scriptExists then
402552
scm:log("Script added: " .. sourceObject.name)
403-
table.insert(self.scripts, sourceObject)
553+
table.insert(self.scripts, sourceObject)
404554
else
405555
scm:log("Script already exists.")
556+
return false
406557
end
407-
558+
408559
self:saveScripts()
409560

561+
-- update for autocomplete
562+
self.commands["update"]["args"] = self.commands["update"]["args"] or {}
563+
self.commands["remove"]["args"] = self.commands["remove"]["args"] or {}
564+
self.commands["update"]["args"][sourceObject.name] = {}
565+
self.commands["remove"]["args"][sourceObject.name] = {}
566+
self:prepareAutocomplete()
567+
updateAutocomplete()
568+
410569
return true
411570
end
412571

@@ -454,6 +613,7 @@ function scm:removeScript (name, keepScriptConfig)
454613
self:saveScripts()
455614
end
456615

616+
-- delete file
457617
if scriptType and fs.exists(self.config[scriptType .. "Directory"] .. name .. ".lua") then
458618
fs.delete(self.config[scriptType .. "Directory"] .. name .. self.config[scriptType .. "Suffix"])
459619
if scriptType == "library" then
@@ -464,6 +624,10 @@ function scm:removeScript (name, keepScriptConfig)
464624
if scriptType == "program" then
465625
fs.delete(name)
466626
end
627+
628+
-- update autocomplete
629+
self:prepareAutocomplete()
630+
updateAutocomplete()
467631
end
468632

469633
function scm:removeAllScripts ()
@@ -689,10 +853,59 @@ function scm:init ()
689853
self:loadScripts()
690854
end
691855

856+
---@param resetPosition boolean | nil
857+
function scm:cli (resetPosition, args)
858+
if resetPosition ~= nil and resetPosition == true then
859+
term.setCursorPos(1, 7)
860+
end
861+
862+
-- enable autocomplete
863+
self:prepareAutocomplete()
864+
updateAutocomplete()
865+
866+
-- enable newline starting with `scm `
867+
if self.config["allowCLIPrefix"] then
868+
self.config["cliPrefix"] = true
869+
self:saveConfig()
870+
end
871+
872+
-- some interface
873+
local _, cursorY = term.getCursorPos()
874+
if cursorY < 7 then cursorY = 7 end
875+
term.setCursorPos(1, cursorY)
876+
term.blit(" ","ffffffffffffffffffffffffffffffff","44444444444444444444444444444444")
877+
term.setCursorPos(1, cursorY)
878+
term.scroll(1)
879+
term.blit(" SCM - Script Manager ","ffffffffffffffffffffffffffffffff","44444444444444444444444444444444")
880+
term.setCursorPos(1, cursorY)
881+
term.scroll(1)
882+
term.blit(" Autocomplete enabled. ","77777777777777777777777777777777","44444444444444444444444444444444")
883+
term.setCursorPos(1, cursorY)
884+
term.scroll(1)
885+
term.blit(" Type `scm help` to learn more. ","77777777ffffffff7777777777777777","44444444444444444444444444444444")
886+
term.setCursorPos(1, cursorY)
887+
term.scroll(1)
888+
term.blit(" ","ffffffffffffffffffffffffffffffff","44444444444444444444444444444444")
889+
term.setCursorPos(1, cursorY)
890+
term.scroll(2)
891+
892+
if self.config["cliPrefix"] then
893+
shell.run(read(nil, nil, shell.complete, "scm "))
894+
end
895+
end
896+
692897
---@param args table
693898
function scm:handleArguments (args)
899+
if #args == 0 then
900+
self:cli(false, args)
901+
return
902+
end
903+
694904
if args[1] and self.commands[args[1]] then
695905
self.commands[args[1]]["func"](args)
906+
if self.config["cliPrefix"] then
907+
shell.run(read(nil, nil, shell.complete, "scm "))
908+
end
696909
end
697910
end
698911

0 commit comments

Comments
 (0)