When developing something as complex as a new exporter, it is a good idea to build it as a [module](Developing-Modules.md). Doing so helps organize the code, provides [a way to automate testing](Adding-Unit-Tests.md), and makes it easy to [share your code with others](Sharing-Your-Module.md).

So let's start by setting up a module containing a really simple action. Create a new file named `lua.lua` and place it into a folder named `lua`. Place this `lua` folder [somewhere Premake can find it](Locating-Scripts.md).

Copy this simple skeleton action definition into your `lua.lua`:


```lua
-- lua/lua.lua

premake.modules.lua = {}
local m = premake.modules.lua

local p = premake

newaction {
	trigger = "lua",
	description = "Export project information as Lua tables",

	onStart = function()
		print("Starting Lua generation")
	end,

	onWorkspace = function(wks)
		printf("Generating Lua for workspace '%s'", wks.name)
	end,

	onProject = function(prj)
		printf("Generating Lua for project '%s'", prj.name)
	end,

	execute = function()
		print("Executing Lua action")
	end,

	onEnd = function()
		print("Lua generation complete")
	end
}

return m
```

I'll explain what all of that means in a moment, but first let's try it out and make sure everything is working. To see our new action in action, we'll need to require it into an existing project's `premake5.lua` script.

```lua
require "lua"  -- add this to load your module

workspace "MyWorkspace"
	configurations { "Debug", "Release" }

project "MyProject"
	-- etc.
```

Then we can generate that project with our new `lua` action and see the `print()` functions get called.

```
$ premake5 lua
Building configurations...
Running action 'lua'...
Starting Lua generation
Generating Lua for workspace 'MyWorkspace'
Generating Lua for project 'MyProject'
Executing Lua action
Lua generation complete
Done.
```

(Quick side note: if you'd like to make this or any third-party module available without having to add a `require()` to every project script, just put that `require("lua")` call in your [system script](System-Scripts.md) instead.)


### Explain. ###

We start out by creating a table to hold our module's interface. Since we'll be referencing this interface quite a lot in our code, we assign it to the shortcut `m` for "module".

```lua
premake.modules.lua = {}
local m = premake.modules.lua
```

We will also be calling functions from the `premake` namespace frequently, so we assign that to the shortcut `p` for "premake".

```lua
local p = premake
```

Now we're ready to register our new action with Premake, using `newaction()`.

```lua
newaction {
	trigger = "lua",
	description = "Export project information as Lua",
```

`trigger` is the token that should be typed on the Premake command line to cause our action to be triggered (i.e. `premake5 lua`).

`description` is the string which should appear in Premake's help text to describe what our action does. You can view this by running `premake5 --help` against the project script we modified above.

Next, we register callbacks for Premake to use when it is time to export the project:

```lua
onStart = function()
	print("Starting Lua generation")
end,

onWorkspace = function(wks)
	printf("Generating Lua for workspace '%s'", wks.name)
end,

onProject = function(prj)
	printf("Generating Lua for project '%s'", prj.name)
end,

execute = function()
	print("Executing Lua action")
end,

onEnd = function()
	print("Lua generation complete")
end
```

All of these callbacks are optional; you only need to include the ones you are actually interested in receiving.

`onStart` is called first to indicate that processing has begun.

`onWorkspace` is called once for every workspace that was declared, via the [`workspace`](workspace.md) function, in the user's project script.

`onProject` is called once for every project that was declared, via the [`project`](project.md) function, in the user's project script.

`execute` is called after all projects and workspaces have been processed. This is a good place to put more general code that doesn't require a workspace or project as input, and should only run once.

`onEnd` is called to indicate the processing is complete.

Finally, we return our module's interface back to the caller (the `require("lua")` call in our project or system script).

```lua
return m
```