- 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.
Unresolved questions