This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
dUc0N's profile picture

Various APIs (Menus, Lock screen, Centered text)

Started by dUc0N, 11 August 2012 - 09:53 PM
dUc0N #1
Posted 11 August 2012 - 11:53 PM
Hi,

Long time lurker, first time poster. Thought I'd put this post here as a way to share some of the code I've been working on with ComputerCraft on our Tekkit server. I've made a total of four new functions across two files with fairly broad usefulness:

1. "menu" API

Usage: menu.status("Message", {"list","of","items"}, {"status","messages"})
Returns: Number of item selected.


Usage: menu.status("Message", {"list","of","items"})
Returns: Number of item selected.


Usage: menu.lockscreen(password) (Yes, technically this isn't exactly a menu, but this is where it made the most sense to put the function.)
Function: Locks the screen and displays number of failed logins and time locked.
Warning! This function requires the textutils mod below. Alternatively, stash the "centerprint" function in another file and change the function calls appropriately.
Disable Ctrl+T for best security using os.pullEvent. Details here.) (Small edit to add an additional term.clear() to the lock screen.)


Code:
Spoiler

-- Menu that displays status messages
-- Usage: menu.status("Message", {"list","of","items"}, {"status","messages"})
-- Returns: Number of item selected.
	function status(q,m,s)
	  local n=1
	  local l=#m
	  while true do
		term.clear()
		term.setCursorPos(1,2)
		print(q)
		for i=1, l, 1 do
		  if i==n then
			term.setCursorPos(1,i+3)
			if (s[i] == "") then
			  print("->", i, "  "..m[i])
			else
			  print("->", i, "  "..m[i].." ["..s[i].."] ")
			end
		  else
			term.setCursorPos(3,i+3)
			if (s[i] == "") then
			  print(i, "  ", m[i])
			else
			  print(i, "  ", m[i].." ["..s[i].."] ")
			end
		  end
		end
		term.setCursorPos(1, l+5)
		print("Make a selection using your arrow keys: "..n)
		local a, b= os.pullEventRaw()
		if a == "key" then
		  if b==200 and n>1 then n=n-1 end
		  if b==208 and n<l then n=n+1 end
		  if b==28 then break end
		end
	  end
	  term.clear() term.setCursorPos(1,1)
	  return n
	end

-- Pretty menu function
-- Usage: menu.status("Message", {"list","of","items"})
-- Returns: Number of item selected.
	function plain(q,m)
	  local n=1
	  local l=#m
	  while true do
		term.clear()
		term.setCursorPos(1,2)
		print(q)
		for i=1, l, 1 do
		  if i==n then
			term.setCursorPos(1,i+3)
			print("->", i, "  "..m[i])
		  else
			term.setCursorPos(3,i+3)
			print(i, "  ", m[i])
		  end
		end
		term.setCursorPos(1, l+5)
		print("Make a selection using your arrow keys: "..n)
		local a, b= os.pullEventRaw()
		if a == "key" then
		  if b==200 and n>1 then n=n-1 end
		  if b==208 and n<l then n=n+1 end
		  if b==28 then break end
		end
	  end
	  term.clear() term.setCursorPos(1,1)
	  return n
	end

-- Screen locking function
-- Usage: menu.lockscreen(password)
-- Locks the screen and displays number of failed logins and time locked.
-- Disable Ctrl+T for best security.
	function lockscreen(pass)
	  local i = 0
	  local timestr = textutils.formatTime( os.time(), false )
	  term.clear()
	  while true do
		textutils.centerprint("-------------------", 3)
		textutils.centerprint("| TERMINAL LOCKED |", 4)
		textutils.centerprint("-------------------", 5)
		textutils.centerprint("Enter password:", 7)
		if i > 0 then
		  textutils.centerprint("** "..i.." login failures since locking. **", 17)
		end
		textutils.centerprint("Locked at "..timestr, 16)
		term.setCursorPos(17,8)
		local t = io.read()
		if t == pass then
		  break
		elseif t == "" then
		  -- Do nothing.
		else
		  i=i+1
		end
		term.clear()
	  end
	end

2. Mod to textutils API:

Usage: textutils.centerprint("Message", terminal row)
Function: Prints the given text in the horizontal center of the row given. If the text is wider than the screen, then it errors (returns 1).
I want to make the row an optional argument, but for now it seems easier to leave it. Specifying it via a call to term.getCursorPos only does in the calling program what I'd be doing in the function, anyways.


function centerprint(message, yoffset)
  local width = term.getSize()
  local o = string.len(message)
  if o > width then
	return 1
  else
	term.setCursorPos((width-o)/2, yoffset)
	print(message)
  end
end
Edited on 11 August 2012 - 10:01 PM
nutcase84 #2
Posted 17 February 2013 - 08:53 AM
This is good, but you could add auto ypos-ing to cprint.