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

[Lua][Error] shell.run() doesn't work

Started by diegodan1893, 22 October 2012 - 04:55 PM
diegodan1893 #1
Posted 22 October 2012 - 06:55 PM
I was making a function that run a program, but I get file:58: attempt to call a nil file:56:attemp to index ? (a nil value), in that line there is the function shell.run(path.."/"..fs.getName(path))

Here is the code:

function run(path) --path must be a dir
if fs.isDir(path) then
  if fs.exists(path.."/info.ini") then
   hRead = fs.open(path.."/info.ini", "r")
   if hRead.readLine() == "icon = {" then
	icon = {}
	for i = 1, 4, 1 do
	 local a = hRead.readLine()
	 table.insert(icon, a)
	end
	local b = hRead.readLine()
	if string.sub(b, 1, 7) == "name = " then
	 name = string.sub(b, 8)
	else
	 name = fs.getName(path)
	end
	local c = hRead.readLine()
	if string.sub(c, 1, 9) == "author = " then
	 author = string.sub(c, 10)
	else
	 author = "Please write an author in info.ini"
	end
   end
   hRead.close()
  end
  gui.splash(icon, name, author)
  shell.run(path.."/"..fs.getName(path)) --Here is the error
end
end

I still getting the error even if I write shell.run("ProgramFiles/TestProgram/TestProgram"). If I run manually the program in CraftOS it works well, so the program works itselft, but I can't run it with shell.run().

I call the function with file.run("ProgramFiles/TestProgram") and in TestProgram folder there are 2 files: "TestProgram" and "info.ini". The 2 files works well themselves.

What is the problem?



Sorry for my bad english
Doyle3694 #2
Posted 22 October 2012 - 07:00 PM
Please post your whole code
diegodan1893 #3
Posted 22 October 2012 - 07:12 PM
Please post your whole code

It's a lot (1053 lines), what do you need the part where I call the function file.run()?
PixelToast #4
Posted 22 October 2012 - 07:13 PM
post the WHOLE code, and tell us where the error is
Cloudy #5
Posted 22 October 2012 - 07:41 PM
fs.getName() isn't a function.
Lyqyd #6
Posted 22 October 2012 - 09:07 PM
Then what is it, Cloudy? http://computercraft.info/wiki/index.php?title=Fs_(API)

Try using fs.combine rather than manually concatenating the string. Also, check the final string using a print() before trying to shell.run it.
Cloudy #7
Posted 22 October 2012 - 09:17 PM
Then what is it, Cloudy? http://computercraft.info/wiki/index.php?title=Fs_(API)

Try using fs.combine rather than manually concatenating the string. Also, check the final string using a print() before trying to shell.run it.

I'd tell him a replacement function if I knew what his fs.getName() was supposed to do :)/>/>
diegodan1893 #8
Posted 22 October 2012 - 09:26 PM
post the WHOLE code

Ok, here is the whole code:
https://github.com/d...er/YdedOS/Files

EDIT: I forget to say where is the error, it is in ydedOS_API/file, in line 56
diegodan1893 #9
Posted 22 October 2012 - 09:28 PM
Then what is it, Cloudy? http://computercraft.info/wiki/index.php?title=Fs_(API) Try using fs.combine rather than manually concatenating the string. Also, check the final string using a print() before trying to shell.run it.

I already print the string and it was right. I will try with fs.combine().
ChunLing #10
Posted 22 October 2012 - 09:33 PM
You're doubling the last component of your path, and there isn't a file by that name. Check using fs.exists on that string you made.
diegodan1893 #11
Posted 22 October 2012 - 09:40 PM
You're doubling the last component of your path, and there isn't a file by that name. Check using fs.exists on that string you made.

I did this:

local programPath = fs.combine(path, fs.getName(path)..".lua")
if fs.exits(programPath) then
shell.run(programPath)
else
gui.dialogBox("Error","File doesn't exits.",{"  OK"})
end

But the file exits and I still getting the same error but in the line 57 (the same line)
ChunLing #12
Posted 22 October 2012 - 09:49 PM
"fs.exits(programPath)" ~= "fs.exists(programPath)"
diegodan1893 #13
Posted 22 October 2012 - 10:09 PM
"fs.exits(programPath)" ~= "fs.exists(programPath)"

