Murga-Projects Forums
Function to return the current directory - Printable Version

+- Murga-Projects Forums (http://www.murga-projects.com/forum)
+-- Forum: Project Forums (/forumdisplay.php?fid=1)
+--- Forum: MurgaLua - General (/forumdisplay.php?fid=2)
+--- Thread: Function to return the current directory (/showthread.php?tid=109)


Function to return the current directory - iGame3D - 07-15-2007 07:20 PM

This is what I'm trying to do:
launch murgaLua,
discover the folders and files in the same directory
return their paths after selecting their file/folder names from menus.

I can fill them menus and return the file names fine..but their long path??
ie, "/volumes/hard drive/somefolder/etc/etc/etc/thefile.lua"

How to return that based on where murgaLua is currently running from?


RE: Function to return the current directory - mikshaw - 07-16-2007 02:12 AM

I have had the same desire, and so far have not found a reasonable solution. For an application that would be targeted to Linux systems, I have wrapped up the lua script inside a shell script, having the shell commands check the directory and then send it to murgaLua as a variable or commandline parameter, but it's not very portable. Even that requires some extra work, since you also have to check whether the file is actually the script or just a link to the script.

EDIT: There must be something within Lua that can be used for this purpose. It already is aware of where the script is, considering it uses relative paths for dofile(), so I guess the question must be where does it store that info?


RE: Function to return the current directory - mikshaw - 07-16-2007 03:29 AM

Here's one possible solution. It works in Unix systems, but I think a forward slash will not translate to Windows. The gsub function will probably need to be modified or replaced for something more universal, but the main point is that arg[0] stores the full path to the script.

Code:
dirname=string.gsub(arg[0],"(%/.*)%/.*","%1")
print(dirname)


EDIT:
Again, this is probably not the cleanest or most useable code, but it might work...

Code:
function dirname(f)
if not f then f=arg[0] end
local s
if murgaLua.getHostOsName() == "windows" then s="\\" else s="/" end
local dirname=string.gsub(f,"(.*"..s..").*","%1")
return(dirname)
end


The function was designed so that it would work on the current script if no arguments are given, and can also be used on other files similar to the dirname command in linux (except this one keeps the trailing slash)


RE: Function to return the current directory - mikshaw - 07-17-2007 03:32 AM

Soooo.....does it work?
Anyone have any feedback on whether (and how) it can be made better, more efficient/portable?
The dirname variable on my local copy has been changed to 'd' to avoid confusion with the function name, but apart from that I'm not sure how to improve it. Also still not sure if it works on Windows or Mac.

The gsub grabs everything up to and including the last slash or backslash in the filename. I assume that's pretty much the same thing that the dirname command does, since both appear to simply work on a given string rather than check whether or not it's actually an existing file or directory. The fl_filename_ext() function seems to work the same way.


RE: Function to return the current directory - iGame3D - 07-17-2007 01:51 PM

In my experiments I didn't get the result I was looking for.
I don't think I'm passing scripts the way you are.
What do your results look like?

For what I was looking to do I should be able to export the current application path to  a variable and retrieve it from the system via the running murgaLua.

I'll share the results soon although they are for OS X.

Did I read John has plans for compiling scripts into executable murgaLua apps?


RE: Function to return the current directory - mikshaw - 07-17-2007 11:34 PM

As I said I don't have any idea if it works on Windows or Mac, but it *should* do the same on Linux and MacOS...grab everything from the beginning of a string to the final slash (i haven't thought to test with a filename without a slash...i'll need to do that next).

Usage:
my_dir=dirname() --for the dirname of the current script
or
my_other_dir=dirname(some_other_file) -- for the dirname of an external file

If your script is /usr/local/bin/my_script.lua, the first example should return "/usr/local/bin/"
You could also use my_dir=dirname(arg[0]) for the first example, but that's redundant.

Quote:
Did I read John has plans for compiling scripts into executable murgaLua apps?

I think you might already have that ability with Lua proper, but I'm not sure if non-Lua stuff would be supported. As far as I can tell, it looks like something John put on his List Of Things To Explore.


RE: Function to return the current directory - iGame3D - 07-18-2007 02:53 PM

Ok I was initially getting a blank when checking dirname at the start of a script, once the script was running it returned the path of the script, but ideally whats needed is the path to the murgaLua executable.

What I have is an application bundle that launches murgaLua, special thanks to Marielle for going through the Xcode tutorial and developing it. Here's what it looks like at the desktop, a peek inside the package, and running.


The 'main.scpt' is an Applescript that originally simply launched murgaLua and a file called script.lua. I keep this script seperate from Lua scripts as it truly belongs to the Applescript executable "applet" and not to murgaLua.

In the script I added a step to write the current application path to a file which
murgaLua will load and set a global variable "bundleroot"
You can see the Applescript here

It generates file bundleroot.lua:

Code:
bundleroot='/ig3d_mac_xcode/build/Development/murgaPlayer/murgaPlayer.app/'
dofile(bundleroot..'Data/Scripts/start.lua')


start.lua at its most basic:

Code:
if bundleroot==nil then os.exit() end
gameroot=bundleroot
dofile(gameroot.."Data/Scripts/console.lua")
Fl:run();


Console.lua loads the directory contents of Data/Scripts/ into a menu
and the callback of that menu feeds the whole path of the chosen
script to a dofile command.  The console script also re-directs all print
commands into the console output so I don't have to find another app to
see what is happening.

iGame3D has an engine level method of finding the path to itself:

Code:
bundleroot=getSceneInfo(IG3D_ROOT) --  retrieves application path

--- by default I script in this variable immediately after:
gameroot=bundleroot

--bundleroot doesn't get changed , gameroot can be set by the user:

gameroot="/a_path_that_contains_Data_folder/"
setSceneInfo(IG3D_ROOT,gameroot)


Now I have somewhat the same functionality in a standalone murgaLua solution
and a fairly snappy murgaLua script launching mechanism.

Now to figure out dynamic submenus and clean up that scripts folder.


RE: Function to return the current directory - mikshaw - 07-18-2007 03:22 PM

The dirname function is not as reliable as I had hoped. It worked fine with my preliminary test, but when testing a few possible variations (such as running the script in the current directory) it failed quickly. I want to make it work dependably for my own uses as well, so it'll be something I'll look into further sometime in the next few days. Might just need a little tweaking, or might need to be rewitten.

Dynamic submenus look terribly complicated. I was looking at the menu stuff in Erco's FLTK cheat page last night, and nothing was making much sense to me =op
http://seriss.com/people/erco/fltk/

EDIT: it seems that the function was doing what it should; my problems were coming from trying to use the result in a way it's not intended...namely, trying to dofile() with a filename path other than ./
I assume there's a way to modify the dofile/require search path, but i haven't looked into it yet.

EDIT2: Of course I assumed incorrectly again. The error was caused by the script that was being loaded with dofile(). Since it required files found in a subdirectory, I needed to pass the base directory on to it. Seems to work again.

On the subject of dynamic menus, it seems to be a little bit easier than I thought, assuming you keep track of the number which represents each menu item. I'm thinking there must be a way to utilize the item's label, but haven't experimented with that yet (maybe the menu is a table?).
The Fl_Menu_Item documentation contains a list of constants that apply to various flags, which can be modified with Fl_Menu:mode(item_number,flag). Zero is not listed, but it refers to the active state of an item. It seems you can use other Fl_Menu methods to remove, rename, and replace items, but that's something else I haven't looked into yet.


RE: Function to return the current directory - mikshaw - 07-20-2007 09:01 AM

An update on the dynamic menus.
You can use Fl_Menu_Bar:find_item(my_menu_item_string) to get a pointer to a specific menu item, which is much more pleasant than trying to determine the index of a particular menu item.
I still have no idea how to use Fl_Menu_Item, but this seems to work with menu items created with my_menu:add(my_menu_item_string).

Code:
my_menu=fltk:Fl_Menu_Bar(0,0,window_width,30)
my_menu:add("&File/open")
my_menu:add("&File/save")
save_item=my_menu:find_item("&File/save")

Now you can disable the "save" item when it's not needed:

Code:
save_item:deactivate()

This can also be used to perform (most?) other actions that can be applied to the Fl_Menu_ class, such as replacing/renaming items. The only things i've tested so far is changing font properties and item labels.


RE: Function to return the current directory - mikshaw - 07-23-2007 01:39 AM

I got an opportunity to see murgaLua work on a Windows XP machine, and the function works there.

Windows has some other dumb issues, though, like no preset "HOME" environment variable and no toleration for dotfiles, which pose an unnecessary problem for several of my scripts.


RE: Function to return the current directory - JohnMurga - 07-23-2007 06:09 PM

If I remember rightly Windows has a "USERPROFILE" variable or something ...

You can use the murgaLua.getHostOsName() to decide whether to use it ...

Cheers
JohnM


RE: Function to return the current directory - mikshaw - 07-24-2007 02:11 AM

I don't know. I recall only seeing "TMP" and "TEMP" as user variables. Maybe the others are there but simply not available for modification by the user (XP Home).
I'll get a chance to look at it again tomorrow or later on today.

It may be a case where I just write a generic function to include with all cross-platform scripts.
The function would check the host os and adjust various parts of the script accordingly.


RE: Function to return the current directory - mikshaw - 07-24-2007 09:36 AM

Those two variables were simply the only two listed under system properties (why, i don't know).
I used the "set" command to display the environment and found a few that will be helpful. I just hope the variable names are the same from one Windows version to another.
Here are some on Windows XP that look like they might be useful:
APPDATA=C:\Documents and Settings\mik\Application Data
HOMEPATH=\Documents and Settings\mik
OS=Windows_NT
USERNAME=mik
USERPROFILE=C:\Documents and Settings\mik

No idea why HOMEPATH and USERPROFILE are both used


RE: Function to return the current directory - JohnMurga - 07-24-2007 05:03 PM

Hey,

HOMEPATH isn't reliable, USERPROFILE is ... On my machine for instance HOMEPATH isn't set.

Cheers
JohnM


RE: Function to return the current directory - mikshaw - 07-24-2007 11:38 PM

Thanks. That will definitely help.


RE: Function to return the current directory - JohnMurga - 07-25-2007 12:58 AM

I did some research, I am thinking that murgaLua probably works on Win98, however on Win98 you wouldn't get things like "APPDATA" or "USERPROFILE" ... And maybe not even "OS".

You will get things like WINDIR, etc ...

Cheers
JohnM


RE: Function to return the current directory - mikshaw - 07-25-2007 01:20 AM

Well then, I guess I won't be relying much on os.getenv() for cross-platform apps =op
I was really hoping that this particular function would be a lifesaver when trying to do things like reading/writing configuration files. Unfortunately it seems that the developers of Windows have little concept of consistency.

But at least OS X is Unix-based (and includes the basic GNU utilities?), so I doubt there will be many portability problems to that from Linux =o)


RE: Function to return the current directory - JohnMurga - 07-27-2007 06:49 PM

Incidentally, the new build will have THIS :

http://www.keplerproject.org/luafilesystem/manual.html#reference

Which might make your life easier.

Cheers
JohnM


RE: Function to return the current directory - mikshaw - 07-27-2007 10:50 PM

O_O
Sweet!
I tried unsuccessfully to install this for Lua proper not long ago...I think at the time it was incompatible with Lua 5.1 or something...can't recall...

Some of these functions are things I believe should have been a part of Lua already, or at least would be if it was my project.


RE: Function to return the current directory - JohnMurga - 07-28-2007 12:09 AM

mikshaw Wrote:
Some of these functions are things I believe should have been a part of Lua already, or at least would be if it was my project.


This comes up a lot, people don't realize that the Lua core is meant to be as portable as possible, and this means that they don't implement some things considered as basic for many because they cannot guarantee that Lua will compile on all platforms.

I don't have this problem as I am clearly targeting murgaLua at those platforms supported by FLTK and LuaSocket.

Cheers
JohnM


RE: Function to return the current directory - iGame3D - 08-01-2007 12:40 AM

Now that the murgaLua directory reading functions have changed to LFS,
how do we filter directories for folders and files?


RE: Function to return the current directory - mikshaw - 08-01-2007 06:57 AM

There is an lfs example included (examples/tests), which looks like it is the same one distributed with lfs (which is also found in the 3rd-party directory).
The first function in that file appears to contain a test of this nature:

Code:
if attr.mode == "directory" then


Now I haven't tried this yet, but going by that example, and the lfs documentation, the table created by lfs.attributes ("attr" in this example) contains the attribute named "mode", which returns the string file, directory, link, socket, named pipe, char device, block device or other


RE: Function to return the current directory - mikshaw - 08-01-2007 08:21 AM

Here's a more direct way to do it.
The docs are vague in specifying which is which, but one way of using fls.attributes creates a table and the other way does not. I think this method does not:

Code:
print(lfs.attributes(filename).mode)




RE: Function to return the current directory - iGame3D - 08-01-2007 10:42 AM

Hmm I thought I posted this code before going out

Code:
cDirectory=lfs.currentdir()


function listFolders(path)
local folderList=""
    for file in lfs.dir(path) do
        
        if file ~= "." and file ~= ".." then
            local f = path..'/'..file
            local attr = lfs.attributes (f)
            assert (type(attr) == "table")
             if attr.mode == "directory" then
              
             folderList=folderList..file.."\n"
             end  
        end
    end
    return folderList
end

function listFiles(path)
local fileList=""
    for file in lfs.dir(path) do
        if file ~= "." and file ~= ".." then
            local f = path..'/'..file
            local attr = lfs.attributes (f)
            assert (type(attr) == "table")
             if attr.mode == "file" then
              fileList=fileList..file.."\n"
              end  
        end
    end
    return fileList
end


a=listFolders(cDirectory)
print(a)
b=listFiles(cDirectory)
print(b)




RE: Function to return the current directory - mikshaw - 08-01-2007 12:45 PM

That's pretty cool.
Personally I would combine the two functions into one, considering they are almost identical.

A warning:
It chokes if you have a broken link in your cDirectory. I spent too long trying to figure that one out =o)

EDIT: Here a fix for the broken link (and any other file that can't be read):

Code:
for file in lfs.dir(path) do
        local readtest=io.open(file)
        if file ~= "." and file ~= ".." and readtest then
            readtest:close()


EDIT2: Oddly enough, it still works for files that have no read permission for the user, even without the readtest.
So I'm guessing a broken link is a special case.