## Secondary development of the build engine

xLua's build engine supports secondary development, and you can use it to generate some text files (for example, code and configuration files). The xLua's link.xml file is generated by the build engine plugin. Other application scenarios (such as generating a Lua IDE auto configuration file) can also be accomplished using this feature.

## Overview

The plugin needs to provide two things: 1. a template for generated files, 2. a callback function that accepts the user configuration and returns the data that needs to be injected into the template and the output stream of the files.

## Template syntax

The template syntax is simple, with only three elements:

* eval: The syntax is <%=exp%>. Exp is an arbitrary expression that will calculate and output the value of exp as a string.
* Code: The syntax is <% if true then end%>. The blue part is any Lua code that will be executed.
* Literal: This contains the parts other than eval and code. Literal means output as it is.

Example:

~~~xml
<%
require "TemplateCommon"
%>

<linker>
<%ForEachCsList(assembly_infos, function(assembly_info)%>
	<assembly fullname="<%=assembly_info.FullName%>">
	    <%ForEachCsList(assembly_info.Types, function(type)
		%><type fullname="<%=type:ToString()%>" preserve="all"/>
		<%end)%>
	</assembly>
<%end)%>
</linker>
~~~

TemplateCommon has some predefined functions that can be used (for example ForEachCsList). You can search in TemplateCommon.lua.txt of the project to see which functions are available. For ordinary Lua, you can write one.

## API

~~~csharp
public static void CSObjectWrapEditor.Generator.CustomGen(string template_src, GetTasks get_tasks)
~~~

* template_src: template source code
* get_tasks: This is a callback function. The type is GetTasks. This function is used to accept the user configuration and return the data that needs to be injected into the template and the output stream of the files.

~~~csharp
public delegate IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig user_cfg);
~~~

* lua_env: This is a LuaEnv object. Because the returned template data needs to be placed in LuaTable, LuaEnv.NewTable is required.
* user_cfg: user configuration
* return: Among the returned values, CustomGenTask represents a generated file, and IEnumerable type indicates that the same template can generate multiple files.

~~~csharp
public struct UserConfig
{
    public IEnumerable<Type> LuaCallCSharp;
    public IEnumerable<Type> CSharpCallLua;
    public IEnumerable<Type> ReflectionUse;
}
~~~

~~~csharp
public struct CustomGenTask
{
    public LuaTable Data;
    public TextWriter Output;
}
~~~

Example:

~~~csharp
public static IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig user_cfg)
{
    LuaTable data = lua_env.NewTable();
    var assembly_infos = (from type in user_cfg.ReflectionUse
                          group type by type.Assembly.GetName().Name into assembly_info
                          select new { FullName = assembly_info.Key, Types = assembly_info.ToList()}).ToList();
    data.Set("assembly_infos", assembly_infos);

    yield return new CustomGenTask
    {
        Data = data,
        Output = new StreamWriter(GeneratorConfig.common_path + "/link.xml",
        false, Encoding.UTF8)
    };
}
~~~

* Only one file is generated here, so only one CustomGenTask is returned.
* data is the data to be used in the template. There is an assembly_infos field included. See the template section for how to use this field.

## Tag

Generally speaking, you can use MenuItem to create a menu to trigger a custom generate operation. However, sometimes you may want the generate operation to be triggered directly by the xLua "Generate Code" menu. In this situation, you will need to use CSObjectWrapEditor.GenCodeMenu

Example:

~~~csharp
[GenCodeMenu]//加到Generate Code菜单里头
public static void GenLinkXml()
{
    Generator.CustomGen(ScriptableObject.CreateInstance<LinkXmlGen>().Template.text, GetTasks);
}
~~~

PS: All the code related to the content above is in the XLua\Src\Editor\LinkXmlGen directory, which is also the implementation of the link.xml generation function that was explained at the beginning.

