This repository has been archived by the owner on May 31, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 118
/
Copy pathstagehand.dart
192 lines (161 loc) · 5.44 KB
/
stagehand.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// Copyright (c) 2014, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/**
* Stagehand is a Dart project generator.
*
* Stagehand helps you get your Dart projects set up and ready for the big show.
* It is a Dart project scaffolding generator, inspired by tools like Web
* Starter Kit and Yeoman.
*
* It can be used as a command-line application, or as a regular Dart library
* composed it a larger development tool. To use as a command-line app, run:
*
* `pub global run stagehand`
*
* to see a list of all app types you can create, and:
*
* `mkdir foobar; cd foobar`
* `pub global run stagehand webapp`
*
* to create a new instance of the `webapp` template in a `foobar` directory.
*/
import 'dart:async';
import 'dart:convert';
import 'generators/console_full.dart';
import 'generators/console_simple.dart';
import 'generators/package_simple.dart';
import 'generators/server_appengine.dart';
import 'generators/server_shelf.dart';
import 'generators/web_angular.dart';
import 'generators/web_polymer.dart';
import 'generators/web_simple.dart';
import 'src/common.dart';
/// A curated, prescriptive list of Dart project generators.
final List<Generator> generators = [
new ConsoleFullGenerator(),
new ConsoleSimpleGenerator(),
new PackageSimpleGenerator(),
new ServerAppEngineGenerator(),
new ServerShelfGenerator(),
new WebAngularGenerator(),
new WebPolymerGenerator(),
new WebSimpleGenerator()
]..sort();
Generator getGenerator(String id) {
return generators.firstWhere((g) => g.id == id, orElse: () => null);
}
/**
* An abstract class which both defines a template generator and can generate a
* user project based on this template.
*/
abstract class Generator implements Comparable<Generator> {
final String id;
final String label;
final String description;
final List<String> categories;
final List<TemplateFile> files = [];
TemplateFile _entrypoint;
Generator(this.id, this.label, this.description, {this.categories: const []});
/**
* The entrypoint of the application; the main file for the project, which an
* IDE might open after creating the project.
*/
TemplateFile get entrypoint => _entrypoint;
/**
* Add a new template file.
*/
TemplateFile addTemplateFile(TemplateFile file) {
files.add(file);
return file;
}
/**
* Return the template file wih the given [path].
*/
TemplateFile getFile(String path) {
return files.firstWhere((file) => file.path == path, orElse: () => null);
}
/**
* Set the main entrypoint of this template. This is the 'most important' file
* of this template. An IDE might use this information to open this file after
* the user's project is generated.
*/
void setEntrypoint(TemplateFile entrypoint) {
if (_entrypoint != null) throw new StateError('entrypoint already set');
if (entrypoint == null) throw new StateError('entrypoint is null');
this._entrypoint = entrypoint;
}
Future generate(String projectName, GeneratorTarget target,
{Map<String, String> additionalVars}) {
Map vars = {
'projectName': projectName,
'description': description,
'year': new DateTime.now().year.toString(),
'author': '<your name>'
};
if (additionalVars != null) {
additionalVars.keys.forEach((key) {
vars[key] = additionalVars[key];
});
}
return Future.forEach(files, (TemplateFile file) {
var resultFile = file.runSubstitution(vars);
String filePath = resultFile.path;
return target.createFile(filePath, resultFile.content);
});
}
int numFiles() => files.length;
int compareTo(Generator other) =>
this.id.toLowerCase().compareTo(other.id.toLowerCase());
/**
* Return some user facing instructions about how to finish installation of
* the template.
*/
String getInstallInstructions() => '';
String toString() => '[${id}: ${description}]';
}
/**
* A target for a [Generator]. This class knows how to create files given a path
* for the file (relavtive to the particular [GeneratorTarget] instance), and
* the binary content for the file.
*/
abstract class GeneratorTarget {
/**
* Create a file at the given path with the given contents.
*/
Future createFile(String path, List<int> contents);
}
/**
* This class represents a file in a generator template. The contents could
* either be binary or text. If text, the contents may contain mustache
* variables that can be substituted (`__myVar__`).
*/
class TemplateFile {
final String path;
final String content;
List<int> _binaryData;
TemplateFile(this.path, this.content);
TemplateFile.fromBinary(this.path, this._binaryData) : this.content = null;
FileContents runSubstitution(Map parameters) {
if (path == 'pubspec.yaml' && parameters['author'] == '<your name>') {
parameters = new Map.from(parameters);
parameters['author'] = 'Your Name';
}
var newPath = substituteVars(path, parameters);
var newContents = _createContent(parameters);
return new FileContents(newPath, newContents);
}
bool get isBinary => _binaryData != null;
List<int> _createContent(Map vars) {
if (isBinary) {
return _binaryData;
} else {
return UTF8.encode(substituteVars(content, vars));
}
}
}
class FileContents {
final String path;
final List<int> content;
FileContents(this.path, this.content);
}