Advertisement
Le_JuiceBOX

[Module] terminal.lua

Mar 29th, 2024 (edited)
789
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.21 KB | None | 0 0
  1. -- Kz2mdMyW
  2. local module = {}
  3. module.__index = module
  4.  
  5. module.mcColorSymbol = '§'
  6. module.replaceSymbol = '&'
  7. module.removeSymbol = 'Â'
  8.  
  9. module.ColorMap = {
  10.     ["0"] = colors.white,
  11.     ["1"] = colors.orange,
  12.     ["2"] = colors.magenta,
  13.     ["3"] = colors.lightBlue,
  14.     ["4"] = colors.yellow,
  15.     ["5"] = colors.lime,
  16.     ["6"] = colors.pink,
  17.     ["7"] = colors.gray,
  18.     ["8"] = colors.lightGray,
  19.     ["9"] = colors.cyan,
  20.     ["a"] = colors.purple,
  21.     ["b"] = colors.blue,
  22.     ["c"] = colors.brown,
  23.     ["d"] = colors.green,
  24.     ["e"] = colors.red,
  25.     ["f"] = colors.black,
  26. }
  27.  
  28. --====================================================================================================
  29. --// Terminal
  30. --====================================================================================================
  31.  
  32. function module:new()
  33.     local self = setmetatable({}, module)
  34.     local tsx,tsy = term.getSize()
  35.     self.output = term
  36.     self.outputLine = 1
  37.     self.canColor = term.isColor()
  38.     self.size = {
  39.         x = tsx,
  40.         y = tsy
  41.     }
  42.     return self
  43. end
  44.  
  45. function module:setOutput(t)
  46.     self.output = t or term
  47.     self.canColor = self.output.isColor()
  48.     local tsx,tsy = self.output.getSize()
  49.     self.size = {
  50.         x = tsx,
  51.         y = tsy
  52.     }
  53. end
  54.  
  55. function module:getComputerLabel()
  56.     return string.gsub(os.getComputerLabel() or "Untitled",self.mcColorSymbol.."%w","")
  57. end
  58.  
  59. --====================================================================================================
  60. --// Complex writing
  61. --====================================================================================================
  62.  
  63. function module:displayHeader(table,startLine)
  64.     startLine = startLine or 1
  65.     local line = 0
  66.     for i,text in pairs(table) do
  67.         line = startLine+(i-1)
  68.         term.clearLine(line)
  69.         term.setCursorPos(1,line)
  70.         print(text)
  71.     end
  72.     term.setCursorPos(1,startLine+(#table))
  73. end
  74.  
  75. function module:display(startLine,...)
  76.     local cx,cy = term.getCursorPos()
  77.     startLine = startLine or cy
  78.     local lines = {...}
  79.     for i = 1, #lines do
  80.         local y = (startLine+i)
  81.         self:writeLine(y,lines[i])
  82.     end
  83.     term.setCursorPos(1,startLine+#lines+1)
  84. end
  85.  
  86. function module:displayFromList(startLine,list)
  87.     local cx,cy = term.getCursorPos()
  88.     startLine = startLine or cy
  89.     for i = 1, #list do
  90.         local y = (startLine+i)
  91.         self:writeLine(y,list[i])
  92.     end
  93.     term.setCursorPos(1,startLine+#list+1)
  94. end
  95.  
  96. function module:displayColumn(startLine,columnWidth,col1,col2)
  97.     local w,h = term.getSize()
  98.     local x,y = term.getCursorPos()
  99.     columnWidth = columnWidth or w/2
  100.     startLine = startLine or y
  101.     for i, text in pairs(col1) do
  102.         self:writeAt(1,startLine+(i-1),text)
  103.     end
  104.     for i, text in pairs(col2) do
  105.         self:writeAt((w/2)-1,startLine+(i-1),text)
  106.     end
  107. end
  108.  
  109. function module:splitIntoColumns(startLine,columnWidth,list)
  110.     local c1 = {}
  111.     local c2 = {}
  112.     for i = 1, #list do
  113.         if i < #list/2 then
  114.             table.insert(c1,list[i])
  115.         else
  116.             table.insert(c2,list[i])
  117.         end
  118.     end
  119.     self:displayColumn(startLine,columnWidth,c1,c2)
  120. end
  121.  
  122. --====================================================================================================
  123. --// Basic text witing
  124. --====================================================================================================
  125.  
  126. function module:setColor(color)
  127.     if self.canColor == false then return; end
  128.     self.output.setTextColor(color)
  129. end
  130. function module:setColorCode(code)
  131.     if self.canColor == false then return; end
  132.     for c,color in pairs(self.ColorMap) do
  133.         if code == c then
  134.             self.output.setTextColor(color)
  135.         end
  136.     end
  137. end
  138.  
  139. function module:colorWrite(str)
  140.     if str == nil then printError("String is nil"); return end
  141.     local txt = {}
  142.     local builtStr = ""
  143.     local lastSymbolPos = 0
  144.     self:setColor(colors.white)
  145.     for i = 1, #str do
  146.         local charBefore = str:sub(i-1, i-1)
  147.         local char = str:sub(i, i)
  148.         local charAfter = str:sub(i+1, i+1)
  149.         if char == module.replaceSymbol and charBefore ~= "\\" and charAfter ~= " " then
  150.             self.output.write(builtStr)
  151.             builtStr = ""
  152.             lastSymbolPos = i+1
  153.             self:setColorCode(charAfter)
  154.         elseif i ~= lastSymbolPos then
  155.             builtStr = builtStr..char
  156.         end
  157.     end
  158.     self.output.write(builtStr)
  159.     self:setColor(colors.white)
  160. end
  161.  
  162. function module:removeColorCodes(str)
  163.     if str == nil then printError("String is nil"); return end
  164.     local builtStr = ""
  165.     for i = 1, #str do
  166.         local charBefore = str:sub(i-1, i-1)
  167.         local char = str:sub(i, i)
  168.         local charAfter = str:sub(i+1, i+1)
  169.         if charBefore ~= self.replaceSymbol and char ~= self.replaceSymbol  then
  170.             builtStr = builtStr..char
  171.         end
  172.     end
  173.     return builtStr
  174. end
  175.  
  176. function module:writeLine(lineNumber,txt)
  177.     if type(lineNumber) ~= "number" then printError("lineNumber is a string, did you forget to input line number?")return end
  178.     txt = txt or ""
  179.     self.output.setCursorPos(1,lineNumber)
  180.     self.output.clearLine(lineNumber)
  181.     self:colorWrite(txt)
  182.     self.output.setCursorPos(1,lineNumber+1)
  183. end
  184.  
  185. function module:writeAt(x,y,txt)
  186.     if type(x) ~= "number" then printError("p1 must be a number.")return end
  187.     if type(y) ~= "number" then printError("p1 must be a number.")return end
  188.     txt = tostring(txt) or ""
  189.     self.output.setCursorPos(x,y)
  190.     self:colorWrite(txt)
  191.     self.output.setCursorPos(1,y+1)
  192. end
  193.  
  194. function module:write(txt)
  195.     txt = txt or ""
  196.     self:colorWrite(txt)
  197. end
  198.  
  199. function module:print(txt)
  200.     txt = txt or ""
  201.     local _,y = self.output.getCursorPos()
  202.     self.output.clearLine(y)
  203.     self:writeLine(y,txt)
  204.     self.output.setCursorPos(1,y+1)
  205. end
  206.  
  207. function module:setOutputLine(lineNum)
  208.     self.outputLine = lineNum
  209.     term.setCursorPos(1,lineNum)
  210. end
  211.  
  212. function module:reset()
  213.     self.output.clear()
  214.     self.output.setCursorPos(1,1)
  215. end
  216.  
  217. --====================================================================================================
  218. --// Prompts
  219. --====================================================================================================
  220.  
  221. function module:prompt(promtText)
  222.     self:print(tostring(promtText))
  223.     self:write("> ")
  224.     return io.read()
  225. end
  226.  
  227. function module:promptNum(promptText)
  228.     local res = self:prompt(promptText)
  229.     return tonumber(res)
  230. end
  231.  
  232. function module:promptBool(promptText)
  233.     local res = self:promptNum(promptText)
  234.     return (res == 1)
  235. end
  236.  
  237. function module:promptConf(promptText,useOptions)
  238.     useOptions = useOptions or false
  239.     self:print(promptText)
  240.     if useOptions then
  241.         local _, res = self:promptOptions(nil,false,{"&dYes","&eNo"})
  242.         return (res == 1)
  243.     else
  244.         while true do
  245.             local k = self:waitForKey()
  246.             if k == keys.enter then
  247.                 return true
  248.             elseif k == keys.backspace then
  249.                 return false
  250.             end
  251.         end
  252.     end
  253. end
  254.  
  255. function module:promptFilePath(startDir,modifyMode,prompt)
  256.     if startDir == nil then return; end
  257.     if fs.isDir(startDir) == false then return; end
  258.     modifyMode = modifyMode or false
  259.     local lastHead = nil
  260.     local head = startDir
  261.     while true do
  262.         self:reset()
  263.         local file, result = self:promptFile(head,modifyMode,prompt,1)
  264.         if result == self.PromptFileResult.GoUp then
  265.             if head == lastHead or lastHead == nil then
  266.                 self:print("&a\nExiting...")
  267.                 os.sleep(0.1)
  268.                 return nil
  269.             end
  270.             self:print("&a\nMoving up a directory...")
  271.             head = lastHead
  272.             os.sleep(0.1)
  273.         elseif result == self.PromptFileResult.SelectedDirectory then
  274.             if #fs.list(file) > 0 then
  275.                 lastHead = head
  276.                 head = file
  277.             else
  278.                 if modifyMode then
  279.                     self:modifyFile(file)
  280.                 else
  281.                     self:print("&aChosen directory has no files.")
  282.                     self:print("&aPlease select another one.")
  283.                     os.sleep(1)
  284.                 end
  285.             end
  286.         elseif result == self.PromptFileResult.SelectedFile then
  287.             if modifyMode then
  288.                 self:reset()
  289.                 self:modifyFile(file)
  290.             else
  291.                 return file
  292.             end
  293.         end
  294.     end
  295.     self:reset()
  296. end
  297.  
  298. module.PromptFileResult = {
  299.     SelectedDirectory = 1,
  300.     SelectedFile = 2,
  301.     GoUp = 3,
  302.     NoChildren = 4
  303. }
  304.  
  305. function module:promptFile(startDir,allowFileModify,prompt,startLine)
  306.     local _,y = self.output.getCursorPos()
  307.     allowFileModify = allowFileModify or false
  308.     local files = fs.list(startDir)
  309.     -- color the directories
  310.     for i,fName in pairs(files) do
  311.         local fPath = startDir.."/"..fName
  312.         if fs.isDir(fPath) then
  313.             files[i] = "&4"..files[i]
  314.         else
  315.             files[i] = files[i]
  316.         end
  317.     end
  318.    
  319.     local resName,resInd = self:promptOptions(prompt or "Choose a file ~",true,files,startLine)
  320.     if resInd == -1 then
  321.         return nil, self.PromptFileResult.GoUp
  322.     end
  323.     local fn = self:removeColorCodes(files[resInd])
  324.     local path = startDir.."/"..fn
  325.     if fs.isDir(path) then
  326.         return path, self.PromptFileResult.SelectedDirectory
  327.     else
  328.         return path, self.PromptFileResult.SelectedFile
  329.     end
  330. end
  331.  
  332. function module:promptOptions(promptMsg,allowCancel,optionsArray,startLine)
  333.     local x,y = self.output.getCursorPos()
  334.     startLine = startLine or y
  335.     if optionsArray == nil then
  336.         printError("Options array is nil.")
  337.     end
  338.     if #optionsArray < 1 then
  339.         printError("Options array has no items.")
  340.         return
  341.     end
  342.     allowCancel = allowCancel or false
  343.     local selectedIndex = 1
  344.     local selectedText
  345.     repeat
  346.         self.output.setCursorPos(1,startLine)
  347.         if promptMsg then            
  348.             self:print(promptMsg)
  349.             self:print()
  350.         end
  351.         for i,v in pairs(optionsArray) do
  352.             local ind = i
  353.             if selectedIndex == ind then
  354.                 self:print("&3> "..v)
  355.             else
  356.                 self:print(" "..v)
  357.             end
  358.         end
  359.         local key = self:waitForKey()
  360.         if key == 265 then -- up
  361.             selectedIndex = selectedIndex - 1
  362.             if selectedIndex < 1 then
  363.                 selectedIndex = #optionsArray
  364.             end
  365.         elseif key == 264 then -- down
  366.             selectedIndex = selectedIndex + 1
  367.             if selectedIndex > #optionsArray then
  368.                 selectedIndex = 1
  369.             end
  370.         elseif allowCancel and key == 259 then -- backspace (exit)
  371.             return "", -1
  372.         end
  373.     until key == 257 -- enter
  374.     return selectedText, selectedIndex
  375. end
  376.  
  377. --====================================================================================================
  378. --// Wait for keys
  379. --====================================================================================================
  380.  
  381. function module:waitForKey()
  382.     term.setCursorBlink(false)
  383.     while true do
  384.         local event, key, is_held = os.pullEvent("key")
  385.         term.setCursorBlink(true)
  386.         return key, is_held;
  387.     end
  388. end
  389.  
  390. function module:waitForNumberKey(max)
  391.     max = max or 9
  392.     while true do
  393.         local keyCode = self:waitForKey()
  394.         local num = self.getKeyCodeInt(keyCode)
  395.         if num and num <= max then return num; end
  396.     end
  397. end
  398.  
  399. function module:pressAnyKeyToContinue()
  400.     local x,y = term.getCursorPos()
  401.     print("Press any key to continue...")    
  402.     term.setCursorPos(0,0)
  403.     self:waitForKey()
  404.     term.setCursorPos(x,y)
  405. end
  406.  
  407. --====================================================================================================
  408. --// Prompts
  409. --====================================================================================================
  410.  
  411. function module:modifyFile(filePath)
  412.     if filePath == nil then
  413.         self:reset()
  414.         printError("Terminal:modifyFile requires a filepath.")
  415.     end
  416.     repeat
  417.         self:reset()
  418.         local resName, resInd = self:promptOptions(
  419.             "File: '"..filePath.."'\n",
  420.             true,
  421.             {
  422.                 "Cancel",
  423.                 "Execute",
  424.                 "Edit",
  425.                 "Delete",
  426.             }
  427.         )
  428.         if resInd == 2 then -- execute
  429.             shell.run(filePath)
  430.             return
  431.         elseif resInd == 3 then -- edit
  432.             shell.run("edit "..filePath)
  433.         elseif resInd == 4 then -- delete
  434.             self:reset()
  435.             self:print("File: '"..filePath.."'")
  436.             local _, resInd = self:promptOptions("Delete this file?",false,{"&dYes","&eNo"})
  437.             if resInd == 1 then
  438.                 shell.run("delete "..filePath)
  439.                 return
  440.             end
  441.         end
  442.     until resInd == 1 -- cancel
  443. end
  444.  
  445. --====================================================================================================
  446. --// Utils
  447. --====================================================================================================
  448.  
  449. function module.formatInt(number)
  450.     local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
  451.     int = int:reverse():gsub("(%d%d%d)", "%1,")
  452.     return minus .. int:reverse():gsub("^,", "") .. fraction
  453. end
  454.  
  455. function module:getItemDisplayName(itemId)
  456.     local str = string.gsub(itemId,".*:", "")
  457.     str = string.gsub(str,"_"," ")
  458.     str = string.gsub(str,"^%l", string.upper)
  459.     return str
  460. end
  461.  
  462. function module:mcColorize(text)
  463.     local txt = string.gsub(text,module.replaceSymbol,module.mcColorSymbol)
  464.     txt = string.gsub(txt,module.removeSymbol,"")
  465.     return txt
  466. end
  467.  
  468. function module.getKeyCodeInt(keycode)
  469.     local c = keycode-48
  470.     if c > 9 or c < 0 then return nil end
  471.     return c
  472. end
  473.  
  474. function module:makeSeperator(char,charsToRemove)
  475.     local s = ""
  476.     for i = 1, self.size.x do
  477.         s = s..tostring(char)
  478.     end
  479.     return s
  480. end
  481.  
  482.  
  483.  
  484. return module
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement