[Dart翻译]用Mason生成代码

1,121 阅读5分钟

对开源工具Mason的概述,它可以自动生成代码。

image.png

原文地址: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工具,你可以直接从你的终端运行它。

开始使用

Mason可以通过pub.devhomebrew来安装。

# 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查看进展,提供反馈,并探索其他例子。

祝你模板制作愉快!


www.deepl.com 翻译