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

Custom Error's Using pcall()

Started by Henness, 21 January 2014 - 12:15 PM
Henness #1
Posted 21 January 2014 - 01:15 PM
I'm trying to add an error menu to my gui program so if it runs a program that results in an error then it will print the error in a new menu.

I cant seem to make a custom error message for if the program is being used wrong. I don't really know how to use pcall() can you even return a custom error message back to it?

http://pastebin.com/QpfucDe1

GUI program:

  bError, sError = pcall(shell.run, "program name", "variable")
  if not bError then
	menustate = "error menu"
  else
	menustate = "main menu"
  end

Program ran by GUI program:

   if turtle.getFuelLevel() > 0 then
	return false, "Error, there must be fuel in the turtle!"
   end
also tryed

   if turtle.getFuelLevel() > 0 then
	return "Error, there must be fuel in the turtle!"
   end
Edited on 21 January 2014 - 12:20 PM
CometWolf #2
Posted 21 January 2014 - 02:29 PM
if an error is raised within a pcall, it returns false and the error message. If the function returns without erroring, it returns true aswell as any variables returned. To make your own error messages, you can either use the error function

error("Error message here!")

or assert, which raises an error if the first argument is false

assert(boolean,"Error message here!")
Assert is pretty much error with an if not condition.

http://www.lua.org/pil/8.3.html pcall
http://www.lua.org/pil/8.4.html assert
Edited on 21 January 2014 - 01:30 PM
Lyqyd #3
Posted 21 January 2014 - 02:30 PM
Shell.run doesn't return any of the values returned by whatever it ran.
Henness #4
Posted 21 January 2014 - 02:56 PM
So would it look like this?

   if turtle.getFuelLevel() > 0 then
	    return assert(false,"Error, there must be fuel in the turtle!")
   end
or

   if turtle.getFuelLevel() > 0 then
	    assert(false,"Error, there must be fuel in the turtle!")
   end
robhol #5
Posted 21 January 2014 - 03:02 PM
The return value from assert is also of no particular interest, the entire point is that it errors if the assertion doesn't work out- ie. evaluates to false.
Henness #6
Posted 21 January 2014 - 03:46 PM
Okay so this is a basic version of what I have.
But this does not seem to be working, it doesnt print the error.

Main program:

bError, sError = pcall(shell.run, "testprogram", "variable")
if not bError then
   print(sError)
else
   -- continue
end

Test program:

error("This is an Error")
H4X0RZ #7
Posted 21 January 2014 - 03:53 PM
Remove the 'not' before bError
Henness #8
Posted 21 January 2014 - 04:17 PM
That isn't working either and I'm fairly sure it's supposed to have the "not" because if it errors bError returns false.

it just prints false.
Lyqyd #9
Posted 21 January 2014 - 04:20 PM
Try catching the return values in a table and see if any of the indices contain anything interesting.
Henness #10
Posted 21 January 2014 - 04:34 PM
What's the best way to do that, I haven't used lua for a while.
Henness #11
Posted 21 January 2014 - 05:20 PM
Scratch that,

only two values were returned

first was true and second was false which doesn't seem to make sense because the first value should be false and the second should be a string.
Henness #12
Posted 22 January 2014 - 04:35 AM
I have been thinking about this all day, and just before I was about to go to bed I thought. Maybe the pcall is returning true because the shell.run is completing without errors but the part that is acualy erroring is whats inside the shell.run. Can anyone conferm this is what's happening? And if so can I put a pcall inside the shell.run or is the another way of doing it.
Edited on 22 January 2014 - 03:40 AM
Bomb Bloke #13
Posted 22 January 2014 - 04:54 AM
That indeed sounds a lot like what Lyqyd was saying above.

Edit: I've not played with them, so I'm not even sure they're available within ComputerCraft, but I suspect you want something along the lines of dofile() or loadfile().
Edited on 22 January 2014 - 03:57 AM
Henness #14
Posted 22 January 2014 - 05:15 PM
That indeed sounds a lot like what Lyqyd was saying above.

Edit: I've not played with them, so I'm not even sure they're available within ComputerCraft, but I suspect you want something along the lines of dofile() or loadfile().

Thanks Bomb, that works first time I have ever seen dofile and loadfile there isn't much info on them either. I think that the shell.run should be modified to return values :/
Lyqyd #15
Posted 22 January 2014 - 05:31 PM
dofile and loadfile are available in ComputerCraft. os.run uses loadfile to run programs.
Henness #16
Posted 22 January 2014 - 07:32 PM
os.run() seems work for running the program but every error is returned as attempt to call boolean. Because its not storing a string in sError. (I think)


bError, sError = pcall(os.run({}, "advancedorefinder", "orefinder.save"))

Loadfile() seems to work too but if I use it then The program that it runs cant use shell.getRunningProgram() :(/>
Edited on 22 January 2014 - 06:39 PM
Lyqyd #17
Posted 22 January 2014 - 07:42 PM
Of course it can, you just have to set the environment correctly for it. Read through shell and bios.lua and watch for how it sets the environment for the programs it runs.
Henness #18
Posted 22 January 2014 - 09:16 PM
Im not quite sure how I'm supposed to set up the environment. Im looking in shell and from what I can see shell.getRunningProgram() isn't going to work if I run a program with loadfile().

Because when you run a program with shell.run it adds the program to a new spot at the end of a table with tProgramStack[#tProgramStack + 1] = sPath then when you call shell.getRunningProgram() it just returns the last variable in the table

Unless your talking about os.run()
Edited on 22 January 2014 - 08:56 PM
CometWolf #19
Posted 23 January 2014 - 12:15 AM
Why do you need shell.getRunningProgram? Don't you already know the file path prior to using os.run on it anyways?
Lyqyd #20
Posted 23 January 2014 - 12:59 AM
You didn't look very hard in shell.

Lines 11-13:


local tEnv = {
    ["shell"] = shell,
}

Line 32 of shell, in the shell.run function:


local result = os.run( tEnv, sPath, ... )

And lines 364-367 of bios.lua:


setfenv( fnFile, tEnv )
local ok, err = pcall( function()
    fnFile( unpack( tArgs ) )
end )

You can glance through the files for more context on what the variable names are, but tEnv happens to be consistently named, so that part should be pretty easy to figure out.
Henness #21
Posted 23 January 2014 - 05:28 AM
yea I have no idea I dont even know what a environment is. I looked is up but still doesn't make sense to me. Im just not gonna bother with shell.getRunningProgram()
CometWolf #22
Posted 23 January 2014 - 05:38 AM
The enviroment is where all the variables are stored. They're just tables which are looked through when looking for a variable. If you try to call a variable not in the current enviroment you'll get an attempt to call nil, unless you use some meta table trickery. When you're running your scripts, the enviroment in use is usually _G, which is the global enviroment.