[gui] support yaml in builder style
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
"license": "BSD",
|
"license": "BSD",
|
||||||
"tags": ["flash", "openfl"],
|
"tags": ["flash", "openfl"],
|
||||||
"description": "Framework.",
|
"description": "Framework.",
|
||||||
"version": "0.7.0",
|
"version": "0.7.1",
|
||||||
"releasenote": "Update.",
|
"releasenote": "Update.",
|
||||||
"contributors": ["shmyga"],
|
"contributors": ["shmyga"],
|
||||||
"classPath": "src/main",
|
"classPath": "src/main",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package haxework.gui.build;
|
package haxework.gui.build;
|
||||||
#if macro
|
#if macro
|
||||||
|
|
||||||
|
import haxework.gui.build.BuilderUtil;
|
||||||
import haxe.macro.Context;
|
import haxe.macro.Context;
|
||||||
import haxework.gui.build.PositionJsonParser;
|
import haxework.gui.build.PositionJsonParser;
|
||||||
import haxe.macro.Expr;
|
import haxe.macro.Expr;
|
||||||
@@ -8,201 +9,204 @@ import haxe.macro.Expr.Field;
|
|||||||
|
|
||||||
class Builder {
|
class Builder {
|
||||||
|
|
||||||
private var templateFile:String;
|
private var templateFile:String;
|
||||||
private var templateKey:String;
|
private var templateKey:String;
|
||||||
private var styleFile:String;
|
private var styleFile:String;
|
||||||
|
|
||||||
private var template:Dynamic;
|
private var template:Dynamic;
|
||||||
private var fields:Array<Field>;
|
private var fields:Array<Field>;
|
||||||
private var exprs:Array<Expr>;
|
private var exprs:Array<Expr>;
|
||||||
private var style:Dynamic;
|
private var style:Dynamic;
|
||||||
|
|
||||||
private var i:Int;
|
private var i:Int;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
var templateMeta = BuilderUtil.getMeta(":template");
|
var templateMeta = BuilderUtil.getMeta(":template");
|
||||||
var templatePath = templateMeta[0].split("@");
|
var templatePath = templateMeta[0].split("@");
|
||||||
templateFile = Context.resolvePath(templatePath[0]);
|
templateFile = Context.resolvePath(templatePath[0]);
|
||||||
templateKey = templatePath[1];
|
templateKey = templatePath[1];
|
||||||
|
|
||||||
var ext = templateFile.split('.').pop();
|
template = BuilderUtil.loadFile(templateFile);
|
||||||
template = switch(ext) {
|
if (templateKey != null) template = Reflect.field(template, templateKey);
|
||||||
case 'json': BuilderUtil.loadJsonFile(templateFile);
|
|
||||||
case 'yml' | 'yaml': BuilderUtil.loadYamlFile(templateFile);
|
|
||||||
case x: throw 'Unsupported template format: "${x}"';
|
|
||||||
}
|
|
||||||
if (templateKey != null) template = Reflect.field(template, templateKey);
|
|
||||||
|
|
||||||
if (templateMeta[1] != null) {
|
if (templateMeta[1] != null) {
|
||||||
styleFile = Context.resolvePath(templateMeta[1]);
|
styleFile = Context.resolvePath(templateMeta[1]);
|
||||||
style = BuilderUtil.loadJsonFile(styleFile);
|
style = BuilderUtil.loadFile(styleFile);
|
||||||
}
|
|
||||||
|
|
||||||
fields = Context.getBuildFields();
|
|
||||||
exprs = [];
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getPosition(?position:JsonKeyPosition):Position {
|
|
||||||
var min = position == null ? 1 : position.min + 32; // :-(
|
|
||||||
var max = position == null ? 1 : position.max + 32;
|
|
||||||
var file = position == null || position.file == null ? templateFile : position.file;
|
|
||||||
return Context.makePosition({min:min, max:max, file:file});
|
|
||||||
}
|
|
||||||
|
|
||||||
private function specialValue(name:String, key:String, a:Array<String>, position:JsonKeyPosition):Dynamic {
|
|
||||||
return switch (a[0]) {
|
|
||||||
case "asset":
|
|
||||||
switch (a[1]) {
|
|
||||||
case "image":
|
|
||||||
"openfl.Assets.getBitmapData(\"" + a[2] + "\")";
|
|
||||||
case _:
|
|
||||||
a[2];
|
|
||||||
}
|
}
|
||||||
case "res":
|
|
||||||
var res = "haxework.provider.Provider.get(haxework.resources.IResources)." + a[1];
|
fields = Context.getBuildFields();
|
||||||
var bindExpr = res + ".bind(\"" + a[2] + "\", " + name + ", \"" + key + "\")";
|
exprs = [];
|
||||||
exprs.push(Context.parse(bindExpr, getPosition(position)));
|
i = 0;
|
||||||
//res + ".get(\"" + a[2] + "\")";
|
|
||||||
null;
|
|
||||||
case "locale":
|
|
||||||
"new haxework.locale.LString(\"" + a[1] + "\")";
|
|
||||||
case "class":
|
|
||||||
a[1];
|
|
||||||
case "layout":
|
|
||||||
var template = BuilderUtil.loadJsonFile(a[1]);
|
|
||||||
return getValue(name, key, template, position);
|
|
||||||
case "link":
|
|
||||||
"(links == null) ? untyped this : Reflect.field(links, \"" + a[1] + "\")";
|
|
||||||
case _:
|
|
||||||
Context.error("Unsupported prefix \"" + a[0] + "\"", getPosition(position));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private function getType(value:Dynamic, position:Position):String {
|
private static function getSpecField(object:Dynamic, field:String):Dynamic {
|
||||||
if (Reflect.hasField(value, "@type")) {
|
if (Reflect.hasField(object, "@" + field)) {
|
||||||
return Reflect.field(value, "@type");
|
return Reflect.field(object, "@" + field);
|
||||||
} else if (Reflect.hasField(value, "$type")) {
|
} else if (Reflect.hasField(object, "$" + field)) {
|
||||||
return Reflect.field(value, "$type");
|
return Reflect.field(object, "$" + field);
|
||||||
} else {
|
|
||||||
Context.error("Need @type field", position);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getValue(name:String, key:String, value:Dynamic, position:JsonKeyPosition):Dynamic {
|
|
||||||
return if (Std.is(value, Array)) {
|
|
||||||
value.map(function(v) {
|
|
||||||
return getValue(null, null, v, position);
|
|
||||||
});
|
|
||||||
} else if (Std.is(value, String)) {
|
|
||||||
if (value.charAt(0) == "@") {
|
|
||||||
specialValue(name, key, value.substring(1, value.length).split(":"), position);
|
|
||||||
} else if (~/(0x|#)[A-Fa-f\d]{6}/.match(value)) {
|
|
||||||
Std.parseInt(StringTools.replace(Std.string(value), "#", "0x"));
|
|
||||||
} else {
|
|
||||||
"\"" + value + "\"";
|
|
||||||
}
|
|
||||||
} else if (Std.is(value, Float) || (Std.is(value, Bool))) {
|
|
||||||
value;
|
|
||||||
} else if (value != null) {
|
|
||||||
var type = getType(value, getPosition(position));
|
|
||||||
if (type != null) {
|
|
||||||
var n = "a" + i++;
|
|
||||||
if (type == "Dynamic") {
|
|
||||||
//ToDo:
|
|
||||||
exprs.push(Context.parse("var " + n + " = cast {}", getPosition(position)));
|
|
||||||
} else {
|
} else {
|
||||||
exprs.push(Context.parse("var " + n + " = new " + type + "()", getPosition(position)));
|
return null;
|
||||||
}
|
}
|
||||||
createElement(value, n);
|
|
||||||
n;
|
|
||||||
} else {
|
|
||||||
null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private function createElement(template:Dynamic, name:String):String {
|
private function getPosition(?position:JsonKeyPosition):Position {
|
||||||
if (Reflect.hasField(template, "@style")) {
|
var min = position == null ? 1 : position.min + 32; // :-(
|
||||||
var s = Reflect.field(style, Reflect.field(template, "@style"));
|
var max = position == null ? 1 : position.max + 32;
|
||||||
for (key in Reflect.fields(s)) {
|
var file = position == null || position.file == null ? templateFile : position.file;
|
||||||
if (key.charAt(0) != "$" && !Reflect.hasField(template, key)) {
|
return Context.makePosition({min:min, max:max, file:file});
|
||||||
Reflect.setField(template, key, Reflect.field(s, key));
|
}
|
||||||
Reflect.setField(template, "$" + key, Reflect.field(s, "$" + key));
|
|
||||||
|
private function specialValue(name:String, key:String, a:Array<String>, position:JsonKeyPosition):Dynamic {
|
||||||
|
return switch (a[0]) {
|
||||||
|
case "asset":
|
||||||
|
switch (a[1]) {
|
||||||
|
case "image":
|
||||||
|
"openfl.Assets.getBitmapData(\"" + a[2] + "\")";
|
||||||
|
case _:
|
||||||
|
a[2];
|
||||||
|
}
|
||||||
|
case "res":
|
||||||
|
var res = "haxework.provider.Provider.get(haxework.resources.IResources)." + a[1];
|
||||||
|
var bindExpr = res + ".bind(\"" + a[2] + "\", " + name + ", \"" + key + "\")";
|
||||||
|
exprs.push(Context.parse(bindExpr, getPosition(position)));
|
||||||
|
//res + ".get(\"" + a[2] + "\")";
|
||||||
|
null;
|
||||||
|
case "locale":
|
||||||
|
"new haxework.locale.LString(\"" + a[1] + "\")";
|
||||||
|
case "class":
|
||||||
|
a[1];
|
||||||
|
case "layout":
|
||||||
|
var template = BuilderUtil.loadJsonFile(a[1]);
|
||||||
|
return getValue(name, key, template, position);
|
||||||
|
case "link":
|
||||||
|
"(links == null) ? untyped this : Reflect.field(links, \"" + a[1] + "\")";
|
||||||
|
case _:
|
||||||
|
Context.error("Unsupported prefix \"" + a[0] + "\"", getPosition(position));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Reflect.hasField(template, "id")) {
|
private static function getType(value:Dynamic, position:Position):String {
|
||||||
var id = Reflect.field(template, "id");
|
var type:String = getSpecField(value, "type");
|
||||||
var type = getType(template, getPosition());
|
if (type == null) {
|
||||||
var expr = Context.parse("var a:" + type, getPosition());
|
Context.error("Need @type field", position);
|
||||||
var complexType = switch (expr.expr) {
|
}
|
||||||
case EVars(vars): vars[0].type;
|
return type;
|
||||||
case _: null;
|
|
||||||
}
|
|
||||||
fields.push({
|
|
||||||
name: id,
|
|
||||||
access: [APublic],
|
|
||||||
pos: getPosition(),
|
|
||||||
kind: FProp("default", "null", complexType)
|
|
||||||
});
|
|
||||||
exprs.push(Context.parse("this." + id + " = " + name, getPosition()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (key in Reflect.fields(template)) {
|
private function getValue(name:String, key:String, value:Dynamic, position:JsonKeyPosition):Dynamic {
|
||||||
if (key.charAt(0) == "$" || key.charAt(0) == "@") continue;
|
return if (Std.is(value, Array)) {
|
||||||
var position = Reflect.field(template, "$" + key);
|
value.map(function(v) {
|
||||||
var value = getValue(name, key, Reflect.field(template, key), position);
|
return getValue(null, null, v, position);
|
||||||
if (value != null) {
|
});
|
||||||
exprs.push(Context.parse(name + "." + key + " = " + value, getPosition(position)));
|
} else if (Std.is(value, String)) {
|
||||||
}
|
if (value.charAt(0) == "@" || value.charAt(0) == "$") {
|
||||||
}
|
specialValue(name, key, value.substring(1, value.length).split(":"), position);
|
||||||
return name;
|
} else if (~/(0x|#)[A-Fa-f\d]{6}/.match(value)) {
|
||||||
}
|
Std.parseInt(StringTools.replace(Std.string(value), "#", "0x"));
|
||||||
|
} else {
|
||||||
|
"\"" + value + "\"";
|
||||||
public function build():Array<Field> {
|
}
|
||||||
createElement(template, "this");
|
} else if (Std.is(value, Float) || (Std.is(value, Bool))) {
|
||||||
|
value;
|
||||||
var init = false;
|
} else if (value != null) {
|
||||||
for (f in fields) if (f.name == "init") {
|
var type = getType(value, getPosition(position));
|
||||||
init = true;
|
if (type != null) {
|
||||||
break;
|
var n = "a" + i++;
|
||||||
|
if (type == "Dynamic") {
|
||||||
|
//ToDo:
|
||||||
|
exprs.push(Context.parse("var " + n + " = cast {}", getPosition(position)));
|
||||||
|
} else {
|
||||||
|
exprs.push(Context.parse("var " + n + " = new " + type + "()", getPosition(position)));
|
||||||
|
}
|
||||||
|
createElement(value, n);
|
||||||
|
n;
|
||||||
|
} else {
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fields.push({
|
private function createElement(template:Dynamic, name:String):String {
|
||||||
name: "build",
|
var s = getSpecField(template, "style");
|
||||||
access: [APublic],
|
if (s != null) {
|
||||||
pos: getPosition(),
|
var s = Reflect.field(style, s);
|
||||||
kind: FFun({
|
for (key in Reflect.fields(s)) {
|
||||||
args: [{name:"links", type:TPath({name:"Dynamic", pack:[], params:[]}), opt:true, value:null}],
|
if (key.charAt(0) != "$" && !Reflect.hasField(template, key)) {
|
||||||
expr: macro $b{exprs},
|
Reflect.setField(template, key, Reflect.field(s, key));
|
||||||
params: [],
|
Reflect.setField(template, "$" + key, Reflect.field(s, "$" + key));
|
||||||
ret: null
|
}
|
||||||
})
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
var contstrExprs = [];
|
if (Reflect.hasField(template, "id")) {
|
||||||
contstrExprs.push(macro super());
|
var id = Reflect.field(template, "id");
|
||||||
contstrExprs.push(macro build(links));
|
var type = getType(template, getPosition());
|
||||||
if (init) contstrExprs.push(macro init());
|
var expr = Context.parse("var a:" + type, getPosition());
|
||||||
|
var complexType = switch (expr.expr) {
|
||||||
|
case EVars(vars): vars[0].type;
|
||||||
|
case _: null;
|
||||||
|
}
|
||||||
|
fields.push({
|
||||||
|
name: id,
|
||||||
|
access: [APublic],
|
||||||
|
pos: getPosition(),
|
||||||
|
kind: FProp("default", "null", complexType)
|
||||||
|
});
|
||||||
|
exprs.push(Context.parse("this." + id + " = " + name, getPosition()));
|
||||||
|
}
|
||||||
|
|
||||||
fields.push({
|
for (key in Reflect.fields(template)) {
|
||||||
name: "new",
|
if (key.charAt(0) == "$" || key.charAt(0) == "@") continue;
|
||||||
access: [APublic],
|
var position = Reflect.field(template, "$" + key);
|
||||||
pos: getPosition(),
|
var value = getValue(name, key, Reflect.field(template, key), position);
|
||||||
kind: FFun({
|
if (value != null) {
|
||||||
args: [{name:"links", type:TPath({name:"Dynamic", pack:[], params:[]}), opt:true, value:null}],
|
exprs.push(Context.parse(name + "." + key + " = " + value, getPosition(position)));
|
||||||
expr: macro $b{contstrExprs},
|
}
|
||||||
params: [],
|
}
|
||||||
ret: null
|
return name;
|
||||||
})
|
}
|
||||||
});
|
|
||||||
return fields;
|
|
||||||
}
|
public function build():Array<Field> {
|
||||||
|
createElement(template, "this");
|
||||||
|
|
||||||
|
var init = false;
|
||||||
|
for (f in fields) if (f.name == "init") {
|
||||||
|
init = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.push({
|
||||||
|
name: "build",
|
||||||
|
access: [APublic],
|
||||||
|
pos: getPosition(),
|
||||||
|
kind: FFun({
|
||||||
|
args: [{name:"links", type:TPath({name:"Dynamic", pack:[], params:[]}), opt:true, value:null}],
|
||||||
|
expr: macro $b{exprs},
|
||||||
|
params: [],
|
||||||
|
ret: null
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
var contstrExprs = [];
|
||||||
|
contstrExprs.push(macro super());
|
||||||
|
contstrExprs.push(macro build(links));
|
||||||
|
if (init) contstrExprs.push(macro init());
|
||||||
|
|
||||||
|
fields.push({
|
||||||
|
name: "new",
|
||||||
|
access: [APublic],
|
||||||
|
pos: getPosition(),
|
||||||
|
kind: FFun({
|
||||||
|
args: [{name:"links", type:TPath({name:"Dynamic", pack:[], params:[]}), opt:true, value:null}],
|
||||||
|
expr: macro $b{contstrExprs},
|
||||||
|
params: [],
|
||||||
|
ret: null
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
@@ -9,44 +9,53 @@ import haxe.macro.Expr.ExprDef;
|
|||||||
|
|
||||||
class BuilderUtil {
|
class BuilderUtil {
|
||||||
|
|
||||||
public static function loadJsonFile(path:String) {
|
public static function loadJsonFile(path:String):Dynamic {
|
||||||
Context.registerModuleDependency(Context.getLocalModule(), path);
|
Context.registerModuleDependency(Context.getLocalModule(), path);
|
||||||
var content = sys.io.File.getContent(path);
|
var content = sys.io.File.getContent(path);
|
||||||
var json = null;
|
var json = null;
|
||||||
try {
|
try {
|
||||||
json = PositionJsonParser.parse(content, path);
|
json = PositionJsonParser.parse(content, path);
|
||||||
} catch(error:Dynamic) {
|
} catch (error:Dynamic) {
|
||||||
Context.error(error, Context.makePosition({min:0, max:0, file:path}));
|
Context.error(error, Context.makePosition({min:0, max:0, file:path}));
|
||||||
|
}
|
||||||
|
Context.parse(content, Context.makePosition({min:0, max:0, file:path}));
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
Context.parse(content, Context.makePosition({min:0, max:0, file:path}));
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function loadYamlFile(path:String) {
|
public static function loadYamlFile(path:String):Dynamic {
|
||||||
Context.registerModuleDependency(Context.getLocalModule(), path);
|
Context.registerModuleDependency(Context.getLocalModule(), path);
|
||||||
var content = sys.io.File.getContent(path);
|
var content = sys.io.File.getContent(path);
|
||||||
var result = null;
|
var result = null;
|
||||||
try {
|
try {
|
||||||
// ToDo: extract poisiton info
|
// ToDo: extract poisiton info
|
||||||
result = Yaml.parse(content, Parser.options().useObjects());
|
result = Yaml.parse(content, Parser.options().useObjects());
|
||||||
} catch(error:Dynamic) {
|
} catch (error:Dynamic) {
|
||||||
Context.error(error, Context.makePosition({min:0, max:0, file:path}));
|
Context.error(error, Context.makePosition({min:0, max:0, file:path}));
|
||||||
|
}
|
||||||
|
//Context.parse(content, Context.makePosition({min:0, max:0, file:path}));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
//Context.parse(content, Context.makePosition({min:0, max:0, file:path}));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getMeta(key:String):Array<String> {
|
public static function loadFile(path:String):Dynamic {
|
||||||
var c = Context.getLocalClass().get();
|
var ext = path.split('.').pop();
|
||||||
for (meta in c.meta.get()) {
|
return switch(ext) {
|
||||||
if (meta.name == key) {
|
case 'json': BuilderUtil.loadJsonFile(path);
|
||||||
return meta.params.map(function(param) return switch(param.expr) {
|
case 'yml' | 'yaml': BuilderUtil.loadYamlFile(path);
|
||||||
case ExprDef.EConst(Constant.CString(value)): value;
|
case x: throw 'Unsupported template format: "${x}"';
|
||||||
case _: null;
|
}
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
public static function getMeta(key:String):Array<String> {
|
||||||
|
var c = Context.getLocalClass().get();
|
||||||
|
for (meta in c.meta.get()) {
|
||||||
|
if (meta.name == key) {
|
||||||
|
return meta.params.map(function(param) return switch(param.expr) {
|
||||||
|
case ExprDef.EConst(Constant.CString(value)): value;
|
||||||
|
case _: null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
Reference in New Issue
Block a user