Easy Menu API
Description
Written By: GhastTearz
Installation
Copy one of these commands into your ComputerCraft terminal:
Pastebin:
pastebin get B1N0C6Ua easy_menu_apiwget:
wget https://pastebin.com/raw/B1N0C6Ua easy_menu_apiArchive:
wget https://cc.shobie.xyz/cc/get/pb-B1N0C6Ua easy_menu_api
Quick Install:
wget https://cc.shobie.xyz/cc/get/pb-B1N0C6Ua Easy Menu API
Usage
Run the program after downloading
Tags
Source
View Original SourceCode Preview
-- Menu API
--
-- Written By: GhastTearz
-- Version: 2.0.0
--
-- This program is a simple and flexible way to get
-- menus in your program.
--
-- The format of menu strings is very simple. Each
-- line of the string is a line in the menu. To add
-- a "link" to a function or screen just as a tag
-- somewhere in the line e.g. "@tag". See the demo
-- program for more information at
-- https://pastebin.com/ZNYdQzaR
--
-- KEYBINDINGS
-- w, k, up = move up the menu
-- a, h, left = go to previous screen
-- s, j, down = move down the menu
-- d, l, right, enter = select an item
-- q, x = quit
-- page up = go up a page
-- page down = go down a page
--
---------------------------------------------------
function addFunc(menu, tag, func, ...)
if menu == nil or type(menu) ~= "table" then
error("Expected a menu table.")
end
if tag == nil or type(tag) ~= "string" then
error("Expected a tag string.")
end
if func == nil or type(func) ~= "function" then
error("Expected a function.")
end
if menu[tag] ~= nil then
error("The tag "..tag.." is already in use.")
end
local args = ...
menu[tag] = function() func(args) end
end
function addScreen(menu, tag, screen)
if menu == nil or type(menu) ~= "table" then
error("Expected a menu table.")
end
if tag == nil or type(tag) ~= "string" then
error("Expected a tag string.")
end
if screen == nil or type(screen) ~= "string" then
error("Expected a screen string.")
end
if menu[tag] ~= nil then
error("The tag "..tag.." is already in use.")
end
menu[tag] = {}
-- parse the screen string into a table
local line = 1
local text = ""
local ref = ""
local i = 1
while i < #screen do
if screen:sub(i,i) == '@' then
if screen:sub(i+1,i+1) == '@' then
--escape two @s by skipping a char
i = i + 1
else
if ref ~= "" then
error("On input line "..line
.." for screen "..tag
.." there is more than one tag.")
end
i = i + 1
while screen:sub(i,i) ~= "" and
screen:sub(i,i) ~= ' ' and
screen:sub(i,i) ~= '\t' and
screen:sub(i,i) ~= '\n' do
ref = ref..screen:sub(i,i)
i = i + 1
end
if ref == "" then
error("On input line "..line
.." for screen "..tag
.." the tag is empty.")
end
end
end
if screen:sub(i,i) == '\n' or
screen:sub(i,i) == "" then
menu[tag][line] = {}
menu[tag][line].text = text
menu[tag][line].ref = ref
text = ""
ref = ""
line = line + 1
else
text = text..screen:sub(i,i)
end
i = i + 1
end
end
function displayScreen(menu, tag)
if menu == nil or type(menu) ~= "table" then
error("Expected a menu table.")
end
if tag == nil or type(tag) ~= "string" then
error("Expected a tag string.")
end
if menu[tag] == nil then
error("The tag "..tag.." does not exist.")
end
if type(menu[tag]) ~= "table" then
error("The tag "..tag.." is not a screen.")
end
--Check that all the tags refer to something
for k, v in pairs(menu) do
if type(menu[k]) == "table" then
for l = 1, #menu[k] do
local r = menu[k][l].ref
if r ~= "" and menu[r] == nil then
error("The tag "..r.." is not defined.")
end
end
end
end
local currentScreen = menu[tag]
local screenStack = {}
screenStack[1] = menu[tag]
local width, height = term.getSize()
-- These are indexes into the screen.
-- Top is the first line to be printed.
-- Bottom is the last line to be printed.
-- Selection is the line the user might select.
local top = 1
local bottom = height
local selection = 0
local function printScreen()
term.clear()
term.setCursorPos(1,1)
for i = top, bottom do
if i > #currentScreen then
break
end
local y = i % height
if y == 0 then
y = height
end
term.setCursorPos(1, y)
if i == selection then
write("->"..currentScreen[i].text)
else
write(" "..currentScreen[i].text)
end
end
end
local function setSelection()
selection = 0
for i = top, bottom do
if i > #currentScreen then
break
end
if currentScreen[i].ref ~= "" then
selection = i
break
end
end
end
local function pageUp()
if top > 1 then
top = top - height
bottom = bottom - height
setSelection()
end
end
local function pageDown()
if #currentScreen > bottom then
top = top + height
bottom = bottom + height
setSelection()
end
end
setSelection()
printScreen()
while true do
local e, key = os.pullEvent("key")
-- go up the screen
if key == 17 or
key == 37 or
key == 200 then
-- find prev item with a ref
local prevItem
for i = selection - 1, 1, -1 do
if currentScreen[i].ref ~= "" then
prevItem = i
break
end
end
if prevItem == nil then
pageUp()
else
selection = prevItem
if prevItem < top then
pageUp()
end
end
end
-- go down the screen
if key == 31 or
key == 36 or
key == 208 then
-- find the next item with a ref
local nextItem
for i = selection + 1, #currentScreen do
if currentScreen[i].ref ~= "" then
nextItem = i
break
end
end
if nextItem == nil then
pageDown()
else
selection = nextItem
if nextItem > bottom then
pageDown()
end
end
end
-- select the current item
if (key == 32 or
key == 38 or
key == 205 or
key == 28 ) and
currentScreen[selection] ~= nil then
local r = currentScreen[selection].ref
if type(menu[r]) == "function" then
term.clear()
term.setCursorPos(1,1)
return menu[r]
else
screenStack[#screenStack + 1] = menu[r]
currentScreen = menu[r]
top = 1
bottom = height
setSelection()
end
end
-- Go back to previous screen
if (key == 30 or
key == 35 or
key == 203) and
#screenStack > 1 then
screenStack[#screenStack] = nil
currentScreen = screenStack[#screenStack]
top = 1
bottom = height
setSelection()
end
-- quit the menu
if key == 16 or
key == 45 then
term.clear()
term.setCursorPos(1,1)
return
end
if key == 201 then
pageUp()
end
if key == 209 then
pageDown()
end
printScreen()
end
end
function new()
local t = {}
t.addFunc = addFunc
t.addScreen = addScreen
t.displayScreen = displayScreen
return t
end