Files
file_scaffold_dart/lib/config.dart
2019-12-23 22:01:01 +02:00

176 lines
5.6 KiB
Dart

import 'dart:convert';
import 'package:args/args.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart';
class TemplateConfig {
final String pattern;
final String baseDirectory;
TemplateConfig({
@required this.pattern,
@required this.baseDirectory,
});
}
class FileScaffoldConfig {
/// Template name.
///
/// This will automatically be available inside your templates as
/// `{{Name}}` for exact value, or `{{name}}` for the name as a lower
/// case string.
///
/// This will also be the subfolder created when `createSubfolder == true`.
String name;
/// List of template configurations.
List<TemplateConfig> templates;
/// Directory to output to. Omit the template name. If you want it to be added
/// to the path, use `createSubfolder` argument in your scaffold config
String outputDirectory;
/// Set this to `true` to create a subfolder to contain your files, using the `name` as
/// the folder name. Default: `false`
bool createSubfolder;
/// Map of strings to use as replacement tokens. Your strings will be then available
/// in the template as `{{key}}`. For example, if your key was `"version"`, your replacement
/// token would be `{{version}}`. See [TemplateParser] for more information.
Map<String, dynamic> locals;
static ArgParser argParser = _createArgsParser();
/// Config for creating a scaffold.
///
/// You may specify glob strings as items in the `templates` list, which
/// will create [TemplateConfig]s from these patterns.
///
/// The `outputDirectory` argument is a path to the output directory in which
/// to scaffold files inside. Omit the template name. If you want it to be added
/// to the path, use `createSubfolder = true`.
FileScaffoldConfig({
@required this.name,
@required Iterable<dynamic> templates,
@required String outputDirectory,
this.createSubfolder = false,
this.locals = const {},
}) : templates = _mapTemplates(templates),
outputDirectory = _getAbsolute(outputDirectory);
static String _getAbsolute(String path) =>
isAbsolute(path) ? path : absolute(path);
static _mapTemplates(Iterable<dynamic> templates) => [
for (dynamic template in templates)
template is TemplateConfig
? TemplateConfig(
pattern: _getAbsolute(template.pattern),
baseDirectory: _getAbsolute(template.baseDirectory),
)
: TemplateConfig(
pattern: _getAbsolute(template),
baseDirectory: _getAbsolute(dirname(template)),
)
];
/// Makes a copy of this config, with the specified properties overridden.
copyWith({
String name,
List<String> templates,
String outputDirectory,
bool createSubfolder,
Map<String, dynamic> locals,
}) =>
FileScaffoldConfig(
name: name ?? this.name,
templates: templates ?? this.templates,
outputDirectory: outputDirectory ?? this.outputDirectory,
createSubfolder: createSubfolder ?? this.createSubfolder,
locals: locals ?? this.locals,
);
factory FileScaffoldConfig.fromArgs(List<String> args) {
var parser = FileScaffoldConfig.argParser;
var results = parser.parse(args);
Map<String, dynamic> locals = {};
for (String local in results['locals']) {
var k = local.substring(0, local.indexOf('='));
var v = local.substring(local.indexOf('=') + 1);
try {
v = json.decode(v);
} catch (e) {
//
}
locals[k] = v;
}
String name = results['name'] ?? results.rest.join(' ');
if (results['output-dir'] == null ||
results['templates'].isEmpty ||
name.isEmpty) {
throw ArgumentError.value(args, 'args', 'arguments are not valid');
}
return FileScaffoldConfig(
name: name,
templates: _mapTemplates(results['templates']),
locals: locals,
outputDirectory: results['output-dir'],
createSubfolder: results['create-subfolder'],
);
}
static void printHelp() {
print('File Scaffolding from a directory structure of any templates with replaceable-tokens');
print('for generating files from simple parameters.\n');
print('Usage:');
print(' When installed globally:\n');
print(' pub global run file_scaffold -n name [...flags]');
print('\nOptions:\n');
print(argParser.usage);
}
static ArgParser _createArgsParser() {
var argParser = ArgParser(usageLineLength: 100);
argParser.addOption(
'name',
abbr: 'n',
help:
'Name of this scaffold, to be used in folder name (if --create-subfolder is used) and file templates.',
);
argParser.addOption(
'output-dir',
abbr: 'o',
help:
'Directory to output the template files to. They will maintain their original directory structure.',
);
argParser.addFlag(
'create-subfolder',
abbr: 'C',
defaultsTo: false,
help:
"Create subfolder at the output directory, using the scaffold's name.",
negatable: true,
);
argParser.addMultiOption('templates',
abbr: 't',
help:
'List of templates to get files from. You may supply a glob string to include only files using that pattern.',
valueHelp: 'path/to/templates/**.json');
argParser.addMultiOption(
'locals',
abbr: 'l',
help: 'List of key-value mappings of locals to pass to the scaffold.',
valueHelp: 'key="value" [, ...]',
);
argParser.addFlag(
'help',
abbr: 'h',
help: 'Display this help message.',
negatable: false,
);
return argParser;
}
}