· 2 years ago · Feb 15, 2023, 01:09 PM
1--===GIT API===
2--=============
3--Developed by LNETeam from LNET Technologies
4--Please remove the 'a' from the end of the file before putting it into your API folder
5
6--Usage: git.get(author,repository,branch,path,saveName), git.view(author,repository,branch,path)
7
8
9local function edit(file)
10-- Error checking
11local sPath = 'temp'
12
13local x,y = 1,1
14local w,h = term.getSize()
15local scrollX, scrollY = 0,0
16
17local tLines = {}
18local bRunning = true
19
20-- Colours
21local highlightColour, keywordColour, commentColour, textColour, bgColour
22if term.isColour() then
23 bgColour = colours.black
24 textColour = colours.white
25 highlightColour = colours.yellow
26 keywordColour = colours.yellow
27 commentColour = colours.lime
28 stringColour = colours.red
29else
30 bgColour = colours.black
31 textColour = colours.white
32 highlightColour = colours.white
33 keywordColour = colours.white
34 commentColour = colours.white
35 stringColour = colours.white
36end
37
38-- Menus
39local bMenu = false
40local nMenuItem = 1
41local tMenuItems = {"Exit", "Print"}
42local sStatus = "Press Ctrl to access menu"
43
44local function load(_sPath)
45 tLines = {}
46 if fs.exists( _sPath ) then
47 local file = io.open( _sPath, "r" )
48 local sLine = file:read()
49 while sLine do
50 table.insert( tLines, sLine )
51 sLine = file:read()
52 end
53 file:close()
54 end
55
56 if #tLines == 0 then
57 table.insert( tLines, "" )
58 end
59end
60
61local function save( _sPath )
62 -- Create intervening folder
63 local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )
64 if not fs.exists( sDir ) then
65 fs.makeDir( sDir )
66 end
67
68 -- Save
69 local file = nil
70 local function innerSave()
71 file = fs.open( _sPath, "w" )
72 if file then
73 for n, sLine in ipairs( tLines ) do
74 file.write( sLine .. "\n" )
75 end
76 else
77 error( "Failed to open ".._sPath )
78 end
79 end
80
81 local ok = pcall( innerSave )
82 if file then
83 file.close()
84 end
85 return ok
86end
87
88local tKeywords = {
89 ["and"] = true,
90 ["break"] = true,
91 ["do"] = true,
92 ["else"] = true,
93 ["elseif"] = true,
94 ["end"] = true,
95 ["false"] = true,
96 ["for"] = true,
97 ["function"] = true,
98 ["if"] = true,
99 ["in"] = true,
100 ["local"] = true,
101 ["nil"] = true,
102 ["not"] = true,
103 ["or"] = true,
104 ["repeat"] = true,
105 ["return"] = true,
106 ["then"] = true,
107 ["true"] = true,
108 ["until"]= true,
109 ["while"] = true,
110}
111
112local function tryWrite( sLine, regex, colour )
113 local match = string.match( sLine, regex )
114 if match then
115 if type(colour) == "number" then
116 term.setTextColour( colour )
117 else
118 term.setTextColour( colour(match) )
119 end
120 term.write( match )
121 term.setTextColour( textColour )
122 return string.sub( sLine, string.len(match) + 1 )
123 end
124 return nil
125end
126
127local function writeHighlighted( sLine )
128 while string.len(sLine) > 0 do
129 sLine =
130 tryWrite( sLine, "^%-%-%[%[.-%]%]", commentColour ) or
131 tryWrite( sLine, "^%-%-.*", commentColour ) or
132 tryWrite( sLine, "^\".-[^\\]\"", stringColour ) or
133 tryWrite( sLine, "^\'.-[^\\]\'", stringColour ) or
134 tryWrite( sLine, "^%[%[.-%]%]", stringColour ) or
135 tryWrite( sLine, "^[%w_]+", function( match )
136 if tKeywords[ match ] then
137 return keywordColour
138 end
139 return textColour
140 end ) or
141 tryWrite( sLine, "^[^%w_]", textColour )
142 end
143end
144
145local function redrawText()
146 for y=1,h-1 do
147 term.setCursorPos( 1 - scrollX, y )
148 term.clearLine()
149
150 local sLine = tLines[ y + scrollY ]
151 if sLine ~= nil then
152 writeHighlighted( sLine )
153 end
154 end
155 term.setCursorPos( x - scrollX, y - scrollY )
156end
157
158local function redrawLine(_nY)
159 local sLine = tLines[_nY]
160 term.setCursorPos( 1 - scrollX, _nY - scrollY )
161 term.clearLine()
162 writeHighlighted( sLine )
163 term.setCursorPos( x - scrollX, _nY - scrollY )
164end
165
166local function setLeftStatus()
167end
168
169local function redrawMenu()
170 term.setCursorPos( 1, h )
171 term.clearLine()
172
173 local sLeft, sRight
174 local nLeftColour, nLeftHighlight1, nLeftHighlight2
175 if bMenu then
176 local sMenu = ""
177 for n,sItem in ipairs( tMenuItems ) do
178 if n == nMenuItem then
179 nLeftHighlight1 = sMenu:len() + 1
180 nLeftHighlight2 = sMenu:len() + sItem:len() + 2
181 end
182 sMenu = sMenu.." "..sItem.." "
183 end
184 sLeft = sMenu
185 nLeftColour = textColour
186 else
187 sLeft = sStatus
188 nLeftColour = highlightColour
189 end
190
191 -- Left goes last so that it can overwrite the line numbers.
192 sRight = "Ln "..y
193 term.setTextColour( highlightColour )
194 term.setCursorPos( w-sRight:len() + 1, h )
195 term.write(sRight)
196
197 sRight = tostring(y)
198 term.setTextColour( textColour )
199 term.setCursorPos( w-sRight:len() + 1, h )
200 term.write(sRight)
201
202 if sLeft then
203 term.setCursorPos( 1, h )
204 term.setTextColour( nLeftColour )
205 term.write(sLeft)
206 if nLeftHighlight1 then
207 term.setTextColour( highlightColour )
208 term.setCursorPos( nLeftHighlight1, h )
209 term.write( "[" )
210 term.setCursorPos( nLeftHighlight2, h )
211 term.write( "]" )
212 end
213 term.setTextColour( textColour )
214 end
215
216 -- Cursor highlights selection
217 term.setCursorPos( x - scrollX, y - scrollY )
218end
219
220local tMenuFuncs = {
221 Save=function()
222 if bReadOnly then
223 sStatus = "Access denied"
224 else
225 local ok, err = save( sPath )
226 if ok then
227 sStatus="Saved to "..sPath
228 else
229 sStatus="Error saving to "..sPath
230 end
231 end
232 redrawMenu()
233 end,
234 Print=function()
235 local sPrinterSide = nil
236 for n,sSide in ipairs(rs.getSides()) do
237 if peripheral.isPresent(sSide) and peripheral.getType(sSide) == "printer" then
238 sPrinterSide = sSide
239 break
240 end
241 end
242
243 if not sPrinterSide then
244 sStatus = "No printer attached"
245 return
246 end
247
248 local nPage = 0
249 local sName = fs.getName( sPath )
250 local printer = peripheral.wrap(sPrinterSide)
251 if printer.getInkLevel() < 1 then
252 sStatus = "Printer out of ink"
253 return
254 elseif printer.getPaperLevel() < 1 then
255 sStatus = "Printer out of paper"
256 return
257 end
258
259 local terminal = {
260 getCursorPos = printer.getCursorPos,
261 setCursorPos = printer.setCursorPos,
262 getSize = printer.getPageSize,
263 write = printer.write,
264 }
265 terminal.scroll = function()
266 if nPage == 1 then
267 printer.setPageTitle( sName.." (page "..nPage..")" )
268 end
269
270 while not printer.newPage() do
271 if printer.getInkLevel() < 1 then
272 sStatus = "Printer out of ink, please refill"
273 elseif printer.getPaperLevel() < 1 then
274 sStatus = "Printer out of paper, please refill"
275 else
276 sStatus = "Printer output tray full, please empty"
277 end
278
279 term.restore()
280 redrawMenu()
281 term.redirect( terminal )
282
283 local timer = os.startTimer(0.5)
284 sleep(0.5)
285 end
286
287 nPage = nPage + 1
288 if nPage == 1 then
289 printer.setPageTitle( sName )
290 else
291 printer.setPageTitle( sName.." (page "..nPage..")" )
292 end
293 end
294
295 bMenu = false
296 term.redirect( terminal )
297 local ok, error = pcall( function()
298 term.scroll()
299 for n, sLine in ipairs( tLines ) do
300 print( sLine )
301 end
302 end )
303 term.restore()
304 if not ok then
305 print( error )
306 end
307
308 while not printer.endPage() do
309 sStatus = "Printer output tray full, please empty"
310 redrawMenu()
311 sleep( 0.5 )
312 end
313 bMenu = true
314
315 if nPage > 1 then
316 sStatus = "Printed "..nPage.." Pages"
317 else
318 sStatus = "Printed 1 Page"
319 end
320 redrawMenu()
321 end,
322 Exit=function()
323 bRunning = false
324 end
325}
326
327local function doMenuItem( _n )
328 tMenuFuncs[tMenuItems[_n]]()
329 if bMenu then
330 bMenu = false
331 term.setCursorBlink( true )
332 end
333 redrawMenu()
334end
335
336local function setCursor( x, y )
337 local screenX = x - scrollX
338 local screenY = y - scrollY
339
340 local bRedraw = false
341 if screenX < 1 then
342 scrollX = x - 1
343 screenX = 1
344 bRedraw = true
345 elseif screenX > w then
346 scrollX = x - w
347 screenX = w
348 bRedraw = true
349 end
350
351 if screenY < 1 then
352 scrollY = y - 1
353 screenY = 1
354 bRedraw = true
355 elseif screenY > h-1 then
356 scrollY = y - (h-1)
357 screenY = h-1
358 bRedraw = true
359 end
360
361 if bRedraw then
362 redrawText()
363 end
364 term.setCursorPos( screenX, screenY )
365
366 -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.
367 redrawMenu()
368end
369
370-- Actual program functionality begins
371load(sPath)
372
373term.setBackgroundColour( bgColour )
374term.clear()
375term.setCursorPos(x,y)
376term.setCursorBlink( true )
377
378redrawText()
379redrawMenu()
380
381-- Handle input
382while bRunning do
383 local sEvent, param, param2, param3 = os.pullEvent()
384 if sEvent == "key" then
385 if param == keys.up then
386 -- Up
387 if not bMenu then
388 if y > 1 then
389 -- Move cursor up
390 y = y - 1
391 x = math.min( x, string.len( tLines[y] ) + 1 )
392 setCursor( x, y )
393 end
394 end
395 elseif param == keys.down then
396 -- Down
397 if not bMenu then
398 -- Move cursor down
399 if y < #tLines then
400 y = y + 1
401 x = math.min( x, string.len( tLines[y] ) + 1 )
402 setCursor( x, y )
403 end
404 end
405 elseif param == keys.tab then
406 -- Tab
407 if not bMenu then
408 local sLine = tLines[y]
409
410 -- Indent line
411 -- IN CASE OF INSERT TAB IN PLACE:
412 -- tLines[y] = string.sub(sLine,1,x-1) .. " " .. string.sub(sLine,x)
413 tLines[y]=" "..tLines[y]
414 x = x + 2
415 setCursor( x, y )
416 redrawLine(y)
417 end
418 elseif param == keys.pageUp then
419 -- Page Up
420 if not bMenu then
421 -- Move up a page
422 local sx,sy=term.getSize()
423 y=y-sy-1
424 if y<1 then y=1 end
425 x = math.min( x, string.len( tLines[y] ) + 1 )
426 setCursor( x, y )
427 end
428 elseif param == keys.pageDown then
429 -- Page Down
430 if not bMenu then
431 -- Move down a page
432 local sx,sy=term.getSize()
433 if y<#tLines-sy-1 then
434 y = y+sy-1
435 else
436 y = #tLines
437 end
438 x = math.min( x, string.len( tLines[y] ) + 1 )
439 setCursor( x, y )
440 end
441 elseif param == keys.home then
442 -- Home
443 if not bMenu then
444 -- Move cursor to the beginning
445 x=1
446 setCursor(x,y)
447 end
448 elseif param == keys["end"] then
449 -- End
450 if not bMenu then
451 -- Move cursor to the end
452 x = string.len( tLines[y] ) + 1
453 setCursor(x,y)
454 end
455 elseif param == keys.left then
456 -- Left
457 if not bMenu then
458 if x > 1 then
459 -- Move cursor left
460 x = x - 1
461 elseif x==1 and y>1 then
462 x = string.len( tLines[y-1] ) + 1
463 y = y - 1
464 end
465 setCursor( x, y )
466 else
467 -- Move menu left
468 nMenuItem = nMenuItem - 1
469 if nMenuItem < 1 then
470 nMenuItem = #tMenuItems
471 end
472 redrawMenu()
473 end
474 elseif param == keys.right then
475 -- Right
476 if not bMenu then
477 if x < string.len( tLines[y] ) + 1 then
478 -- Move cursor right
479 x = x + 1
480 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then
481 x = 1
482 y = y + 1
483 end
484 setCursor( x, y )
485 else
486 -- Move menu right
487 nMenuItem = nMenuItem + 1
488 if nMenuItem > #tMenuItems then
489 nMenuItem = 1
490 end
491 redrawMenu()
492 end
493 elseif param == keys.delete then
494 -- Delete
495 if not bMenu then
496 if x < string.len( tLines[y] ) + 1 then
497 local sLine = tLines[y]
498 tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
499 redrawLine(y)
500 elseif y<#tLines then
501 tLines[y] = tLines[y] .. tLines[y+1]
502 table.remove( tLines, y+1 )
503 redrawText()
504 redrawMenu()
505 end
506 end
507 elseif param == keys.backspace then
508 -- Backspace
509 if not bMenu then
510 if x > 1 then
511 -- Remove character
512 local sLine = tLines[y]
513 tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
514 redrawLine(y)
515
516 x = x - 1
517 setCursor( x, y )
518 elseif y > 1 then
519 -- Remove newline
520 local sPrevLen = string.len( tLines[y-1] )
521 tLines[y-1] = tLines[y-1] .. tLines[y]
522 table.remove( tLines, y )
523 redrawText()
524
525 x = sPrevLen + 1
526 y = y - 1
527 setCursor( x, y )
528 end
529 end
530 elseif param == keys.enter then
531 -- Enter
532 if not bMenu then
533 -- Newline
534 local sLine = tLines[y]
535 local _,spaces=string.find(sLine,"^[ ]+")
536 if not spaces then
537 spaces=0
538 end
539 tLines[y] = string.sub(sLine,1,x-1)
540 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )
541 redrawText()
542
543 x = spaces+1
544 y = y + 1
545 setCursor( x, y )
546 else
547 -- Menu selection
548 doMenuItem( nMenuItem )
549 end
550 elseif param == keys.leftCtrl or param == keys.rightCtrl then
551 -- Menu toggle
552 bMenu = not bMenu
553 if bMenu then
554 term.setCursorBlink( false )
555 nMenuItem = 1
556 else
557 term.setCursorBlink( true )
558 end
559 redrawMenu()
560 end
561
562 elseif sEvent == "char" then
563 if not bMenu then
564 -- Input text
565 local sLine = tLines[y]
566 tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
567 redrawLine(y)
568
569 x = x + string.len( param )
570 setCursor( x, y )
571 else
572 -- Select menu items
573 for n,sMenuItem in ipairs( tMenuItems ) do
574 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
575 doMenuItem( n )
576 break
577 end
578 end
579 end
580
581 elseif sEvent == "mouse_click" then
582 if not bMenu then
583 if param == 1 then
584 -- Left click
585 local cx,cy = param2, param3
586 if cy < h then
587 y = math.min( math.max( scrollY + cy, 1 ), #tLines )
588 x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )
589 setCursor( x, y )
590 end
591 end
592 end
593
594 elseif sEvent == "mouse_scroll" then
595 if not bMenu then
596 if param == -1 then
597 -- Scroll up
598 if scrollY > 0 then
599 -- Move cursor up
600 scrollY = scrollY - 1
601 redrawText()
602 end
603
604 elseif param == 1 then
605 -- Scroll down
606 local nMaxScroll = #tLines - (h-1)
607 if scrollY < nMaxScroll then
608 -- Move cursor down
609 scrollY = scrollY + 1
610 redrawText()
611 end
612
613 end
614 end
615 end
616end
617
618-- Cleanup
619term.clear()
620term.setCursorBlink( false )
621term.setCursorPos(1,1)
622end
623
624function requestObject(url,sN,mode,sP)
625 if not url then error('Incorrect statement!') end
626 if not sN and mode == 'get' then error('Check mode!') end
627 if mode == 'get' then
628 http.request(url)
629 local requesting = true
630 while requesting do
631 local event, url, sourceText = os.pullEvent()
632 if event == "http_success" then
633 if fs.exists(sP) then
634 fs.makeDir(sP)
635 end
636 local respondedText = sourceText.readAll()
637 temp = io.open(sP.."/"..sN,'w')
638 temp:write(respondedText)
639 temp:close()
640 requesting = false
641 return true
642 elseif event == "http_failure" then
643 requesting = false
644 return false
645 end
646 end
647 elseif mode == 'view' then
648 write('Fetching: '..url..'... ')
649 http.request(url)
650 local requesting = true
651 while requesting do
652 local event, url, sourceText = os.pullEvent()
653 if event == "http_success" then
654 local respondedText = sourceText.readAll()
655 temp = io.open('temp','w')
656 temp:write(respondedText)
657 temp:close()
658 edit('temp')
659 fs.delete('temp')
660 requesting = false
661 return true
662 elseif event == "http_failure" then
663 requesting = false
664 return false
665 end
666 end
667 end
668end
669
670function compileURL(auth,pro,bran,pat)
671 baseURL = 'https://raw.github.com/'..auth..'/'..pro..'/'..bran..'/'..pat
672 return baseURL
673end
674
675function get(auth,reps,bran,paths,sN,save_path)
676 if not auth or not reps or not bran or not paths or not sN then error('Attempt to compile nonexistent terms!') end
677 statusCode = requestObject(compileURL(auth,reps,bran,paths),sN,'get',save_path)
678 return statusCode
679end
680
681function view(auth,reps,bran,paths)
682 if not auth or not reps or not bran or not paths then error('Attempt to compile nonexistent terms!') end
683 statusCode = requestObject(compileURL(auth,reps,bran,paths),nil,'view')
684 return statusCode
685end
686