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

[ Error ] [ Solved ] Why is my program returning attempt to call nil?

Started by AnthonyD98™, 10 February 2013 - 01:14 PM
AnthonyD98™ #1
Posted 10 February 2013 - 02:14 PM
Okay so what happens is I run the program and I press enter on the selection 'Programs' and It returns

multi:80: attempt to call nil

I've tried moving the functions that each function needs above each other.

Example:

drawTitle() function needs the space() & cPrint function to work, so I moved those up to the top of the code so It can use those functions

But I still don't know why I get the attempt to call nil when I try use the Programs Selection.

Pastebin link:

http://pastebin.com/8dNJdrRz

Thanks, AnthonyD98
theoriginalbit #2
Posted 10 February 2013 - 02:25 PM
move the declaration of var (line 100) up to the top…
AnthonyD98™ #3
Posted 10 February 2013 - 02:31 PM
move the declaration of var (line 100) up to the top…

Then I get the error

multi:53: attempt to index ? (a nil value )
theoriginalbit #4
Posted 10 February 2013 - 02:42 PM
I get the error on line 51 "'for' limit must be a number… so move numvar up to to the top too…

Also both need to be below mainOptions

edit: There are also problems with this function… gui is declared below it, and your not modifying the var and numvar variables, you have made them local to that scope (function) so it doesn't change the ones in the program scope


local function drawPrograms()
 local var = programOptions
 local numvar = #programOptions
 gui()
end
AnthonyD98™ #5
Posted 10 February 2013 - 02:56 PM
I get the error on line 51 "'for' limit must be a number… so move numvar up to to the top too…

Also both need to be below mainOptions

edit: There are also problems with this function… gui is declared below it, and your not modifying the var and numvar variables, you have made them local to that scope (function) so it doesn't change the ones in the program scope


local function drawPrograms()
local var = programOptions
local numvar = #programOptions
gui()
end

Okay now my code looks like this
http://pastebin.com/FsRXifw0

How do I fix the drawPrograms() function
Every place I put it at, it errors.
AnthonyD98™ #6
Posted 10 February 2013 - 03:09 PM
AHA!

If I write drawPrograms() in a different program as a global function it works!!

EDIT: Now just need to find out how to make it work within the program as a global function!
AnthonyD98™ #7
Posted 10 February 2013 - 03:17 PM
Now its bugging out again -_-/>
remiX #8
Posted 10 February 2013 - 03:28 PM
I highly suggest using an argument within the functions for which table to print etc:

Spoiler
local programOptions = {
    {"Button1", button1},
}

local varY = 3
local s = 1
local w,h = term.getSize()
local function center(text, line, col)
	term.setCursorPos(math.floor(w/2)-string.len(text)/2, line)
	term.setBackgroundColour(col)
	term.clearLine()
	print(text)
end

local function space()
 print("")
end

