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

Need help, strange error..

Started by jag, 20 December 2012 - 09:43 AM
jag #1
Posted 20 December 2012 - 10:43 AM
So here I was coding some, and I stumbled upon a strange error message:
[indent=1]
API:259: index expected, got nil
[/indent]

Now heres the code that I am running:
Spoiler
--[[

+-------------+
| JagOS - API |
+-------------+

]]--

local occu = {}
local selection = nil

local defaultWidth, defaultHeight = term.getSize()
defaultWidth = defaultWidth / 2
defaultHeight = defaultHeight / 2

local focus = {}
local window = {
	id = {},
	position_x = {},
	position_y = {},
	label = {},
	height = {},
	width = {},
}

local windowGraffic = {
	UR_corner = "+",
	UL_corner = "+",
	LR_corner = "+",
	LL_corner = "+",
	URS_corner = ".",
	ULS_corner = ".",
	L_side = "|",
	R_side = "|",
	LS_side = "|",
	RS_side = "|",
	top = "-",
	S_top = "-",
	bottom = "-",
	button_1 = "[+]", -- enlarge window
	button_2 = "[-]", -- minimize window
	button_3 = "[o]", -- close window
}

local toolBarGraffic = {
	border = "-",
	L_cutter = ")",
	R_cutter = "|",
	menu_name = "Start",
	window_name_L = "[",
	window_name_R = "]"
}

local colors = {
	["white"] = 0,
	["orange"] = 1,
	["light purple"] = 2,
	["light blue"] = 3,
	["yellow"] = 4,
	["light green"] = 5,
	["pink"] = 6,
	["gray"] = 7,
	["light gray"] = 8,
	["cyan"] = 9,
	["purple"] = 10,
	["blue"] = 11,
	["brown"] = 12,
	["green"] = 13,
	["red"] = 14,
	["black"] = 15
}

function screen_width()
	width_var, _ = term.getSize()
	defaultWidth = width_var / 2
	return width_var
end

function screen_height()
	_, height_var = term.getSize()
	defaultHeight = height_var / 2
	return height_var
end

function detectModem()
  for _,side in ipairs(rs.getSides()) do
	if peripheral.isPresent(side) then
	  if peripheral.getType(side) == "modem" then
		rednet.open(side)
		return side
	  end
	end
  end
  return false
end

function table_contains(table, element)
	if type(table) ~= "table" then
		error("Table expected, got \""..type(table).."\"")
	end
	for _, value in pairs(table) do
		if value == element then
			return true
		end
	end
	return false
end

function table_header_contains(table, element)
	if type(table) ~= "table" then
		error("Table expected, got \""..type(table).."\"")
	end
	for value, _ in pairs(table) do
		if value == element then
			return true
		end
	end
	return false
end

function col(colorName)
	if type(colorName) ~= "string" then
		error("String expected, got \""..type(colorName).."\"")
	else
		colorName = string.lower(colorName)
	end
	if table_header_contains(colors, colorName) then
		return colors[colorName]
	else
		error("Invalid color name: "..colorName)
	end
end

windowGraffic.color_1 = col("light blue") -- top border
windowGraffic.color_2 = col("blue") -- border background
windowGraffic.color_3 = col("light blue") -- border
windowGraffic.color_4 = col("black") -- inner background
windowGraffic.color_5 = col("cyan") -- top inner background
windowGraffic.color_6 = col("blue") -- top border background

toolBarGraffic.color_1 = col("blue") -- border background
toolBarGraffic.color_2 = col("light blue") -- border
toolBarGraffic.color_3 = col("white") -- menu name
toolBarGraffic.color_4 = col("cyan") -- bar background
toolBarGraffic.color_5 = col("light blue") -- cutters
toolBarGraffic.color_6 = col("light gray") -- window names
toolBarGraffic.color_7 = col("white") -- symbols

