Thread Tools Display Modes
09-12-18, 01:44 AM   #1
doofus
A Chromatic Dragonspawn
Join Date: Feb 2018
Posts: 158
Include files

Hello guys

I have a rather large addon which is in a single .lua file, and it has about 15,000 lines and it is hard to navigate. Because lua variables are global I precede them with "local" so they can only be seen in my own file and avoid namespace issues with other addons. Because everyting is in one .lua file I do not have to worry about declarations of functions and variables and only make sure I declare them in the right order.

I want to split this large .lua file into smaller files just for ease of editing purposes.

In C/C++ I would simply do, #include "file1.c". With the "#include" the C compiler simply merges source files together as one might do by hand. file1.c would not compile on its own of course, it is just a convenient way to split a large source code file into chunks without worrying too much about externs and linkage.

That is in the C world. Is there a way to do the same in wow's lua?

thanks
  Reply With Quote
09-12-18, 03:51 AM   #2
VincentSDSH
Non-Canadian Luzer!
 
VincentSDSH's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2006
Posts: 350
In short: No, you can't create a merge in that way.

If you break things out into individual files they have their own context (e.g, locals are local to that space, etc) which is a good thing for managing large amounts of code and simplifies design and debugging.

Those file segments have access to as shared namespace that is passed to each segment -- to capture it, place " local addonName, nameSpace = ... " (the first var is the string-name of the addon, the second is the namespace table) at the top of each file.

If you just want to break things apart, store your addon-global vars in the namespace table, then you can declare the file-order in the .toc file, which loads and executes in order, iirc.

Not sure why you'd want to go through that rather than use they hyper-friendly lua function but it might get you past one-massive-why-would-you-do-that-to-yourself-file problem.
__________________
AddonsExecutive Assistant User Configurable To-Do ListLegible Mail Choose the Font for Your Mail
  Reply With Quote
09-12-18, 05:51 AM   #3
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,892
You can easily split them into several files.

As Vincent said, at the top of each file put

local addonName, addonData = ...

This allows each access to the addon wide data table


Function declarations will need to be defined before they are used but I think you can forward declare them where necessary.


You then specify the files in the order they need to be.


For example:
A toc file could contain something as follows:

Code:
file1.lua
file2.xml
file3.xml
file3.xml could then contain this


Code:
<UI xmlns="http://www.blizzard.com/wow/ui/"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
    <Include file = "Core.xml" />
    <Include file = "Features.xml" />    
</UI>
Core.xml could then contain this
Code:
<UI xmlns="http://www.blizzard.com/wow/ui/"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
    
    <!-- Items everything else requires access to -->
    <Include file = "Utils/Utils.xml" />
    <Include file = "Localization/Localization.xml"/>
    <Include file = "Options/Options.xml" />
</UI>

As you can see each file is included in the order it needs to be processed. Later files will call functions contained in earlier specified files etc.

The Utils.xml will hold a list of files that have individual unique but addon accessible functions
The Localization.xml will hold a list of localization related files which will include one that has an addon wide table to hold the active translation values used by other files
The Options.xml will hold a list of options related files which may need access to the localization files

Further core files can be added in the Core.xml file and the files listed in Features.xml will have access to everything that was included before it.

If the file you need is a code file you can use
<script file = "file1.lua" />

to add it to the list of files to load inside an xml file.

This is the only way I know of to 'include' files in a specified order

Here is an example of a frame that requires access to functions in a source file but is also used in another source file. For example if the frame display is controlled. Most of the time though only first first file is needed and the frame just passes itself to the functions it wants to work.

Code:
<UI xmlns="http://www.blizzard.com/wow/ui/"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://www.blizzard.com/wow/ui/">

    <!-- Include script file that will hold the functions called by the FrameToDisplay frame and functions within sourceFile2.lua -->
    <Script file = "sourceFile1.lua" />
    
    <!-- Layout of the FrameToDisplay Frame -->
    <Frame name="FrameToDisplay">
        ...
        <Scripts>
            <OnLoad>
                functionInSourceFile1(self);
            </OnLoad>
        </Scripts>
    </Frame>
    
    <!-- Include script file that acts on FrameToDisplayFrame -->
    <Script file = "sourceFile2.lua" />