local function cPrint(str)
	x, _ = term.getSize()
	_, y = term.getCursorPos()
	term.setCursorPos((x-#str)/2, y)
	print(str)
end

local function drawTitle()
	term.setTextColor(32)
	term.clear()
	term.setCursorPos(1,1)
	cPrint("[ SelectOS BETA ]")
	space()
	space()
end

local function drawMain(_table)
	for i = 1, #_table do
		if s == i then
			center(_table[i][1], varY + i, colours.cyan)
		else
			center(_table[i][1], varY + i, colours.blue)
		end
	end
end

local function gui(_table)
	while true do
		term.clear()
		term.setCursorPos(1,1)
		term.setBackgroundColor(colors.blue)
		drawTitle()
		term.setTextColor(colors.white)
		drawMain(_table)
		local event, p1, p2, p3 = os.pullEvent()
		if event == "key" then
			if p1 == keys.down or p1 == 31 then
				s = s + 1
				if s >= #_table + 1 then s = 1 end
			elseif p1 == keys.up or p1 == 17 then
				s = s - 1
				if s <= 0 then s = #_table end
			elseif p1 == keys.enter then
				term.setBackgroundColor(colors.black)
				term.setTextColor(colors.white)
				print(type(_table[s][2])) sleep(1)
				_table[s][2]()
			end
		elseif event == "mouse_click" then
			if _table[p3 - 3] ~= nil then
				start=math.floor(math.floor(51/2)-(string.len(_table[p3-3][1])+4)/2)-1
				if start <p2 and start+(string.len(_table[p3-3][1])+5)>p2 then
					term.setBackgroundColor(colors.black)
					term.setTextColor(colors.white)
					_table[p3-3][2]()
				end
			end
		elseif event == "mouse_scroll" then
			s = s + p1
			if s >= #_table + 1 then s = 1 end
			if s <= 0 then s = #_table end
		end
	end
end

local function drawPrograms()
	gui(programOptions)
end

local mainOptions = {
    {"Programs", drawPrograms},
    {"Control Panal", drawCP},
    {"File Browser", bFile},
    {"Command Prompt", drawCMD},
    {"Exit to CraftOS", function() term.clear() term.setCursorPos(1,1) error();end},
    {"Restart Computer", os.reboot},
    {"Shutdown Computer", os.shutdown},
}

gui(mainOptions)
Doyle3694 #9
Posted 10 February 2013 - 03:29 PM
What do you mean with making it work withing the program as a global function?
AnthonyD98™ #10
Posted 10 February 2013 - 03:39 PM
I highly suggest using an argument within the functions for which table to print etc:

Spoiler
local programOptions = {
	{"Button1", button1},
}

local varY = 3
local s = 1
local w,h = term.getSize()
local function center(text, line, col)
	term.setCursorPos(math.floor(w/2)-string.len(text)/2, line)
	term.setBackgroundColour(col)
	term.clearLine()
	print(text)
end

local function space()
print("")
end

local function cPrint(str)
	x, _ = term.getSize()
	_, y = term.getCursorPos()
	term.setCursorPos((x-#str)/2, y)
	print(str)
end

local function drawTitle()
	term.setTextColor(32)
	term.clear()
	term.setCursorPos(1,1)
	cPrint("[ SelectOS BETA ]")
	space()
	space()
end

local function drawMain(_table)
	for i = 1, #_table do
		if s == i then
			center(_table[i][1], varY + i, colours.cyan)
		else
			center(_table[i][1], varY + i, colours.blue)
		end
	end
end

local function gui(_table)
	while true do
		term.clear()
		term.setCursorPos(1,1)
		term.setBackgroundColor(colors.blue)
		drawTitle()
		term.setTextColor(colors.white)
		drawMain(_table)
		local event, p1, p2, p3 = os.pullEvent()
		if event == "key" then
			if p1 == keys.down or p1 == 31 then
				s = s + 1
				if s >= #_table + 1 then s = 1 end
			elseif p1 == keys.up or p1 == 17 then
				s = s - 1
				if s <= 0 then s = #_table end
			elseif p1 == keys.enter then
				term.setBackgroundColor(colors.black)
				term.setTextColor(colors.white)
				print(type(_table[s][2])) sleep(1)
				_table[s][2]()
			end
		elseif event == "mouse_click" then
			if _table[p3 - 3] ~= nil then
				start=math.floor(math.floor(51/2)-(string.len(_table[p3-3][1])+4)/2)-1
				if start <p2 and start+(string.len(_table[p3-3][1])+5)>p2 then
					term.setBackgroundColor(colors.black)
					term.setTextColor(colors.white)
					_table[p3-3][2]()
				end
			end
		elseif event == "mouse_scroll" then
			s = s + p1
			if s >= #_table + 1 then s = 1 end
			if s <= 0 then s = #_table end
		end
	end
end

local function drawPrograms()
	gui(programOptions)
end

local mainOptions = {
	{"Programs", drawPrograms},
	{"Control Panal", drawCP},
	{"File Browser", bFile},
	{"Command Prompt", drawCMD},
	{"Exit to CraftOS", function() term.clear() term.setCursorPos(1,1) error();end},
	{"Restart Computer", os.reboot},
	{"Shutdown Computer", os.shutdown},
}

gui(mainOptions)

If you don't mind could you put that code on pastebin for me?

What do you mean with making it work withing the program as a global function?

I meant have the drawPrograms() function working within the orginal program and not having to be used outside of the program as a global function
remiX #11
Posted 10 February 2013 - 03:50 PM
http://pastebin.com/WDFkQJhR
AnthonyD98™ #12
Posted 10 February 2013 - 03:54 PM

I saw you changed the center function slighty. What does the col part of it do?
I also noticed whenever I use a function / selection it prints whats happening
Is that a feature that I can turn off and when needed turn on for debugging purposes?
remiX #13
Posted 10 February 2013 - 04:57 PM
col is for the colour of the background.

Yeah, was a debug line I used:
print(type(_table[s][2])) sleep(1)

You can delete it
AnthonyD98™ #14
Posted 10 February 2013 - 05:00 PM
col is for the colour of the background.

Yeah, was a debug line I used:
print(type(_table[s][2])) sleep(1)

You can delete it

No its fine, I added some tArgs to the beggining of the program.
if you run with -debug the you can see the printing of functions
if you run without the -debug it runs normally.

local tArgs = (...)
if tArgs == "-debug" then
debug = true
else
debug = false
end
theoriginalbit #15
Posted 10 February 2013 - 05:14 PM
This is a more stream line version of what you did

local tArgs = ...
local debug = (tArgs == "-debug")
This can be used because an if statement uses a true false to know what it's to do, so why have an if, to then assign a Boolean… May as well just put the condition in the variable assignment

This is how I normally do it, mind you I normally allow for more args like '-help'

local tArgs = {...}
if #tArgs == 1 then
  if tArgs[1] == "-debug" then
    debug = true
  -- elseif other args checking and such
  else
    -- print usage
  end
elseif #tArgs ~= 0 then -- if they entered something more than 1 arg
  -- print usage
end