You're right, fixed but it still the same :)/>/>
Cloudy #14
Posted 22 October 2012 - 10:52 PM
fs.getName() isn't a function.
Lyqyd #15
Posted 22 October 2012 - 11:54 PM
fs.getName() isn't a function.

Is this confirmation that the wiki documentation for the fs API is incorrect? I am not at home and cannot test this. Was this function removed? Did the authors of the wiki page make it up?
ChunLing #16
Posted 23 October 2012 - 12:54 AM
No, it's a function, and it works, but it doesn't maybe do what it's being used for here. fs.getName() just returns the last part of a string representing a path. The path doesn't have to be real or anything.
ChunLing #17
Posted 23 October 2012 - 12:57 AM
And blarg, I just thought of something. You can't run shell.run on a path unless the path starts with "/". shell.run("ProgramFiles/TestProgram/TestProgram") should be shell.run("/ProgramFiles/TestProgram/TestProgram"). I ran into this ages ago and completely forget it because it's so minor.
diegodan1893 #18
Posted 23 October 2012 - 06:55 PM
No, it's a function, and it works, but it doesn't maybe do what it's being used for here. fs.getName() just returns the last part of a string representing a path. The path doesn't have to be real or anything.

I use fs.getName() because in /ProgramFiles/ProgramName/ there are 2 files: ProgramName.lua and info.ini. This function is called with the path of the dir so I need to double the last part of the path and add ".lua" to the end to make it work.

And blarg, I just thought of something. You can't run shell.run on a path unless the path starts with "/". shell.run("ProgramFiles/TestProgram/TestProgram") should be shell.run("/ProgramFiles/TestProgram/TestProgram"). I ran into this ages ago and completely forget it because it's so minor.

I tried that but it doesn't work ^_^/>/>
diegodan1893 #19
Posted 23 October 2012 - 07:02 PM
I discovered that the problem is that you can't call shell.run() in an API. If I call from another program file.run(path) it attempt to index ? (a nil value) but if I call the function from the file "file" with run(path) it works well. Maybe a computercraft bug?
Lyqyd #20
Posted 23 October 2012 - 07:53 PM
No, the shell "API" doesn't load until after the actual APIs, so you would need to manually load your API file with os.loadAPI() in the startup if you absolutely must use shell.run. os.run() may work instead.
diegodan1893 #21
Posted 23 October 2012 - 08:02 PM
No, the shell "API" doesn't load until after the actual APIs, so you would need to manually load your API file with os.loadAPI() in the startup if you absolutely must use shell.run. os.run() may work instead.
I already load my api with os.loadAPI("ydedOS_API/file") and all the other function work well. It's only shell.run() that doesn't work.
faubiguy #22
Posted 23 October 2012 - 08:08 PM
The problem is that os.loadAPI doesn't add the shell API to the environment that APIs are loaded in (the shell API isn't defined at the time os.loadAPI is). shell.run adds the shell API to the environment of any program that it runs, so programs run from the shell, or run by another program using shell.run, will have access to the shell API. APIs loaded with os.loadAPI, and programs run with os.run won't (You can specifically add the shell API to the environment of programs run with os.run, but it doesn't do it automatically, unlike shell.run)

EDIT: As a workaround, you can do _G.shell = shell before loading the API. This will add shell to the global environment, which the API environments inherit from.
diegodan1893 #23
Posted 23 October 2012 - 09:03 PM
The problem is that os.loadAPI doesn't add the shell API to the environment that APIs are loaded in (the shell API isn't defined at the time os.loadAPI is). shell.run adds the shell API to the environment of any program that it runs, so programs run from the shell, or run by another program using shell.run, will have access to the shell API. APIs loaded with os.loadAPI, and programs run with os.run won't (You can specifically add the shell API to the environment of programs run with os.run, but it doesn't do it automatically, unlike shell.run)

EDIT: As a workaround, you can do _G.shell = shell before loading the API. This will add shell to the global environment, which the API environments inherit from.

Thanks it works with os.run({},programPath)