コンテンツにスキップ

cargo generate を触ってみた

cargo generate とは

cargo generate

cargo-generate は、既存の git リポジトリをテンプレートとして利用することで、新しい Rust プロジェクトを迅速に起動して実行できるようにする開発者ツールです。

Cargo-generate は Shopify の Liquid テンプレート言語、 フック スクリプトには Rhai 、プレースホルダーには正規表現を使用します。

setup

cargo install cargo-generate

usage

1
2
3
4
5
6
7
cargo generate username-on-github/mytemplate
# is the same as
cargo generate gh:username-on-github/mytemplate
# is the same as
cargo generate --git https://github.com/username-on-github/mytemplate.git
# for gitlab.com
cargo generate gl:username-on-gitlab/mytemplate

テンプレートレポジトリにサブディレクトリを作成し、その配下にテンプレートを配置することで複数のテンプレートの中からどのテンプレートを使うか選ぶことができる。

cargo-generate.toml
[template]
sub_templates = ["folder1", "folder2"]

そのほかにも--initフラグを使うとカレントディレクトリにテンプレートを展開できたり、--path LOCAL_PATH/mytemplateのようにすることでローカルのテンプレートを指定できる。

template の記述

Liquid テンプレート言語を使ってテンプレートを記述する。 テンプレートの中で{{variable}}のように記述すると、cargo generateの実行時にユーザー入力を求めることができる。 また、{{variable}.rsのようなファイルを作るとテンプレート生成時に入力値を適用したファイルが生成される。 if 分岐や for 文による繰り返しもできる。hooksで init、pre、post のフックを設定することもできる。

組み込みカスタムのプレースホルダーがある。カスタムのプレースホルダーは次のように使う

cargo-generate.toml
[placeholders.hypervisor]
type = "string"
prompt = "What hypervisor to use?"
choices = ["uhyve", "qemu"]
default = "qemu"

[placeholders.network_enabled]
type = "bool"
prompt = "Want to enable network?"
default = true
src/main.rs
{% if network_enabled %}
use std::net::TcpListener;

fn main() {
    let listener = TcpListener::bind("0.0.0.0:8080").unwrap();
    loop {
        let (conn, addr) = listener.accept().unwrap();
        println!("Incoming Connection from {}", addr);
        std::io::copy(&mut &conn, &mut &conn).unwrap();
    }
}
{% else %}
fn main() {
    println!("Hello Rusty Hermit 🦀");
}
{% endif %}

Cargo.toml も対象。

Cargo.toml
[package]
# the usual stuff

[dependencies]
{% if crate_type == "bin" %}
structopt = "0.3.21"
{% endif %}
# other general dependencies

{% if crate_type == "bin" %}
[[bin]]
path = "src/main.rs"
name = "{{crate_name}}-cli"
{% endif %}

使ってみた感想

プロジェクトテンプレートとして Cookiecutter や copier があるがそれの Rust 版という感じ。

参考