@@ -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
156306function 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
411570end
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 ()
467631end
468632
469633function scm :removeAllScripts ()
@@ -689,10 +853,59 @@ function scm:init ()
689853 self :loadScripts ()
690854end
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
693898function 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
697910end
698911
0 commit comments