Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to use any template by giving its path #78

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions info/template.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
Usage : template <name> <path> <options>
<name> : The name for the template to generate, the "default"
template will be created when none is specified.
<path> : The name for the path to create the template in, default
is the name of the template itself.
Usage : template <tpl-name | tpl-path> <target-path> <options>
<tpl-name | tpl-path> :
The name or the path of the template to generate.
The "default" template will be created when none is specified.
<target-path> :
The path to create the template in, default is the name
of the template itself.
<options> : The options available will depend on the specific
template's template.json. The default template has options
such as -n for project name and -w -h for width and height.
Eg. flixel tpl -n "Name" -w 680 -h 480
-ide <subl|fd|idea|vscode|none> : The IDE to use (overrides the configuration).
-ide <subl|fd|idea|vscode|none> : The IDE to use (overrides the configuration).

Examples :

flixel tpl -n "Hello World"
Creates a project with name "Hello World"
from the "default" template,
inside "./Hello World" directory.
flixel tpl ./my-game -n MyGame
Creates a project with name "MyGame"
from the "default" template,
inside "./my-game" directory.
flixel tpl ../platformer-template . -n "Marevo"
Creates a project with name "Marevo"
from the template found in "../platformer-template" directory,
inside current directory.
6 changes: 6 additions & 0 deletions src/FlxTools.hx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ class FlxTools extends CommandLineRunner
displayInfo();
}

