对开源工具Mason的概述,它可以自动生成代码。
原文地址:verygood.ventures/blog/code-g…
原文作者:verygood.ventures/team/felix-…
发布时间:2021年5月27日
Mason是一个开源工具,可以从称为砖块的自定义模板中生成代码。它对于那些发现自己反复编写相同代码的开发者,或者那些寻找定制可重复使用的模板的人来说是有帮助的。
梅森可以通过实现更大的日常自动化来提高开发团队的效率。例如,如果有一个部件或方法是你的团队在整个项目中都要使用的,你可以简单地把这段代码写成一次砖块模板。然后,你可以在任何时候使用mason,用动态变量从模板生成那段代码。砖块模板可以作为特定项目的一部分在本地维护,也可以通过GitHub仓库远程维护。
作为一个个人开发者,砖家对于创建和生成你自己的模板来启动新项目是非常有帮助的。事实上,这正是我们在Very Good CLI中所做的,它在引擎盖下使用mason来生成Very Good Core,即我们的VGV意见的Flutter启动器应用模板。另一个例子是groovin_cli,这是一个由GroovinChip使用mason创建的应用生成器,灵感来自Very Good CLI。
Mason是用Dart编写的,但可以用来生成任何编程语言的代码。它还可以从任何规模的模板中生成代码--从几行到由数百个文件和目录组成的完整应用程序。
它是如何工作的
Mason使用mustache模板语法,使开发者能够创建和维护称为砖块的复杂模板,而不必编写任何生成器代码。在内部,Mason维护对所有已安装的砖块模板的引用,并通过Mason make命令将它们浮现给开发者。砖块模板包括一个brick.yaml文件和一个包含模板代码的__brick__目录。
当你想从砖块中生成代码时,mason通过提示或命令行参数来收集砖块所需的输入变量,并在将新生成的代码写入磁盘之前将它们注入砖块。由于mason是一个CLI工具,你可以直接从你的终端运行它。
开始使用
# Install from pub.dev
$ dart pub global activate mason
# Install from homebrew
$ brew tap felangel/mason
$ brew install mason
在这一点上,mason应该可以作为一个命令使用。你可以通过在终端运行mason来验证。
$ mason
⛏️ mason • lay the foundation!
Usage: mason [arguments]
Global options:
-h, --help Print this usage information.
--version Print the current version.
Available commands:
bundle Generates a bundle from a brick template
cache Interact with mason cache
get Gets all bricks.
init Initialize mason in the current directory.
make Generate code using an existing brick template.
new Creates a new brick template.
Run "mason help " for more information about a command.
Hello World 示例
我们要看的第一个例子是hello world的例子,它在你初始化mason时就已经出现了。
初始化Mason
首先,在你选择的目录中运行mason init。它应该生成一个mason.yaml和一个砖块目录。
$ mason init
✓ Initialized (0.1ms)
✓ Generated 3 file(s):
mason.yaml (new)
bricks/hello/brick.yaml (new)
bricks/hello/__brick__/HELLO.md (new)
mason.yaml是可以注册砖块的地方,与pubspec.yaml类似。砖块可以通过路径或git url进行引用,如下所示。
# Register bricks which can be consumed via the Mason CLI.
# https://pub.dev/packages/mason
bricks:
# Sample Brick
# Run `mason make hello` to try it out.
hello:
path: bricks/hello
# Bricks can also be imported via git url.
# Uncomment the following lines to import
# a brick from a remote git url.
# todos:
# git:
# url: git@github.com:felangel/mason.git
# path: bricks/todos
砖块目录包含砖块模板。在本例中,只有一个名为 hello 的砖块。brick.yaml 包含关于模板的重要元数据,如名称、描述和所需变量。
name: hello
description: An example hello brick.
vars:
- name
每个砖块都有一个__brick__目录,包含了模板本身。当砖块运行时,__brick__中的任何文件或目录都将成为生成代码的一部分。
├── __brick__
│ └── HELLO.md
└── brick.yaml
如果我们快速浏览一下HELLO.md模板文件,我们可以看到我们能够通过{{name}}访问name变量。
Hello {{name}}!
现在我们已经仔细看了一下砖块模板的各个部分,让我们来安装一个。
安装砖块模板
我们可以通过mason get命令来安装mason.yaml中声明的所有砖块。
$ mason get
✓ getting bricks (0.0ms)
这将生成一个.mason,其中包含确定模板安装位置所需的相关元数据。我们建议将.mason目录添加到你的.gitignore中。
# .gitignore
.mason/
现在我们准备好生成一些代码了!
生成代码
一旦砖块安装完毕,我们可以运行mason make hello来使用hello模板。
$ mason make hello --name Felix
✓ Made brick hello (0.0ms)
✓ Generated 1 file(s):
/HELLO.md (new)
HELLO.md将在当前目录下生成。该文件的内容应该是这样的。
Hello Felix!
Mason会提示你任何没有通过命令行参数提供的变量。
$ mason make hello
name: Dash
✓ Made brick hello (7.7ms)
✓ Generated 1 file(s):
/HELLO.md (new)
现在HELLO.md应该已经被覆盖,包括更新的名字:Dash。
Hello Dash!
现在让我们来看看如何为自定义部件创建我们自己的砖块。
自定义部件实例
我们可以使用mason new命令来创建一个新的砖块。
mason new widget -d "A custom Flutter widget"
✓ Created new brick: widget (0.1ms)
✓ Generated 2 file(s):
bricks/widget/brick.yaml (new)
bricks/widget/__brick__/hello.md (new)
注意,mason在mason.yaml中自动声明了新的widget砖块。
bricks:
hello:
path: bricks/hello
widget:
path: bricks/widget
这里是我们新的widget砖块的brick.yaml文件。
name: widget
description: A custom Flutter widget
vars:
- name
让我们添加一个名为routable的变量,它将决定新的widget是否应该暴露一个路由函数。
name: widget
description: A custom Flutter widget
vars:
- name
- routable
现在brick.yaml已经完成。让我们开始编写模板。
我们可以删除__brick__目录下默认的hello.md文件,并创建一个新的文件,名为。
{{#snakeCase}}{{name}}{{/snakeCase}}.dart
snakeCase lambda是由mason提供的。目前mason提供了许多开箱即用的lambdas,比如。
- camelCase
- constantCase
- dotCase
- headerCase
- lowerCase
- pascalCase
- paramCase
- pathCase
- sentenceCase
- snakeCase
- titleCase
- upperCase
这将告诉mason创建一个名为<name>.dart的文件,并确保文件名是蛇形大小写。接下来,让我们修改我们的widget模板文件的内容,以包括widget代码。
import 'package:flutter/material.dart';
class {{#pascalCase}}{{name}}{{/pascalCase}} extends StatelessWidget {
const {{#pascalCase}}{{name}}{{/pascalCase}}({Key? key}) : super(key: key);
{{#routable}}
static PageRoute route() {
return MaterialPageRoute(builder: (context) => const {{#pascalCase}}{{name}}{{/pascalCase}}());
}
{{/routable}}
@override
Widget build(BuildContext context) {
// TODO: implement build
return const SizedBox();
}
}
这里我们定义了一个名为name的无状态Widget,并使用pascalCase lambda来确保它是一个有效的类名。我们还使用了mustache部分来定义一个静态路由函数,只有当变量routable为真时才会出现。
就这样,现在无论何时我们想生成一个新的部件,我们都可以使用mason make widget。
$ mason make widget
name: dash container
routable: true
✓ Made brick widget (12.5ms)
✓ Generated 1 file(s):
dash_container.dart (new)
然后我们可以看一下dash_container.dart中生成的代码。
import 'package:flutter/material.dart';
class DashContainer extends StatelessWidget {
const DashContainer({Key? key}) : super(key: key);
static PageRoute route() {
return MaterialPageRoute(builder: (context) => const DashContainer());
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return const SizedBox();
}
}
如果我们想要一个不可路由的新部件,我们可以将可路由设置为假。
$ mason make widget
name: flutter box
routable: false
✓ Made brick widget (16.8ms)
✓ Generated 1 file(s):
flutter_box.dart (new)
如果我们看一下新生成的flutter_box.dart,我们应该看到没有定义路由方法。
import 'package:flutter/material.dart';
class FlutterBox extends StatelessWidget {
const FlutterBox({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return const SizedBox();
}
}
下一步是什么
我们正在积极开发一些新功能,包括对全局模板和模板扩展的支持。你可以去mason repo查看进展,提供反馈,并探索其他例子。
祝你模板制作愉快!