function setFocus(windowID)
	local oldFocus = focus
	focus = {}
	focus[1] = windowID
	for i = 1, #oldFocus do
		if oldFocus[i] ~= windowID then
			focus[#focus+1] = oldFocus[i]
		end
	end
	oldFocus = nil
end

function writeCol(txt, txtCol, bgCol)
	if type(txt) ~= "string" then
		error("String expected, got \""..type(txt).."\"")
	end
	if txtCol then
		if type(txtCol) ~= "number" then
			error("Number expected, got \""..type(txtCol).."\"")
		else
			if table_contains(colors, txtCol) then
				term.setTextColor(2^txtCol)
			else
				error("Invalid color code!")
			end
		end
	end
	if bgCol then
		if type(bgCol) ~= "number" then
			error("Number expected, got \""..type(bgCol).."\"")
		else
			if table_contains(colors, txtCol) then
				term.setBackgroundColor(2^bgCol)
			else
				error("Invalid color code!")
			end
		end
	end
	term.write(txt)
	return true
end

-- occu[ x ][ y ]
-- occu[ w ][ h ]
function fixOccu()
	local w,h = term.getSize()
	for x = 1,#occu do
		if x > w then
			table.remove(occu,x)
		else
			for y = 1,#occu[x] do
				if y > h then
					table.remove(occu[x],y)
				end
			end
		end
	end
	for p_width = 1,w do
		if type(occu[p_width]) ~= "table" then
			occu[p_width] = {}
		end
		for p_height = 1,h do
			if type(occu[p_width][p_height]) ~= "number" then
				occu[p_width][p_height] = 0
			end
		end
	end
end

function createWindow(windowLabel, positionX, positionY)
	if type(windowLabel) ~= "string" then
		error("String expected, got \""..type(windowLabel).."\"")
	end
	if positionX then
		if type(positionX) ~= "number" then
			error("Number expected, got \""..type(positionX).."\"")
		end
	end
	if positionY then
		if type(positionY) ~= "number" then
			error("Number expected, got \""..type(positionY).."\"")
		end
	end
	positionX = positionX or 1
	positionY = positionY or 1
	local windowID = #window.id + 1
	table.insert(window.id, windowID)
	table.insert(window.position_x, windowID, positionX)
	table.insert(window.position_y, windowID, positionY)
	table.insert(window.label, windowID, windowLabel)
	table.insert(window.width, windowID, defaultWidth)
	table.insert(window.height, windowID, defaultHeight)
	setFocus(windowID)

	return windowID
end

function drawWindow(windowID)
	if type(windowID) ~= "number" then
		error("Number expected, got \""..type(windowID).."\"")
	end
	if table_contains(window,windowID) then
		error("Undefined window ID, not valid")
	end

	local extra = #windowGraffic.button_3 + #windowGraffic.button_2 + #windowGraffic.button_1
	fixOccu()

	for width = 0, window.width[windowID] do
		for height = 0, window.height[windowID] do
			occu[width][height] = windowID !!!!!!!!{{{ 'THIS LINE' }}}!!!!!!!!
		end
	end

	-- Upper left special corner
	term.setCursorPos(window.position_x[windowID], window.position_y[windowID])
	writeCol(windowGraffic.ULS_corner, windowGraffic.color_1, windowGraffic.color_6)

	-- Special top
	for width = 1, window.width[windowID]-1 do
		term.setCursorPos(window.position_x[windowID]+width, window.position_y[windowID])
		writeCol(windowGraffic.S_top, windowGraffic.color_1, windowGraffic.color_6)
	end

	-- Left special side
	term.setCursorPos(window.position_x[windowID], window.position_y[windowID]+1)
	writeCol(windowGraffic.LS_side, windowGraffic.color_1, windowGraffic.color_6)

	-- Top inner background
	for TI_bg = 1, window.width[windowID]-1 do
		term.setCursorPos(window.position_x[windowID]+TI_bg, window.position_y[windowID]+1)
		writeCol(" ", col("white"), windowGraffic.color_5)
	end

	-- Window Label
	local label = window.label[windowID]
	if #label > window.width[windowID]-4-extra then
		label = label.sub(label,1,window.width[windowID]-7-extra)
		label = label .. "..."
	end
	term.setCursorPos(window.position_x[windowID]+2, window.position_y[windowID]+1)
	writeCol(label, col("white"), windowGraffic.color_5)

	-- Upper left corner
	term.setCursorPos(window.position_x[windowID], window.position_y[windowID]+2)
	writeCol(windowGraffic.UL_corner, windowGraffic.color_3, windowGraffic.color_2)

	-- Left side
	for height = 3, window.height[windowID]-1 do
		term.setCursorPos(window.position_x[windowID], window.position_y[windowID]+height)
		writeCol(windowGraffic.L_side, windowGraffic.color_3, windowGraffic.color_2)
	end

	-- Lower left corner
	term.setCursorPos(window.position_x[windowID], window.position_y[windowID]+window.height[windowID])
	writeCol(windowGraffic.LL_corner, windowGraffic.color_3, windowGraffic.color_2)

	-- Bottom
	for width = 1, window.width[windowID]-1 do
		term.setCursorPos(window.position_x[windowID]+width, window.position_y[windowID]+window.height[windowID])
		writeCol(windowGraffic.bottom, windowGraffic.color_3, windowGraffic.color_2)
	end

	-- Lower right corner
	term.setCursorPos(window.position_x[windowID]+window.width[windowID], window.position_y[windowID]+window.height[windowID])
	writeCol(windowGraffic.LR_corner, windowGraffic.color_3, windowGraffic.color_2)

	-- Right side
	for height = 3, window.height[windowID]-1 do
		term.setCursorPos(window.position_x[windowID]+window.width[windowID], window.position_y[windowID]+height)
		writeCol(windowGraffic.R_side, windowGraffic.color_3, windowGraffic.color_2)
	end

	-- Top
	for width = 1, window.width[windowID]-1 do
		term.setCursorPos(window.position_x[windowID]+width, window.position_y[windowID]+2)
		writeCol(windowGraffic.top, windowGraffic.color_3, windowGraffic.color_2)
	end

	-- Right special side
	term.setCursorPos(window.position_x[windowID]+window.width[windowID], window.position_y[windowID]+1)
	writeCol(windowGraffic.RS_side, windowGraffic.color_1, windowGraffic.color_6)

	-- Upper right corner
	term.setCursorPos(window.position_x[windowID]+window.width[windowID], window.position_y[windowID]+2)
	writeCol(windowGraffic.UR_corner, windowGraffic.color_3, windowGraffic.color_2)

	-- Upper right special corner
	term.setCursorPos(window.position_x[windowID]+window.width[windowID], window.position_y[windowID])
	writeCol(windowGraffic.URS_corner, windowGraffic.color_1, windowGraffic.color_6)

	-- Right special side
	term.setCursorPos(window.position_x[windowID]+window.width[windowID], window.position_y[windowID]+1)
	writeCol(windowGraffic.RS_side, windowGraffic.color_1, windowGraffic.color_6)

	-- Inner window background
	for height = 3, window.height[windowID]-1 do
		for width = 1, window.width[windowID]-1 do
			term.setCursorPos(window.position_x[windowID]+width, window.position_y[windowID]+height)
			writeCol(" ", col("white"), windowGraffic.color_4)
		end
	end

	-- Buttons
	term.setCursorPos(window.position_x[windowID]+window.width[windowID]-extra, window.position_y[windowID]+1)
	writeCol(windowGraffic.button_1, col("green"), col("light green"))
	writeCol(windowGraffic.button_2, col("orange"), col("yellow"))
	writeCol(windowGraffic.button_3, col("brown"), col("red"))
end

function drawWindows()
	for i = #focus, 1, -1 do
		drawWindow(focus[i])
	end
end


function drawToolBar()
	-- Border
	for width = 1, screen_width() do
		term.setCursorPos(width,screen_height()-1)
		writeCol(toolBarGraffic.border, toolBarGraffic.color_1, toolBarGraffic.color_2)
	end

	-- ToolBar background
	for width = 1, screen_width() do
		term.setCursorPos(width,screen_height())
		writeCol(" ", toolBarGraffic.color_1, toolBarGraffic.color_4)
	end

	-- Menu name
	term.setCursorPos(1, screen_height())
	writeCol(" "..toolBarGraffic.menu_name.." ", toolBarGraffic.color_3, toolBarGraffic.color_4)
	writeCol(toolBarGraffic.L_cutter.." ", toolBarGraffic.color_5, toolBarGraffic.color_4)

	-- Window names
	local toolBarNameDistance = string.len(" "..toolBarGraffic.menu_name.." "..toolBarGraffic.L_cutter.." ")+1
	local limit = screen_width()-toolBarNameDistance-7-(3 * #window.id)
	limit = (limit / #window.id)
	for value, _ in pairs(window.id) do
		term.setCursorPos(toolBarNameDistance,screen_height())
		local label = window.label[value]
		if #label > limit and #label > 4 then
			label = label.sub(label,1,limit-3)
			label = label .. "..."
		end
		label = toolBarGraffic.window_name_L..label..toolBarGraffic.window_name_R.." "
		toolBarNameDistance = toolBarNameDistance + #label
		writeCol(label, toolBarGraffic.color_6, toolBarGraffic.color_4)
	end
end

--[[function pullEvent(windowID, evIn)
	if type(windowID) ~= "number" then
		error("Number expected, got \""..type(windowID).."\"")
	end
	if evIn ~= nil then
		if type(evIn) ~= "string" then
			error("String expected, got \""..type(windowID).."\"")
		end
	end
	local ev,p1,p2,p3,p4,p5 = os.pullEvent(evIn)
	if ev == "mouse_click" or ev == "mouse_scroll" then
		if ]]--

function getSize(windowID)
	if type(windowID) ~= "number" then
		error("Number expected, got \""..type(windowID).."\"")
	end
	if not table.contains(window.id, windowID) then
		return false
	end
	return window.width[windowID], window.height[windowID]
end

function test()
	for i = 1,#occu do
		for j = 1,#occu[i] do
			term.setCursorPos(i,j)

			API.writeCol(tostring(occu[i][j]), col("white"), col("black"))
		end
	end
end

I am running this via a test file:
Spoiler
term.clear()
if not fs.exists("API") then
  print("Can't locate API!")
  return
end
if not os.loadAPI("API") then
  print("Failed to load API!")
  return
end

API.createWindow("superlongnamewithoutspaces",_,2)
API.createWindow("Window 2!",7,4)
API.createWindow("Nisse :)/>",15,12)

API.drawWindows()
API.drawToolBar()

term.setCursorPos(1,API.screen_height()-2)

os.unloadAPI("API")
Lyqyd #2
Posted 20 December 2012 - 11:17 AM
Post the full code and the full error message.
jag #3
Posted 20 December 2012 - 11:21 AM
Post the full code and the full error message.

That is the full error message!
The rest of the message is just the file name : line number, wich I have marked out.
Anyways, I added it

Entire code: sure, added. It's from the making of a OS btw
remiX #4
Posted 20 December 2012 - 11:29 AM
Do some debug lines like, print(window.width[windowID]) and print(type(window.width[windowID]))
do it for the others to and check what they are.
jag #5
Posted 20 December 2012 - 11:31 AM
Do some debug lines like, print(window.width[windowID]) and print(type(window.width[windowID]))
do it for the others to and check what they are.
I've already, but it dosen't help, still the same error and no debug messages

EDIT: I think I might have read your question wrong… This is the output from the respective code:
print("Window "..windowID)
print("Width: "..window.width[windowID])
print("Height: "..window.height[windowID])

for width = 0, window.width[windowID] do
	for height = 0, window.height[windowID] do
		occu[width][height] = windowID
	end
end
Output:
Window 1
Width: 25.5
Height: 9.5
API:263: index expected, got nil

I think I know whats happening here..

EDIT 2: Nope I was wrong, still same error!
jag #6
Posted 20 December 2012 - 11:48 AM
I think I found the problem:
When it tries to set occu[0] it cant, because in lua tables start in 1…
Cranium #7
Posted 20 December 2012 - 11:50 AM
actually, you can have a 0 index.
Indices can be anything you want, even negative numbers.
remiX #8
Posted 20 December 2012 - 12:08 PM
Yeah I was going to say that jag, but I first tested it and you can. But it just prints blank but doesn't error.
ChunLing #9
Posted 20 December 2012 - 06:45 PM
	   for width = 0, window.width[windowID] do
-- occu[width] = {} -- uncomment this if occu[width] was not already a table
			    for height = 0, window.height[windowID] do
print(type(width),width,type(height),height)
					    occu[width][height] = windowID !!!!!!!!{{{ 'THIS LINE' }}}!!!!!!!!
			    end
	    end
The error indicates that either width or height was a nil at some point, so print those out for every value. Also, if you didn't make occu[width] a table before, you need to do so before attempting to populate it (that should have given a different error message, though).
jag #10
Posted 20 December 2012 - 08:37 PM
I fixed it just by doing this:

if not occu[width+window.position_x[windowID]] then
	occu[width+window.position_x[windowID]] = {}
end