override public function createConsole()
{
final isHaxelibRun = Sys.getEnv('HAXELIB_RUN') != null;
return new massive.sys.cmd.Console(isHaxelibRun);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This properly determines if tools are run by haxelib. During tests of this patch I run the tools directly by neko run.n, and without HAXELIB_RUN var check there is a bug when last . argument passed to the tools is ignored. See massive-oss/mlib/pull/25

static function displayInfo()
{
displayLogo();
Expand Down
85 changes: 73 additions & 12 deletions src/commands/Template.hx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package commands;

import FlxTools.IDE;
import haxe.io.Path;
import massive.sys.cmd.Command;
import sys.FileSystem;
import utils.CommandUtils;
import utils.FileSysUtils;
import utils.ProjectUtils;
import utils.TemplateUtils;

Expand All @@ -14,6 +16,32 @@ class Template extends Command

override public function execute()
{
/*
Ways to use `template` command
NOTE: literaly no one on github used "flixel tpl ./<new_dir>

- tpl
creates "FlxProject" from "default" tpl inside "%cwd/default" dir
- tpl -n MyGame
creates "MyGame" from "default" tpl inside "%cwd/MyGame" dir
- tpl demo
creates "FlxProject" from "demo" tpl inside "%cwd/demo" dir
- tpl demo -n MyGame
creates "MyGame" from "demo" tpl inside "%cwd/MyGame" dir
- tpl ./my-game
creates "FlxProject" from "default" tpl inside "%cwd/my-game" dir
- tpl ./my-game -n MyGame
creates "MyGame" from "default" tpl inside "%cwd/my-game" dir
- tpl demo my-game
creates "FlxProject" from "demo" tpl inside "%cwd/my-game" dir
- tpl demo my-game -n MyGame
creates "MyGame" from "demo" tpl inside "%cwd/MyGame" dir
- tpl ./demo ./../my-game
creates "FlxProject" from "./demo" tpl inside "%cwd/../my-game" dir
- tpl ../demo ./../my-game -n MyGame
creates "MyGame" from "./demo" tpl inside "%cwd/../my-game" dir
*/

TemplateUtils.verifyTemplatesLoaded();

var targetPath = "";
Expand All @@ -30,12 +58,9 @@ class Template extends Command

ideOption = ProjectUtils.resolveIDEChoice(console, autoContinue);

if (console.getOption("-n") != null)
targetPath = console.getOption("-n");

// support a path as an arg without name for default
// flixel t ./<new_directory> <options>
if (templateName.startsWith("./"))
// flixel tpl ./<new_directory> <options>
if (FileSysUtils.isDirectoryPath(templateName) && targetPath == "")
{
targetPath = templateName;
templateName = "";
Expand All @@ -48,11 +73,30 @@ class Template extends Command
{
var template:TemplateProject = TemplateUtils.get(templateName);

// to fake existence of non-existed templates,
// will be deleted before merge
if (template == null)
{
trace('template was faked');
template = {
name: templateName,
path: 'some/path/to/${templateName}',
template: {
replacements: [
{
replacement: "FlxProject",
cmdOption: "-n",
pattern: "${PROJECT_NAME}"
}
]
}
}
}

if (template == null)
{
error("Error getting the template with the name of "
+ templateName
+ " make sure you have installed flixel-templates ('haxelib install flixel-templates')");
error('Error getting the template with the name of "${templateName}"'
+ "\nMake sure you have installed flixel-templates ('haxelib install flixel-templates')");
}
else
{
Expand All @@ -62,15 +106,27 @@ class Template extends Command
// override the template defaults form the command arguments
template = addOptionReplacement(template);

// try to use project name as target path
if (targetPath == "" && console.getOption('-n') != null)
targetPath = console.getOption('-n');

if (targetPath == "")
{
targetPath = Sys.getCwd() + templateName;
targetPath = Path.join([Sys.getCwd(), templateName]);
}
else if (!targetPath.startsWith("/"))
else if (!Path.isAbsolute(targetPath))
{
targetPath = CommandUtils.combine(Sys.getCwd(), CommandUtils.stripPath(targetPath));
targetPath = Path.join([Sys.getCwd(), targetPath]);
}

// used for tests, will be deleted before merge
Sys.print('\n---------
template name: ${template.name}
template path: ${template.path}
target path: $targetPath
project name: ${console.getOption("-n") != null ? console.getOption("-n") : "FlxProject"}
---------\n');

if (FileSystem.exists(targetPath))
{
Sys.println("Warning::" + targetPath);
Expand All @@ -79,7 +135,7 @@ class Template extends Command

if (!autoContinue)
{
answer = CommandUtils.askYN("Directory exists - do you want to delete it first?");
answer = CommandUtils.askYN("Directory exists - do you want to delete it first? Type . to abort.");
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add CommandUtils.askYNAbort to be more clear?

}

if (answer == Answer.Yes)
Expand All @@ -94,6 +150,11 @@ class Template extends Command
exit();
}
}
else if (answer == null)
{
Sys.println("Aborted by user");
exit();
}
}

Sys.println('Copying template files...');
Expand Down
2 changes: 1 addition & 1 deletion src/utils/CommandUtils.hx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class CommandUtils
}

/**
* Prompt user with a y/n/a
* Prompt user with a y/n
*
* @param question String with the prompt to display
* @return User choice in an Answer enum or null if an invalid answer given
Expand Down
7 changes: 6 additions & 1 deletion src/utils/FileSysUtils.hx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class FileSysUtils
}
catch (e:Dynamic)
{
throw "Error loading file::" + filePath + " \n check you dont have it open and you have permissions to modify it.";
throw "Error loading file::" + filePath + " \n Check the file exists or you dont have it open and you have permissions to modify it.";
}
}

Expand All @@ -45,4 +45,9 @@ class FileSysUtils
segments.shift();
return segments.join(cwd);
}

public static function isDirectoryPath(str:String):Bool
{
return new Path(str).dir != null;
}
}
53 changes: 40 additions & 13 deletions src/utils/TemplateUtils.hx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package utils;

import FlxTools.IDE;
import haxe.Json;
import haxe.io.Path;
import massive.sys.io.FileSys;
import sys.FileSystem;
import sys.io.FileOutput;
Expand All @@ -24,6 +25,9 @@ class TemplateUtils
if (templateName == "")
templateName = 'default';

if (FileSysUtils.isDirectoryPath(templateName))
return findTemplate(templateName);

for (template in findTemplates())
{
if (template.name == templateName)
Expand All @@ -32,17 +36,33 @@ class TemplateUtils
return null;
}

public static function findTemplate(path:String):TemplateProject
{
if (!FileSys.exists(path))
return null;

// NOTE: isDirectory() throws an error if path does not exist
if (!FileSys.isDirectory(path))
return null;

path = FileSystem.fullPath(Path.normalize(path));
var dirName = Path.withoutDirectory(Path.removeTrailingSlashes(path));
var template = readTemplateJson(path, dirName);

return template;
}

public static function findTemplates(?templatesPath:String):Array<TemplateProject>
{
if (templatesPath == null)
{
templatesPath = CommandUtils.getHaxelibPath("flixel-templates");
if (templatesPath == "")
return null;
return [];
}

if (!FileSys.exists(templatesPath))
return null;
return [];

final templates = [];

Expand All @@ -52,27 +72,34 @@ class TemplateUtils

if (FileSys.exists(folderPath) && FileSys.isDirectory(folderPath) && name != '.git')
{
var filePath = CommandUtils.combine(templatesPath, name);
filePath = CommandUtils.combine(filePath, "template.json");
var templatePath = CommandUtils.combine(templatesPath, name);
var templateJsonPath = CommandUtils.combine(templatePath, "template.json");

// Make sure we don't get a crash if the file doesn't exist
if (FileSystem.exists(filePath))
if (FileSystem.exists(templateJsonPath))
{
final file = FileSysUtils.getContent(filePath);
final FileData:TemplateFile = Json.parse(file);
final project:TemplateProject = {
name: name,
path: templatesPath + name,
template: FileData
};
templates.push(project);
templates.push(readTemplateJson(templatePath, name, templateJsonPath));
}
}
}

return templates;
}

static function readTemplateJson(templatePath:String, teamplateName:String, ?templateJsonPath:String):TemplateProject
{
if (templateJsonPath == null)
templateJsonPath = Path.join([templatePath, "template.json"]);

final fileContent = FileSysUtils.getContent(templateJsonPath);

return {
name: teamplateName,
path: templatePath,
template: Json.parse(fileContent)
};
}

public static function getReplacementValue(replacements:Array<TemplateReplacement>, pattern:String):String
{
for (o in replacements)
Expand Down