[Pre-RFC]: cargo new templates
-
Feature Name:
cargo_new_project_from_template
-
Start Date: 2020-04-01
-
RFC PR: rust-lang/rfcs#0000
-
Rust Issue: rust-lang/cargo#3506
Summary
Add the ability to pass a template to cargo new
when creating a new project.
Add an interactive mode to cargo new
if it is run without arguments. This would take the user through a series of questions(i.e. Name, initialize git repo, include README
, etc.)
Motivation
We’re doing this for two reasons. One, there is a disagreement between members of the community on whether or not the default cargo new
template should include a README
. The hope is the interactive mode would allow the user to choose whether or not they want a README
.
The other is allowing users to create new projects using their own templates.
The expected outcomes are:
-
a more user-friendly new project workflow (interactive mode)
-
support for
README
out of the box -
support community-member-made templates
Guide-level explanation
Let’s create a new project using Cargo. Navigate to your projects directory (or wherever you decided to store your code). Then, on any operating system, run the following:
cargo new
Cargo will run you through its interactive mode and ask you the following questions:
-
Project Name: <write the name of the project, default: hello_cargo>
-
Binary or library: <write “bin” or “lib”, default: bin>
-
Initialize git repo: <write y or n, default: y>
-
Create README: <write y or n, default: y>
If you want to skip the questions and use the defaults, you can pass the flag -y
or --yes
to the cargo new
command like so:
cargo new -y
You can also skip questions by passing the name of the project to the command:
cargo new my_project
Once you become more familiar with Rust, you may have your preferred project folder structure. For this, you might be interested in creating a template. The cargo new
command supports templates via git repositories. You can use it by running:
cargo new <name-of-project> <template-repository-URL>
Reference-level explanation
Running cargo new
without any flags will initialize an interactive mode, similar to how cargo-generate
works. The user will be prompted for the questions and provide input. Once the input is collected, cargo
will create the project and add the files.
We will add a check for the flag -y
/--yes
. If this is passed, we will skip the questions and provide the defaults.
If a name is provided after cargo new
without a URL to a template, it will follow the behavior of the -yes
flag.
If a name is provided after cargo new
along with a URL to a template, Cargo will create a directory with the provided name and copy the files from the template into the new directory.
Drawbacks
Don’t fix it if it’s not broken
This introduces unnecessary complexity to the cargo
project. Creating a new project with cargo new
suffices. Users can add a README.md
or modify the project without much hassle after creating a new project.
Currently, the cargo-generate
project solves the template issue. The cost of bringing this functionality into the core features of cargo
may be more than the benefits it would bring.
Unmaintained templates -> negative effect on the community
With cargo
supporting templates, this may lead to a large influx of community-created templates. Over time, this will grow and many will go unmaintained. When community members try to use these templates, it may lead to issues that could have a hurt on the community.
Rationale and alternatives
This is the best design because it keeps it simple while providing an upgraded UX to both users using the default template and users using their own templates. The interactive mode will be helpful for those who are less familiar with CLIs (i.e. they might not realize they can configure their project with specific flags).
Interactive mode will also encourage documentation out of the box by asking if the user would like a README.md
created for their new project.
The templates are kept simple. Cargo can look at a git repository and copy the files over. This solution provides the simplest implementation without overcomplicating things.
The impact of not doing this is:
-
not encouraging users to include
README
s in their project -
asking users to reach for other tools to use their own templates
Prior art
Does this exist in other programming languages?
Looking at other programming communities, similar implementations exist.
JavaScript
In the JS community, two similar concepts have been implemented.
npm init
This initializes your package.json
(same as Cargo.toml
). It asks a series of questions then provides you with a pacakge.json
filled out. The difference is that it only creates this file and no other files.
Note you can skip the questionnaire by -y
/--yes
flags.
npx create-<initializer>
The npm CLI also added a convention that allows you to initialize a project for any package following the convention: create-<initializer>
which can then be used to generate a new project with npx
(similar to npm init
). This has been implemented by popular projects such as React and Next.
gatsby new
Another JavaScript framework called Gatsby.js has a command that feels most similar to cargo new
, which is gatsby new
. Here is how it works:
-
gatsby new
with no flags/arguments runs an interactive shell asking for the name of your project and which starter/template to use -
gatsby new [<site-name> [<starter-URL>]]
can also start a new project using a URL to a starter (template) from GitHub. Example
gatsby new my-awesome-blog-site https://github.com/gatsbyjs/gatsby-starter-blog
npx degit sveltejs/template my-svelte-project
The Svelte framework follows a similar pattern to Gatsby. It uses a project scaffolding tool called degit
. It follows the pattern npx degit <user/repo> <name-of-project>
. You can read more about it in the README
.
Python
paster
It appears there is a pip
package created by the community called pastescript
, which, “[creates] file layouts for packages.” You can use it by running:
paster create --template=basic_package MyPackage
Ruby
bundle gem my_app
This runs through an interactive shell that asks about tests, a license, a code of conduct and it creates a README
for you. Read more here.
rails new my-app
Ruby on Rails, a popular framework in the Ruby community, includes a script to scaffold out a new project, which includes a README.md
.
Go
dep init
Creates a new Go project and includes the following: Gopkg.toml
Gopkg.lock
vendor/
. Read more here.
go mod init
Creates a new Go module, which adds the go.mod
file. Read more here.
ReasonML
bsb -init my-new-project -theme basic-reason
Using BuckleScript, you can initialize a basic Reason project. This includes the following: README.md
bsconfig.json
node_modules
package.json
src
and is similar to cargo new
.
Swift
swift package init
This creates a new Swift package. It includes the following: Package.swift
README.md
Sources/
Tests
. Read more here.
Has the community suggested this before? Are there crates that solve this problem already?
A similar RFC for cargo templates was written back in April 2017 and shared on the internals forum. It seemed like there were a lot of discussions, but no consensus reached.
The community has also created two crates that solve similar problems:
-
cargo-readme
: GenerateREADME.md
from doc comments. -
cargo-generate
: a developer tool to help you get up and running quickly with a new Rust project by leveraging a pre-existing git repository as a template
In addition, there was a lot of discussion both from the Cargo team and the community on this issue. It has been decided that there still remains disagreement among both the Cargo team and the community on how to solve this, hence why this RFC seems to be the logical next step.
What lessons can we learn from what other communities have done here?
There are pros and cons to having templates or some type of template ecosystem. I think the biggest question is **who will maintain them?**It may not be directly related, but it's an important point to consider should templates be added to cargo new
.
If we return to our examples from the JavaScript industry, there are two that stick out:
Community maintained templates
In the Gatsby.js community, there are +300 starters. Only a select few are maintained by the Gatsby.js core team. The rest are added by community members.
Pros
- Community members can contribute
- There is a wilder selection of options
Cons
- Members can abandon their starters which can negatively impact the community
Core team maintained templates
Revisiting the create-react-app
and the create-next-app
templates, those are maintained by core team members (i.e. a select group of individuals). There are some variations to the templates (i.e. regular vs. TypeScript).
Pros
- Higher-quality
- Creates a “standard”
- Reliable
Cons
- Requires dedicated maintainers
- Less community involvement (beyond direct contributions)
Unresolved questions
Some questions that may require further discussion depending on how this RFC goes.
Questions that fall in the scope of this RFC:
-
What should the
README
include that is created for the default template? -
Where do the docs need to be updated?
-
What security measures need to be accounted for when Cargo clones from third-party templates? (i.e. what if a template contains a malicious file?)
Questions that could be answered after the implementation:
-
What guidelines should the Cargo team provide for creating templates?
-
Will there be any “official” templates?
-
Should templates live in a central place? (i.e. in one repo in the
rust-lang
org)
Related issues that are considered out of scope for this RFC:
-
using local templates
-
using templates from private repos
Future possibilities
Nothing at the moment beyond the questions I noted for after the implementation.