20 posts
Posted 17 August 2014 - 05:18 PM
Although i encounter a common error here which is line 21, attempt to index ? (a nil value) but there is something that make this error even more complicated, which is the different placement of array and functions that correspond to each other. I need help to give my tips on how to arrange my codes so that i won't get the error.
The error occurs when i want to call a function that seems to be nil…
This is the code:(UNDERLINED IS WHERE ERROR OCCURS)
local select = 1
local running = true
local function clear()
term.clear()
term.setCursorPos(1,1)
end
local function printMenu(menustate)
clear()
for i = 1, #menustate do
if i == select then
print(">"..menustate.opt)
else
print(menustate.opt)
end
end
end
local function control()
changeState("control")
end
local function keyHandler(menustate)
event, key = os.pullEvent()
if key == 200 and select > 1 then
select = select - 1
elseif key == 208 and select < #menustate then
select = select + 1
elseif key == 28 then
menustate.action()
end
end
local menu = {
["main"] = {
[1] = {opt = "Control", action = control},
[2] = {opt = "Command", action = command},
[3] = {opt = "Exit", action = exit}
},
["control"] = {
[1] = {opt = "Lights", action = light},
[2] = {opt = "Door", action = door}
},
["command"] = {},
["lights"] = {}
}
local menustate = menu["main"]
local function changeState(newstate)
menustate = menu[newstate]
end
while true do
printMenu(menustate)
keyHandler(menustate)
end
Edited on 17 August 2014 - 04:05 PM
15 posts
Posted 17 August 2014 - 06:22 PM
What exactly is this function "changeState" and where is it defined? And why are you feeding it the string "("control")"
20 posts
Posted 17 August 2014 - 06:33 PM
local menu = {
["main"] = {
[1] = {opt = "Control", action = control},
[2] = {opt = "Command", action = command},
[3] = {opt = "Exit", action = exit}
},
["control"] = {
[1] = {opt = "Lights", action = light},
[2] = {opt = "Door", action = door}
},
["command"] = {},
["lights"] = {}
}
local function changeState(newstate)
menustate = menu[newstate]
end
changeState("control") simply change the menustate to a control menu
3057 posts
Location
United States of America
Posted 17 August 2014 - 07:26 PM
Try defining your functions before calling them.
20 posts
Posted 17 August 2014 - 07:45 PM
So if i define the function before calling for them, there will be another error called as it is calling for menu["control"] but the variable is later then defined. So to make everyone clear, i have an issue for the defining of variables and functions that corresponds with each other, one comes after another still gives error…
These four parts causes the problem, i need better ways to arrange them…
local menu = {
["main"] = {
[1] = {opt = "Control", action = control},
[2] = {opt = "Command", action = command},
[3] = {opt = "Exit", action = exit}
},
["control"] = {
[1] = {opt = "Lights", action = light},
[2] = {opt = "Door", action = door}
},
["command"] = {},
["lights"] = {}
}
local function changeState(newstate)
menustate = menu[newstate]
end
local function control()
changeState("control")
end
local function keyHandler(menustate)
event, key = os.pullEvent()
if key == 200 and select > 1 then
select = select - 1
elseif key == 208 and select < #menustate then
select = select + 1
elseif key == 28 then
menustate[select].action()
end
Edited on 17 August 2014 - 05:47 PM
3057 posts
Location
United States of America
Posted 17 August 2014 - 07:51 PM
Fixed it for you:
local menu = {
["main"] = {
[1] = {opt = "Control", action = control},
[2] = {opt = "Command", action = command},
[3] = {opt = "Exit", action = exit}
},
["control"] = {
[1] = {opt = "Lights", action = light},
[2] = {opt = "Door", action = door}
},
["command"] = {},
["lights"] = {},
}
local function changeState(newstate)
menustate = menu[newstate]
end
local function control()
changeState("control")
end
local function keyHandler(menustate)
event, key = os.pullEvent()
if key == 200 and select > 1 then
select = select - 1
elseif key == 208 and select < #menustate then
select = select + 1
elseif key == 28 then
menustate[select].action()
end
end
The issue: you were missing an end. It was easy to see after properly indenting your code. Also I believe there was a comma missing.
20 posts
Posted 17 August 2014 - 07:58 PM
It is still not fixed, now the error occurs at the menustate[select].action(), attempt to call nil
1140 posts
Location
Kaunas, Lithuania
Posted 17 August 2014 - 10:06 PM
In Lua, you have to first define any variables (functions are variables too) before you can use them, but if you really need to use a variable before you can define it (and don't worry, there are a lot of cases where this kind of thing is needed) you can forward-define the variable like so:
local foo --// Define the variable, it's going to be nil for now
local function bar ()
print(foo + 2) --// We use the variable "foo" assuming it is a number, even though it's still nil
end
foo = 3 --// We define the variable later
bar() -->> 5
Note that you do not have to do this if you are using global variables, but using them is a bad habit and you should always, when possible, use local variables.
3057 posts
Location
United States of America
Posted 17 August 2014 - 11:20 PM
It is still not fixed, now the error occurs at the menustate[select].action(), attempt to call nil
Uhm… Please post the full code. Some of the actions are *not* defined here, which might be the problem.
Edit: I'm not sure if this is related to your question or not, but this may help you… I wrote a quick little "menu" code that is pretty simple to use. Simply give the function a few strings, and the user will be able to choose between them.
Spoiler
function menu( ... )
local tArgs = { ... }
local maxLen = 0
for k, v in ipairs( tArgs ) do
if #v > maxLen then maxLen = #v end
end
local maxx, maxy = term.getSize()
centerx = maxx/2
centery = (maxy/2) + #tArgs
local yValue = {}
term.clear()
for i = 1, #tArgs do
term.setCursorPos( centerx - (#tArgs[i]/2), centery - i )
yValue[ i ] = centery - i
term.write( tArgs[ i ] )
end
local selected = 1
while true do
term.setCursorPos( centerx - (maxLen/2) - 2, yValue[ selected ] )
term.write( "[" )
term.setCursorPos( centerx + (maxLen/2) + 2, yValue[ selected ] )
term.write( "]" )
local event, key = os.pullEvent( "key" )
local old = selected
if key == 200 and tArgs[ selected + 1 ] then
selected = selected + 1
elseif key == 208 and tArgs[ selected - 1 ] then
selected = selected - 1
elseif key == 28 then
return tArgs[ selected ]
end
term.setCursorPos( centerx - (maxLen/2) - 2, yValue[ old ] )
term.write( " " )
term.setCursorPos( centerx + (maxLen/2) + 2, yValue[ old ] )
term.write( " " )
end
end
Example of use:
local option = menu( "main", "control", "command", "lights" )
if option == "main" then
--#etc.
elseif option == "control" then
--#etc.
end
Edited on 17 August 2014 - 11:49 PM