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

How to get current path for file

Started by Mirodin, 25 May 2016 - 01:35 PM
Mirodin #1
Posted 25 May 2016 - 03:35 PM
Hey guys,

it is a long time since I last messed around with Minecraft and therefore CC. Some days ago I started implementing a UI framework which is inspired by the box design (HTML, Qt, …). Therefore I have multiple files which contain one UI element each and I want to run a init.lua file via dofile() from my normal scripts to get all elements loaded.

Maybe my english is not good enough to understand the CC APIs but I can not figure out a way to use relative paths from the init file for the load process. At the moment it looks like this:


local modules = {
	"border",
	"option",
	"optionmenu",
	"window"
}
local pwd = ??? <--- How do I get the current directory of the init file?

-- Load a UI element from file
local function loadFile( fileName )
	return dofile( fs.combine( pwd, fileName ) )
end

local function init()
	local elements = {}
	for _, e in ipairs( modules ) do
		elements.insert( loadFile( e..".lua" ) )
	end
	return elements
end

init()

My "normal" approach is to use something like this, but that only works if I run the init script directly which is not what I want:

local pwd = fs.getDir( shell.getRunningProgram() )

I hope some of you guys kann help me with this, I'd really appreciate that.
Cheers Mirodin
Edited on 25 May 2016 - 01:37 PM
Dragon53535 #2
Posted 25 May 2016 - 03:48 PM
I'm assuming that it doesn't work if you use loadfile? In which case you probably need to set the environment table of the loaded file to include the shell api.
Mirodin #3
Posted 25 May 2016 - 03:56 PM
I'm assuming that it doesn't work if you use loadfile?

Yes, you are right, it fails around line 20 (the one that calls loadfile). I do get the basic idea of your suggestion but I have no clue how I would do that :rolleyes:/>
Bomb Bloke #4
Posted 25 May 2016 - 04:12 PM
ComputerCraft scripts use an environment table that can access _G (via a metatable), but is not _G. Global variables (like the pointer to the shell API) go into these custom environment tables, not into _G. dofile() uses _G so scripts executed through dofile() can't access the shell API.

Instead of:

dofile("filename")

… use:

loadfile("filename", getfenv())()

This sets the loaded function's environment to whatever the current environment is before execution.

Though you only need to do things this way if you want to capture something returned by the loaded function. If you don't care about return values, just use shell.run() instead.
Edited on 25 May 2016 - 02:14 PM
Mirodin #5
Posted 30 May 2016 - 06:38 AM
Thanks for the explanation :)/>

Unfortunately this does not solve my problem since the init file is already called via dofile. My idea was to "import" the framework via dofile in my script and the init file handles the dofile actions for all modules (I hope this makes sense).

Cheers
Mirodin
Bomb Bloke #6
Posted 30 May 2016 - 09:17 AM
Unfortunately this does not solve my problem since the init file is already called via dofile.

… and I'm telling you to change that. :|
Mirodin #7
Posted 30 May 2016 - 10:07 AM
Ok, sorry to bother you again but I do not get it :(/>

My "main" file calls

loadfile("/lib/gui/init.lua", getfenv())()

Where the init file is:


local modules = {
    "border",
    "option",
    "optionmenu",
    "window"
}
local pwd = fs.getDir( shell.getRunningProgram() )
print("pwd:"..pwd)

-- Load a UI element from file
local function loadFile( fileName )
    print(pwd, "..", fileName)
    return dofile( fs.combine( pwd, fileName ) )
end

local function init()
    local elements = {}
    for _, e in ipairs( modules ) do
	    elements.insert( loadFile( e..".lua") )
    end
    return elements
end

init()

But I still get the message in line 19 that the file was not found :unsure:/>
Bomb Bloke #8
Posted 30 May 2016 - 10:17 AM
That tells you that you've successfully obtained access to the shell API (or you'd've got an "attempt to index nil" on line 7 instead), but the file can't be found when line 13 attempts to return to 19.

So: What gets printed before that?
Mirodin #9
Posted 30 May 2016 - 10:28 AM
Hi Bomb Bloke,

thank you for your patience, I must seem quite stupid :D/>

Well the thing is, I never had the problem with "attempt to index nil". I just replaced (for testing) the loadfile call in my main script with dofile (and without getfenv) with the exact same result. So I already had access to the shell API with dofile but I do not get the thing working where the init script calls the module files relative to its own position. I hope my explanation makes sense :rolleyes:/>

Line 12 prints "..ui.lua".
Edited on 30 May 2016 - 08:29 AM
Bomb Bloke #10
Posted 30 May 2016 - 10:45 AM
Ah, righto.

The shell is telling you that the current script is running from the root of the computer's drive (which is technically true - you didn't shell.run() your init script, so shell.getRunningProgram() has no reason to think the init script is "running").

I guess you'll just have to pass in the path when you call init:

local initPath = "/lib/gui/init.lua"
loadfile(initPath , getfenv())(fs.getDir(initPath))

local pwd = ...

It's either that or change the working directory:

local initPath, curPath = "/lib/gui/init.lua", shell.dir()
shell.setDir(fs.getDir(initPath)) 
loadfile(initPath , getfenv())()
shell.setDir(curPath)

local pwd = shell.dir()

thank you for your patience, I must seem quite stupid :D/>

Not at all.
Mirodin #11
Posted 30 May 2016 - 10:58 AM
Ah, that does the trick, thanks man that was awesome :D/>