Skip to content

Commit

Permalink
Added DI
Browse files Browse the repository at this point in the history
Added simple steps system
  • Loading branch information
fantoine committed Jul 11, 2016
1 parent 7aad465 commit 509e410
Show file tree
Hide file tree
Showing 20 changed files with 467 additions and 93 deletions.
2 changes: 2 additions & 0 deletions build.hxml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
--interp
-main hxextern.Main
-cp src/
-lib hscript
-lib hxargs
-lib minject
3 changes: 2 additions & 1 deletion haxelib.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"classPath": "src/",
"contributors": ["fantoine"],
"dependencies": {
"hscript": "",
"hxargs": "",
"hxssl": ""
"minject": ""
}
}
36 changes: 22 additions & 14 deletions src/hxextern/Cli.hx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ package hxextern;

import hxargs.Args;
import hxextern.command.*;
import hxextern.service.*;
import hxextern.service.Console;
import minject.Injector;

typedef ArgsHandler = {
function getDoc() : String;
Expand All @@ -12,33 +13,39 @@ typedef ArgsHandler = {

class Cli
{
@inject
public var injector(default, null) : Injector;

@inject
public var console(default, null) : Console;

private var handler : ArgsHandler;

public function new()
{
this.handler = Args.generate([
@doc('Generate extern code')
'generate' => function(?path : String) : Void {
this.runCommand(GenerateCommand, [path]);
},

@doc('List available externs')
'list' => function(?target : String) : Void {
this.runCommand(new ListCommand(target));
this.runCommand(ListCommand, [target]);
},

@doc('Search for an extern')
'search' => function(name : String, ?target : String) : Void {
this.runCommand(new SearchCommand(name, target));
},

@doc('Generate extern code')
'generate' => function(?path : String) : Void {
trace('Not implemented');
this.runCommand(SearchCommand, [name, target]);
},

@doc('Show this help')
'help' => function() : Void {
this.runCommand(new HelpCommand(this.handler.getDoc()));
this.runCommand(HelpCommand, [this.handler.getDoc()]);
},

_ => function(arg : String) : Void {
this.runCommand(new HelpCommand(this.handler.getDoc()));
this.runCommand(HelpCommand, [this.handler.getDoc()]);
},
]);
}
Expand All @@ -51,16 +58,17 @@ class Cli
try {
this.handler.parse(args);
} catch (e : Dynamic) {
Console.instance.error(Std.string(e));
this.console.error(Std.string(e));
}
}

private function runCommand(command : ICommand) : Void
private function runCommand(commandType : Class<ICommand>, ?args : Array<Dynamic>) : Void
{
try {
command.run();
var command = this.injector.instantiate(commandType);
command.run(null == args ? [] : args);
} catch (e : Dynamic) {
Console.instance.error(Std.string(e));
this.console.error(Std.string(e));
}
}
}
107 changes: 107 additions & 0 deletions src/hxextern/Macro.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package hxextern;

import haxe.io.Path;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
import haxe.macro.TypeTools;
import sys.FileSystem;

using StringTools;

class Macro
{
private static inline var STEP_META : String = ':step';

public static macro function listSteps(injector : Expr) : Expr
{
var injections = [];
var modules = Macro.listTypes('hxextern.step');
for (module in modules) {
var type = switch (module) {
case TInst(inst, _): inst.get();
case _: null;
}
if (null == type) {
continue;
}

if (type.isExtern || type.isInterface || !type.meta.has(Macro.STEP_META) || !Macro.doesImplement(type, 'hxextern.step.IStep')) {
continue;
}
var step = switch (type.meta.extract(Macro.STEP_META)) {
case [{ params: [{ expr: EConst(CString(name)) }] }]: name;
case _: null;
}
if (null == step) {
continue;
}

var moduleName = type.name;
injections.push(macro $injector.mapClass(hxextern.step.IStep, hxextern.step.$moduleName, $v{step}));
}
return macro { $a{injections} };
}

public static macro function listCommands(injector : Expr) : Expr
{
var injections = [];
var modules = Macro.listTypes('hxextern.step');
for (module in modules) {
var type = switch (module) {
case TInst(inst, _): inst.get();
case _: null;
}
if (null == type) {
continue;
}

if (type.isExtern || type.isInterface || !Macro.doesImplement(type, 'hxextern.command.ICommand')) {
continue;
}

var moduleName = type.name;
injections.push(macro $injector.mapClass(hxextern.command.$moduleName, hxextern.command.$moduleName));
injections.push(macro $injector.mapClass(hxextern.command.ICommand, hxextern.command.$moduleName, $v{moduleName}));
}
return macro { $a{injections} };
}

#if macro
private static function listTypes(pack : String) : Array<Type>
{
var types = [];
for (cp in Context.getClassPath()) {
var directory = Path.addTrailingSlash(cp) + pack.replace('.', '/');
if (!FileSystem.exists(directory) || !FileSystem.isDirectory(directory)) {
continue;
}

for (file in FileSystem.readDirectory(directory)) {
if (!file.endsWith('.hx')) {
continue;
}

var moduleName = file.substr(0, -3);
var module = try Context.getType('${pack}.${moduleName}') catch(e : String) null;
if (null == module) {
continue;
}
types.push(module);
}
}
return types;
}

private static function doesImplement(type : ClassType, interfaceType : String) : Bool
{
for (entry in type.interfaces) {
if (entry.t.toString() == interfaceType || Macro.doesImplement(entry.t.get(), interfaceType)) {
return true;
}
}

return (null != type.superClass ? Macro.doesImplement(type.superClass.t.get(), interfaceType) : false);
}
#end
}
19 changes: 17 additions & 2 deletions src/hxextern/Main.hx
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
package hxextern;

import hxextern.service.*;
import minject.Injector;

class Main
{
public static function main() : Void
{
// Get arguments
var args = Sys.args();
args.pop();
var cwd = args.pop();

// Prepare injector
var injector = new Injector();
injector.mapValue(Injector, injector);
injector.mapSingleton(Console);
injector.mapSingleton(Haxelib);
injector.mapSingleton(Process);
injector.mapSingleton(Repository);
Macro.listSteps(injector);

// Update cwd
Sys.setCwd(cwd);

// Run
var cli = new Cli();
var cli = injector.instantiate(Cli);
cli.run(args);
}
}
20 changes: 14 additions & 6 deletions src/hxextern/command/AbstractListCommand.hx
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,36 @@ import hxextern.service.Repository;

class AbstractListCommand implements ICommand
{
@inject
public var console(default, null) : Console;

@inject
public var repository(default, null) : Repository;

public function new()
{
// Nothing to do
}

public function run() : Void
public function run(args : Array<Dynamic>) : Void
{
throw 'Must be overriden';
}

private function printList(infos : Array<RepositoryInfo>) : Void
{
if (0 == infos.length) {
Console.instance.info('No results found');
this.console.info('No results found');
return;
}

Console.instance.success('Found ${infos.length} result(s)');
this.console.success('Found ${infos.length} result(s)');
for (info in infos) {
Console.instance.message(' * ', false);
Console.instance.info('${info.name} (${info.target})', false);
Console.instance.message(' : ${info.description}');
this.console
.message(' * ', false)
.info('${info.name} (${info.target})', false)
.message(' : ${info.description}')
;
}
}
}
62 changes: 62 additions & 0 deletions src/hxextern/command/GenerateCommand.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package hxextern.command;

import hxextern.service.Haxelib;
import hxextern.step.*;
import hxextern.step.IStep;
import sys.FileSystem;

using StringTools;

class GenerateCommand implements ICommand
{
@inject
public var haxelib(default, null) : Haxelib;

public function new()
{
/*
this.path = path;
this.steps = new Map();
var types : Array<Class<IStep>> = [ScriptStep, NpmStep];
for (type in types) {
var instance = Type.createInstance(type, []);
this.steps[instance.type] = instance;
}
*/
}

public function run(args : Array<Dynamic>) : Void
{
var path : Null<String> = args[0];

// Find haxelib file
var file = (null != path ?
this.haxelib.findFile(path) :
this.haxelib.findFromPath(Sys.getCwd())
);

// Extract datas
var data = this.haxelib.extract(file);
this.executeSteps(data.steps);
}

private function executeSteps(steps : Array<HaxelibHxExternStep>) : Void
{
/*
var definitions = new TypeDefinitionMap();
for (step in steps) {
// Get step name
var name = step.type.trim().toLowerCase();
if (!this.steps.exists(name)) {
throw 'Step "${step.type}" has not been found';
}
// Run step
var instance = this.steps[name];
definitions = instance.run(definitions, step.options);
}
trace(definitions);
*/
}
}
19 changes: 14 additions & 5 deletions src/hxextern/command/HelpCommand.hx
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
package hxextern.command;

import hxextern.service.Console;

class HelpCommand implements ICommand
{
private var doc : String;
@inject
public var console(default, null) : Console;

public function new(doc : String)
public function new()
{
this.doc = doc;

}

public function run() : Void
public function run(args : Array<Dynamic>) : Void
{
Sys.println(this.doc);
var doc : String = args[0];

this.console
.info('HxExtern Manager 1.0.0')
.message(' Usage: hxextern [command] <arguments>')
.message(' ' + doc.split('\n').join('\n '))
;
}
}
2 changes: 1 addition & 1 deletion src/hxextern/command/ICommand.hx
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package hxextern.command;

interface ICommand
{
public function run() : Void;
public function run(args : Array<Dynamic>) : Void;
}
Loading

0 comments on commit 509e410

Please sign in to comment.