dadragon84

menuAPI

Feb 19th, 2025
22
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.85 KB | Source Code | 0 0
  1. function titleize(text)
  2. local x = term.getSize()
  3. if #text+2 > x then return text end
  4. text = " "..string.upper(text).." "
  5. for i=1, math.floor((x-#text)/2) do
  6.   text = "="..text.."="
  7. end
  8. return text
  9. end
  10.  
  11. function menu(title, description, textTable, isNumbered, titleAlign, textAlign, prefixCharacter, suffixCharacter, incrementFunction)
  12. local x, y = term.getSize() --Screen size
  13. local alignments = { left = "left", center = "center", right = "right" } --Used for checking if alignment is valid
  14. if not (title and textTable) then error("Requires title and menu list",2) end
  15. if not type(textTable) == "table" and #textTable >= 1 then error("Menu list must be a table with values",2) end
  16. if #title > x then error("Title too long",2) end --If the title is longer than a line, program messes up
  17. if isNumbered == nil then isNumbered = true end --Setting isNumbered default
  18. titleAlign = alignments[titleAlign] or alignments.center --Default title alignment
  19. textAlign = alignments[textAlign] or alignments.left --Default options alignment
  20. prefixCharacter = prefixCharacter or "["
  21. suffixCharacter = suffixCharacter or "]"
  22. if type(textTable[1]) == "table" then --This allows you to have tables of text, function pairs. So my function returns 1, and you call input[1].func()
  23.   for i=1, #textTable do
  24.     textTable[i] = textTable[i].text
  25.   end
  26. end
  27. local function align(text, alignment) --Used to align text to a certain direction
  28.   if alignment == "left" then return 1 end
  29.   if alignment == "center" then return (x/2)-(#text/2) end
  30.   if alignment == "right" then return x - #text end
  31.   error("Invalid Alignment",3) --Three because is only called by output
  32. end
  33. local function output(text,y, alignment) --My own term.write with more control
  34.   local x = align(text, alignment)
  35.   term.setCursorPos(x,y)
  36.   term.clearLine()
  37.   return term.write(text)
  38. end
  39. local currIndex, descriptionLines, scroll = 1, 0, 0 --currIndex is the item from the table it is on, scroll is how many down it should go.
  40. if description then  --descriptionLines is how many lines the description takes up
  41.   descriptionLines = print(description); term.clear(); term.setCursorPos(1,1)--This is my way of figuring out how many lines the description is
  42. end
  43. if descriptionLines > y-4 then error("Description takes up too many lines",2) end --So at least two options are on screen
  44. local titleLines = descriptionLines + 2 --The title line, descriptions, plus extra line
  45. local top, bottom = 1, (y-titleLines) --These two are used to determine what options are on the screen right now (through scroll)
  46. while true do
  47.   if currIndex <= top and top > 1 then --If index is at top, scroll up
  48.     scroll = scroll - 1
  49.     top, bottom = top - 1, bottom - 1
  50.   end
  51.   if currIndex >= bottom and bottom < #textTable then --If at bottom scroll down. Change to > instead of >= to only do on bottom line. Same for above
  52.     scroll = scroll + 1
  53.     top, bottom = top + 1, bottom + 1
  54.   end
  55.   term.clear()
  56.   output(title,1, titleAlign) --Print title
  57.   if descriptionLines == 1 then --Not an else because we don't want to print nothing
  58.     output(description,2, titleAlign)
  59.   elseif descriptionLines > 1 then
  60.     term.setCursorPos(1,2); print(description)
  61.   end
  62.   for i = 1, math.min(y - titleLines,#textTable) do --The min because may be fewer table entries than the screen is big
  63.     local prefix, suffix = "", "" --Stuff like spaces and numbers
  64.     if isNumbered then prefix = tostring(i+scroll)..". " end --Attaches a number to the front
  65.     if i + scroll == currIndex then prefix = prefixCharacter.." "..prefix; suffix = suffix.." "..suffixCharacter  --Puts brackets on the one highlighted
  66.       elseif textAlign == "left" then for i=1, #prefixCharacter+1 do prefix = " "..prefix end --This helps alignment
  67.       elseif textAlign == "right" then for i=1, #suffixCharacter+1 do suffix  = suffix.." " end --Same as above
  68.     end
  69.     if not (#(prefix..textTable[i+scroll]..suffix) <= x) then term.clear(); term.setCursorPos(1,1); error("Menu item "..tostring(i+scroll).." is longer than one line. Cannot Print",2) end
  70.     output(prefix..textTable[i+scroll]..suffix, i + titleLines, textAlign)
  71.   end
  72.   if type(incrementFunction) ~= "function" then --This allows you to have your own custom logic for how to shift up and down and press enter.
  73.     incrementFunction = function()                --e.g. You could use redstone on left to increment, right to decrement, front to press enter.
  74.       _, key = os.pullEvent("key")
  75.       if key == 200 then return "up"
  76.         elseif key == 208 then return "down"
  77.         elseif key == 28 then return "enter"
  78.       end
  79.     end
  80.   end
  81.   action = incrementFunction()
  82.   if action == "up" and currIndex > 1 then
  83.     currIndex = currIndex - 1
  84.   end
  85.   if action == "down" and currIndex < #textTable then
  86.     currIndex = currIndex + 1
  87.   end
  88.   if action == "enter" then
  89.     return currIndex, textTable[currIndex]
  90.   end
  91. end
  92. end
Add Comment
Please, Sign In to add comment