- Feature Name: cargo-template
- Start Date: 28-03-2017
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)
Summary
This RFC proposes Cargo Templates to generate new projects from existing prototypes.
A simple version was already merged (but not released in Stable) without an RFC, but some useful feedback has underlined the need to have more feedback in the design phase.
Motivation
Writing boiler plate is no fun. Starting a new project often involves writing a lot of repeated code, copying a LICENSE file into place, setting crate dependencies, filling out a hello world example for the crate. In the case of a daemon, setting up the main event loop and signal handling is also something that requires filling out.
We propose Cargo Templates to generate new projects from existing prototypes. This lets people start projects more quickly by not having to type out boiler plate each time.
Also, because the templates can be managed as a repository, they can work as way to spread up to date âbest practicesâ through curated templates.
Detailed design
The design of templates consists of two sides. The interface for users, and the interface for template writers.
User Interface
Users creating a new project will use templates as follows:
$ cargo new foo --template https://gitrepo.com/user/rust-project-template
Template repositories may also have multiple templates within them. Therefore you can specify a subdirectory: may also have sever
$ cargo new foo --template https://gitrepo.com/user/rust-project-templates --template-subdir cmdline
Templates can also be taken from file://
or from the local filesystem (using a
path). When using file://
or a path, it does not make sense to use
--template-subdir
but it
Template Writer Interface
Templates will consist of two parts: a Template.toml
file and the files
themselves. The Template.toml
will consist of two parts: actions
and
renames
.
Actions
Templates actions consist of templating a file or copying a file into place. Copying a file into place is used for binary blobs or files that do not need to be templated (e.g. they may be templates themselves).
Renames
Renames are for files that conflict with files in the template. For example,
README.md
and Template.toml
(if you were to make a template of a template).
A rename entry is a list of <input-name>
= output-name>
Example Template.toml
[actions]
template = ["src/main.rs", "src/cmd/new.rs"]
copy = [".travis.yml", "some-template.handlebars"]
[renames]
"README.md.in" = "README.md"
"Template.toml.in" = "Template.toml"
Template helpers
Some strings need to be escaped in different ways. For example a string in a
toml file needs \"
when escaping quotes and nothing for <
. But html uses
<
for <
. This is done by the template system with toml-escape
and
html-escape
:
[package]
name = "{{name}}"
version = "0.1.0"
authors = [{{toml-escape author}}]
Template strings
There are initially three template strings:
-
name
: name of the project. -
author
: author of the project as retrieved from cargo settings or git configuration. -
date
: used for injecting the date for e.g. copyright information into the template.
How We Teach This
This should be documented in the crates.io documentation for the Cargo.toml manifest format.
Drawbacks
This adds some complication into Cargo which could possibly be better suited to an external tool, or one that is installed (e.g. clippy, etc).
Alternatives
Templating systems exist. They tend to be focused on their own language communities. e.g. Cookiecutter appears to focus on Python, while Boilr appears to focus on Go.
Creating a template tool that works as a cargo subcommand which could be
installed. This is not in line one of the goals of discoverability as new users
who want to generate a hello world project would have no simple way to see that
the template subcommand exists. However, clippy
surely has a dedicated
following.
We can use other template libraries. For example, moustache or Askama.