</UI>
So to recap ..

TOC file can be used to list key xml/lua files in order of process
XML files can be used to include xml/lua files in order of process
Lua files are used to connect the individual code files by sharing a table amongst all the files

1. Define which parts are needed by everything ... they go in the earliest files
2. Define which parts are needed by most .. they go next
3. Define which parts are needed by some .. they go next
4. Define which parts are not needed by any .. they can go anywhere but best last
5. Define which parts are needed by some but needs others .. they go in between the related files .. after the ones they need and before the ones that needs them

I hope that helps you see how you can segregate your file into smaller files
__________________

Last edited by Xrystal : 09-12-18 at 06:40 AM.
  Reply With Quote
09-19-18, 08:55 AM   #4
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
Splitting is easy.

Just add all your files to the TOC. (This requires a restart of the WoW client if changed!)

Example:
https://github.com/zorker/rothui/blo...oUF_Simple.toc

In every addon file you have access to globals, locals and your addon namespace.

Lua Code:
  1. --addon name, addon namespace
  2. local an, ans = ...

You can add functions and objects to your addon namespace without poluting the global namespace.
Making an object global, keeping it local or adding it to the addon namespace is up to you.

Example:
https://github.com/zorker/rothui/blo.../functions.lua
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 09-19-18 at 09:02 AM.
  Reply With Quote
09-21-18, 10:15 AM   #5
doofus
A Chromatic Dragonspawn
Join Date: Feb 2018
Posts: 158
Thanks for the suggestions.

Today I have tried a major restructure, trying to split the one large .lua file into multiple smaller ones, making use of the nameSpace table.

However I am unclear about the order of loading of the .lua files (is it the order in the .toc file?) and the order of initialising static variables.

in file3 I do:

nameSpace["a"]["b"]();

in file2 I do:

nameSpace["a"]["b"] = some_local_function();


and in file1 I do:

nameSpace["a"] = {};

The way I see it, if file1 loads first then nameSpace["a"] becomes a table. If file2 follows, it will have no problem setting nameSpace["a"]["b"] = some function. And finally, file3 can now invoke nameSpace["a"]["b"]();

But it fails in file3 saying that nameSpace["a"]["b"] is nil.

The way around it is to say in file2:

nameSpace["a"] = {};
nameSpace["a"]["b"] = some_local_function();

Then, file3 works as expected.

This begs the question, why was file1's definition not taken into account?
  Reply With Quote
09-21-18, 11:05 AM   #6
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
The files load in the order in the .toc.

The "NameSpace" is already a table passed in by Blizzard so you don't need to create a second one.

File 1
Lua Code:
  1. local addonName, NS = ...
  2.  
  3. NS.a = {}

File 2
Lua Code:
  1. local addonName, NS = ...
  2.  
  3. local function LocalTest(val)
  4.      print(val)
  5. end
  6.  
  7. NS.a.Test =  LocalTest
File 3
Lua Code:
  1. local addonName, NS = ...
  2. NS.a.Test("Hi there.")

you don't add the () when assigning the function unless you want to assign the result of calling the function.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 09-21-18 at 11:34 AM.
  Reply With Quote
09-21-18, 11:50 AM   #7
doofus
A Chromatic Dragonspawn
Join Date: Feb 2018
Posts: 158
The () after the function name was a typo here, not in the code.

I do not re-initialise the namespace, only the namespace["something"].

There is an issue with

file1:
local n, ns = ...
ns["a"] = { };

file2:
local n, ns = ...
ns["a"]["b"] = some_local_function;

file3:
local n, ns = ...
ns["a"]["b"](params); -- error, it is nil
  Reply With Quote
09-21-18, 12:16 PM   #8
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
If you could supply the actual code please. What you put there "seems" ok so the problem may be eslewhere.

All the [""] is unnecessary if you know the key names you can just use dots.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
09-21-18, 01:08 PM   #9
doofus
A Chromatic Dragonspawn
Join Date: Feb 2018
Posts: 158
I think I have found the issue, when I move variable initialisation from inside a function to the outside (static init), I forgot in some cases to delete the function initialisation resulting in the static one to be overwritten.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Include files

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off