Introduction
cargo, make me a project
cargo-generate
is 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.
cargo-generate uses Shopify's Liquid template language, Rhai for hook scripts and regex for placeholders.
Due to the use of Shopify's Liquid, cargo-generate
special cases files with the file-ending
.liquid
, by simply removing the file-ending when processing the files. If you, as a template
author, truly want the .liquid
file-ending, you need to repeat it twice!
For example: The file README.md.liquid
will be renamed after templating to README.md
.
If README.md
already exists, then it will be overwritten to include the contents of README.md.liquid
.
Here's an example of using cargo-generate
with this template:
Installation
Using cargo-generate
with vendored libgit2
and system's OpenSSL
By default, cargo-generate uses vendored sources for libgit2
and OpenSSL that is installed on your system.
cargo install cargo-generate
This requires the following dependencies on your system:
libssl-dev
(this could also be named openssl)
Using cargo-generate
with vendored OpenSSL
However, you can also opt in to use a vendored OpenSSL version. So that you don't have to have OpenSSL installed and built it on the spot.
this would require the following dependencies on your system, as documented by the openssl
crate:
- A C compiler (
gcc
, for example) perl
andperl-core
make
cargo install cargo-generate --features vendored-openssl
Using cargo-generate
with system's libgit2
and system's OpenSSL
You can opt-out of vendored libraries and use libgit2
and OpenSSL from your system
by building cargo-generate without the default dependencies.
cargo install cargo-generate --no-default-features
This will require the following dependencies on your system:
pkg-config
libgit2
libssl-dev
(this could also be named openssl)
Using pacman
(Arch Linux)
cargo-generate
can be installed from the extra repository for Arch Linux:
pacman -S cargo-generate
Manual Installation
- Download the binary tarball for your platform from our releases page.
- Unpack the tarball and place the binary
cargo-generate
in~/.cargo/bin/
Usage
Standard usage is to pass a --git
flag to cargo generate
or short cargo gen
. This will prompt you to enter the name of your project.
⚠️ NOTE:
cargo gen
requires a cargo alias configuration
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
If you have your templates not GitHub then you can leverage the lazy abbreviation prefixes:
# for gitlab.com
cargo generate gl:username-on-gitlab/mytemplate # translates to https://gitlab.com/username-on-gitlab/mytemplate.git
# or for bitbucket.org
cargo generate bb:username-on-bitbucket/mytemplate # translates to https://bitbucket.org/username-on-bitbucket/mytemplate.git
# or for github.com
cargo generate gh:username-on-github/mytemplate # translates to https://github.com/username-on-github/mytemplate.git
# or for git.sr.ht
cargo generate sr:username-on-sourcehut/mytemplate # translates to https://git.sr.ht/~username-on-sourcehut/mytemplate (note the tilde)
Both will expand to the https
urls of the repo with the suffix .git
in the URL.
You can also pass the name of your project to the tool using the --name
or -n
flag:
cargo generate --git https://github.com/username-on-github/mytemplate.git --name myproject
Templates in subfolders
If the repository or path specified for the template contains multiple templates (Any sub-folder that contains a cargo-generate.toml
file), cargo-generate
will ask for the specific folder to be used as the template.
Multiple sub-templates can also be configured in the cargo-generate.toml
file like this:
[template]
sub_templates = ["folder1", "folder2"]
Doing so also sets the order when cargo-generate
asks what to expand, while the first option will be the default.
The specific subfolder in the git repository may be specified on the command line like this:
cargo generate --git https://github.com/username-on-github/mytemplate.git <relative-template-path>
⚠️ NOTE: When using the
subfolder
feature,cargo-generate
will search for thecargo-generate.toml
file in the subfolder first, traversing back towards the template root in case it is not found.
Generating into current dir
If the user wants to generate a template straight into the current folder, without creating a subfolder for the contents and without attempting to initialize a .git
repo or similar, the --init
flag can be used.
cargo generate --init --git https://github.com/username-on-github/mytemplate.git
⚠️ NOTE:
cargo-generate
will not allow any existing files to be overwritten and will fail to generate any files should there be any conflicts.
Generating using a local template
You can generate a project using a local template via the --path
flag:
git clone https://github.com/username-on-github/mytemplate.git $HOME/mytemplate # Clone any template
cargo generate --path $HOME/mytemplate # Use it locally
⚠️ NOTE:
cargo-generate
will not allow to use the association--path
and--git
flags.
Http(s) proxy
New in version 0.7.0 is automatic proxy usage. So, if http(s)_PROXY env variables are provided, they will be used for cloning a http(s) template repository.
Git over SSH
New in version 0.7.0 is the support for both public and private and ssh git remote urls.
New in version 0.22.0 is the support for ssh-agent
on Windows and interactively asking for passphrase for password protected keys on *Nix and macOS.
There are 2 different git over ssh urls, one with the git@
prefix and one with the ssh://
prefix. Both are supported. Please note that the ssh://
prefix url uses a path where the git@
prefix uses a colon at the user/github-org level. For example:
git@github.com:rustwasm/wasm-pack-template.git
# vs
ssh://git@github.com/rustwasm/wasm-pack-template.git
Both those urls can also be used in the .gitconfig
insteadOf configuration, see more in the section below.
cargo generate --git git@github.com:rustwasm/wasm-pack-template.git --name mywasm
Authentication using ssh-agent
New in version 0.15.1 is the ssh-agent
usage for password protected keys. It's also the default mechanism on Windows.
On Windows
ssh-agent
is the default and also the only possibility to get git+ssh working.
Please follow this guide to get ssh-agent
configured on windows.
On *Nix and macOS
If you omit the identity file (read the next paragraph) OR a provided identity file does not exist, then the default is to use ssh-agent
.
Ssh identity file defaults
Since version 0.22.0 the default mechanism on unix/macOS is to use the function add_default_ssh_keys
that adds a couple of default keys to look up first.
// the list used..
let candidates = [
"id_rsa",
"id_ecdsa,",
"id_ecdsa_sk",
"id_ed25519",
"id_ed25519_sk",
"id_dsa",
];
Custom ssh identity file (private key)
However, if you use a different file, you can pass a custom ssh identity with via -i | --identity
like -i ~/.ssh/id_rsa_other
as argument.
If the file is passphrase protected cargo-generate will ask for the passphrase interactively.
If you permanently want to use a custom identity file, you can configure it in the cargo-generate config file like this:
# an extract of ~/.cargo/cargo-generate.toml
[defaults]
# note that `~/` and `$HOME/` are going to be expanded to the full path seamlessly
ssh_identity = "~/.ssh/id_rsa_other"
# that is equivalent to
ssh_identity = "$HOME/.ssh/id_rsa_other"
# that is equivalent to
ssh_identity = "/home/john/.ssh/id_rsa_other"
⚠️ NOTE: that the cli argument
-i
always overrules thessh_identity
from the config file.
.gitconfig
and insteadOf
configuration
⚠️ New in version 0.22.0
git supports a magic trick to rewrite urls on the fly. This is done by adding a url.<base>.insteadOf
configuration to your .gitconfig
file.
In cargo-generate this is supported as well.
For example, if you prefer the ssh over the https urls and you want to use cargo-generate
with it, you can add the following to your .gitconfig
:
# ~/.gitconfig
[url "git@github.com:"]
insteadOf = https://github.com/
and then you can use cargo-generate
with the https
url:
RUST_LOG=debug cargo generate https://github.com/Rahix/avr-hal-template.git
🔧 gitconfig 'insteadOf' lead to this url: git@github.com:Rahix/avr-hal-template.git
...
In this case please notice the ssh url is git@github.com:
if you prefer the more explicit notation you can also write it like this:
# ~/.gitconfig
[url "ssh://git@github.com/"]
insteadOf = https://github.com/
that would lead to the same result, with slightly different url:
RUST_LOG=debug cargo generate https://github.com/Rahix/avr-hal-template.git
🔧 gitconfig 'insteadOf' lead to this url: ssh://git@github.com/Rahix/avr-hal-template.git
...
⚠️ NOTE:
RUST_LOG=debug
would allow you to see the rewritten url in the output.
In cases where you have a different .gitconfig
location, you can use the --gitconfig
argument to specify the path to the .gitconfig
file, like this:
$ cd /path/to/my/workspace
$ cat .gitconfig
[url "git@github.com:"]
insteadOf = https://github.com/
$ cargo generate --gitconfig ./.gitconfig https://github.com/Rahix/avr-hal-template.git
Favorites
Favorite templates can be defined in a config file, that by default is placed at $CARGO_HOME/cargo-generate.toml
or $CARGO_HOME/cargo-generate
.
To specify an alternate configuration file, use the --config <config-file>
option.
⚠️ NOTE: A relative
--config
option, will be relative to the template root during expansion.
Each favorite template is specified in its own section, e.g.:
[favorites.demo]
description = "<optional description, visible with --list-favorites>"
git = "https://github.com/rustwasm/wasm-pack-template"
branch = "<optional-branch>"
subfolder = "<optional-subfolder>"
vcs = "<optional: None|Git>"
init = optional true|false
overwrite = optional true|false
Values may be overridden using the CLI arguments of the same names (e.g. --subfolder
for the subfolder
value).
Note: Specifying init = true
has the effect of forcing the template to exhibit behaviour as if --init
is specified on the
commandline, as there is no counter-option!
Note: Specifying overwrite = true
has the effect of allowing the template to always overwrite files as there is no counter-option!
When favorites are available, they can be generated simply by invoking:
cargo gen <favorite>
or slightly more involved:
cargo generate demo --branch mybranch --name expanded_demo --subfolder myfolder
⚠️ NOTE: when
<favorite>
is not defined in the config file, it is interpreted as a git repo like as if--git <favorite>
Templates
Placeholders
Templates are git repositories whose files can contain placeholders. A placeholder can be seen as a variable that is substituted by another value upon expansion of the template.
cargo-generate
supports both builtin variables/placeholders and custom defined ones.
Additionally, all filters and tags of the liquid template language are supported.
For more information, check out the Liquid Documentation on Tags
and Filters
.
You can use those placeholders in the file and directory names of the generated project.
For example, for a project named awesome
, the filename {{project_name}}/{{project_name}}.rs
will be transformed to awesome/awesome.rs
during generation.
Only files that are not listed in the exclude settings will be templated.
⚠️ NOTE: invalid characters for a filename or directory name will be sanitized after template substitution. Invalid is e.g.
/
or\
.
⚠️ Deprecated in favor of using ignore in
cargo-generate.toml
You can also add a
.genignore
file to your template. The files listed in the.genignore
file will be removed from the local machine whencargo-generate
is run on the end user's machine. The.genignore
file is always ignored, so there is no need to list it in the.genignore
file.
Additional liquid
filters
Following are filters that cargo-generate
expands the liquid
language with.
-
rhai
Tries to run the argument as a
rhai
script. Whatever the script returns will be the output of the filter.Example Liquid:
Here we try to run a rhai script: {{"script_name.rhai" | rhai}}
⚠️ NOTE:
Liquid
does not support failing filters, thus if the script fails for any reason,cargo-generate
will simply print a warning message to stderr, andLiquid
will leave the substitution in its original form. -
kebab_case
"We are going to inherit the earth."
=>"we-are-going-to-inherit-the-earth"
-
lower_camel_case
"It is we who built these palaces and cities."
=>"itIsWeWhoBuiltThesePalacesAndCities"
-
pascal_case
Same as
upper_camel_case
-
shouty_kebab_case
"We are going to inherit the earth."
=>"WE-ARE-GOING-TO-INHERIT-THE-EARTH"
-
shouty_snake_case
"That world is growing in this minute."
=>"THAT_WORLD_IS_GROWING_IN_THIS_MINUTE"
-
snake_case
"We carry a new world here, in our hearts."
=>"we_carry_a_new_world_here_in_our_hearts"
-
title_case
"We have always lived in slums and holes in the wall."
=>"We Have Always Lived In Slums And Holes In The Wall"
-
upper_camel_case
"We are not in the least afraid of ruins."
=>"WeAreNotInTheLeastAfraidOfRuins"
Templates by the community
It's encouraged to classify your template repository with a GitHub topic labeled cargo-generate
.
So that every developer can find the template via cargo-generate topic on GitHub.
If you have a great template, please tag your repository with the topic and tweet about it by including the hashtag #cargogenerate
(since twitter does not support hashtags with -
).
⚠️ Note: the list of currently available templates is still available, but is now deprecated.
Example for --bin
and --lib
A template could be prepared in a way to act as a binary or a library. For example the Cargo.toml
might look like:
[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 %}
Now a user of this template could decide weather they want the binary version by passing --bin
or use only the library version by passing --lib
as a command line argument.
Builtin placeholders
cargo-generate
supports a number of builtin placeholders for use in templates.
These placeholders can be used directly in files using the Liquid language, or from Rhai scripts using the syntax:
variable::get("placeholder name")
Builtin placeholders are:
authors
- this will be filled in by a function borrowed from Cargo's source code, that determines your information from
Cargo's configuration. It will either be on the form
username <email>
or just plainusername
.
- this will be filled in by a function borrowed from Cargo's source code, that determines your information from
Cargo's configuration. It will either be on the form
project-name
- this is supplied by either passing the
--name
flag to the command or working with the interactive CLI to supply a name. It can be provided in snake_case or dash-case, in all other cases it is converted to dash-case. - it can also be supplied via the environment variable
CARGO_GENERATE_VALUE_PROJECT_NAME
when running in--silent
mode⚠️ Note: the
--force
flag allows you to use the project name as it is given, without adjusting. Please use it carefully.
- this is supplied by either passing the
crate_name
- the snake_case_version of
project-name
- the snake_case_version of
crate_type
- this is supplied by either passing the
--bin
or--lib
flag to the command line, contains eitherbin
orlib
,--bin
is the default
- this is supplied by either passing the
os-arch
- contains the current operating system and architecture ex:
linux-x86_64
- contains the current operating system and architecture ex:
username
- this will be filled in by a function borrowed from Cargo's source code, that determines your information from Cargo's configuration.
within_cargo_project
- A boolean with the value
true
if the template is being expanded inside aCargo
project. It's a simple matter of whetherCargo.toml
is present in any parent folder.
- A boolean with the value
is_init
- A boolean that reflects the value of the
--init
parameter ofcargo-generate
.
- A boolean that reflects the value of the
Usage example
// README.md
This awesome crate `{{ crate_name }}` is brought to you by {{ authors }}.
Template Defined Placeholders
Template defined placeholders offer a powerful way for template authors to customize project templates and streamline project creation. In addition to defining placeholders directly within template files, users can also define placeholders in the cargo-generate.toml
file, providing additional flexibility and customization options.
Defining Placeholders in cargo-generate.toml
To define placeholders in the cargo-generate.toml
file, template authors can specify them under the placeholders
section using the following syntax:
[placeholders]
placeholder_name = { prompt = "Enter your name", choices = ["Alice", "Bob"], default = "Alice", type = "string" }
placeholder_name
: The name of the placeholder.prompt
: The prompt message displayed to the user during project creation.choices
(optional): A list of predefined choices for the placeholder value.default
(optional): The default value for the placeholder if no user input is provided.regex
(optional and only for string-like types): The entered value is validated against this regex.type
: The data type of the placeholder value (see Supported Types).
Prompt, Choices, and Default Values
- Prompt: With the
prompt
will be displayed it to the user during project creation, prompting them to provide a value for the placeholder. - Choices: If
choices
are specified,cargo-generate
will present them as options to the user, restricting the input to the predefined choices and provide more convenience. - Default Value: If a
default
value is provided and the user does not provide input,cargo-generate
will use the default value for the placeholder.
Supported Types
cargo-generate
supports the following placeholder value types:
"string"
: Represents a string value."text"
: Represents a multiline string value. (terminated by hitting CTRL-D)"editor"
: Represents a multiline string value, collected from the user by a real terminal editor."bool"
: Represents a boolean value (true
orfalse
).
Example
Consider the following cargo-generate.toml
file:
[placeholders]
project_name = { prompt = "Enter project name", default = "my_project", type = "string" }
environment = { prompt = "Which environment?", choices = ["dev", "prod"], default = "dev", type = "string"}
use_git = { prompt = "Initialize Git repository?", default = true, type = "bool" }
phone_number = { prompt = "What's your phone number?", type = "string", regex = "^[0-9]+$" }
During project creation, cargo-generate
will prompt the user to provide values for project_name
, use_git
and phone_number
using the specified prompts, choices, and default values.
Further phone_number
is validated against the provided regex, hence it can only contain digits.
Conclusion
Template defined placeholders, defined in the cargo-generate.toml
configuration file, offer powerful customization options for project templates. By specifying prompts, choices, default values, and supported types, template authors can create intuitive and flexible project scaffolding experiences, enhancing developer productivity and project consistency.
Default values for placeholders
For automation purposes the user of the template may provide the values for the keys in the template using one or more of the following methods.
The methods are listed by falling priority.
--define
or -d
flag
The user may specify variables individually using the --define
flag.
cargo generate template-above -n project-name -d hypervisor=qemu -d network_enabled=true
--template_values_file
flag
The user of the template may provide a file containing the values for the keys in the template by using the --template-values-file
flag.
⚠️ NOTE: A relative path will be relative to current working dir, which is not inside the expanding template!
[values]
hypervisor = "qemu"
network_enabled = true
Individual values via environment variables
Variables may be specified using environment variables. To do so, set the env var CARGO_GENERATE_VALUE_<variable key>
to the desired value.
set CARGO_GENERATE_VALUE_HYPERVISOR=qemu
set CARGO_GENERATE_VALUE_NETWORK_ENABLED=true
cargo generate template-above
⚠️ Windows does not support mixed case environment variables. Internally,
cargo-generate
will ensure the variable name is all lowercase. For that reason, it is strongly recommended that template authors only use lowercase variable/placeholder names.
Template values file via environment variable
The user may use the environment variable CARGO_GENERATE_TEMPLATE_VALUES
to specify a file with default values.
For the file format, see above.
Default values
Default values may be specified in the config file (specified with the --config
flag, or in the default config file $CARGO_HOME/cargo-generate
)
Example config file:
[values]
placeholder1 = "default value"
[favorites.my_favorite]
git = "https://github.com/username-on-github/mytemplate.git"
[favorites.my_favorite.values]
placeholder1 = "default value overriding the default"
placeholder2 = "default value for favorite"
Further examples
You can find further examples in the example-templates folder you will find further examples that provide some template provided placeholders.
Ignoring files
The template author may choose to ignore files completely, by including an ignore
list in the cargo-generate.toml
file.
Example:
[template]
ignore = [
"file",
"or folder",
"to be ignored"
]
Both files and folders may be ignored using this method, but currently wildcards are not supported.
Note that cargo-generate
checks for which files to ignore after the removal of any .liquid
file extensions.
Meaning; Setting ignore
to ["file.txt"]
will result in the ignoring of a file named file.txt.liquid
.
Include / Exclude
Templates support a cargo-generate.toml
, with a "template" section that allows you to configure the files that will be processed by cargo-generate
.
The behavior mirrors Cargo's Include / Exclude functionality, which is documented here.
If you are using placeholders in a file name, and also wish to use placeholders in the contents of that file,
you should setup your globs to match on the pre-rename filename.
[template]
include = ["Cargo.toml"]
# include and exclude are exclusive, if both appear we will use include
exclude = ["*.c"]
⚠️ NOTE:
exclude
only makescargo-generate
ignore anyliquid
tags in the file. In order to exclude a file from being copied to the final dir, see ignoring files.
The cargo-generate.toml
file should be placed in the root of the template. If using the subfolder
feature, the root is the subfolder
inside the repository, though cargo-generate
will look for the file in all parent folders until it reaches the repository root.
Require cargo-generate
version from template
Available since version 0.9.0
Using the supported cargo-generate.toml
file, the template author may setup version requirements towards cargo-generate
.
[template]
cargo_generate_version = ">=0.9.0"
The format for the version requirement is documented here.
Conditional template settings
Using cargo-generate.toml
, values and some [Rhai
] syntax, the template author can make certain conditional decisions before expansion of the template.
include
, exclude
, ignore
and placeholders
can all be used in sections that are only used based upon the value of one or more values, possibly input by the user using the interactive prompt (if the values in question are defined as placeholders in the non-conditional section).
Using the following example, cargo-generate
will ask for the license
, and depending on the --lib
| --bin
flags it'll as for the hypervisor
and network_enabled
values. It will then continue to expand the template, ignoring the src/main.rs
file (and thus excluding it from the output) in case --lib
was specified.
The example is broken up in order to explain each section.
[template]
cargo_generate_version = ">=0.10.0"
# ignore = [ "..." ]
# include = [ "..." ]
# exclude = [ "..." ]
...
This first part declares that the template requires cargo-generate
version 0.10 or higher. In this same section the template author may also specify the following 3 lists:
ignore
Files/folders on this list will be ignored entirely and are not included in the final output.include
These files will be processed forLiquid
syntax by the template engine.exclude
These files will not be processed for anyliquid
syntax. The files will be in the final output.
...
[placeholders]
license = { type = "string", prompt = "What license to use?", choices = ["MIT", "Unrestricted"], default = "MIT" }
...
This is the section for the default placeholders. These are variable definitions that cargo-generate
knows about and will query for if they are not provided e.g. on the commandline (see [Default-values-for-placeholders]).
The section should contain at least all variables used for any conditions (unless it's an automatic variable such as crate_type
). All variables that are not specific to a condition are recommended to go here as well.
Here we simply define a variable license
for selecting the desired license type.
...
[conditional.'crate_type == "lib"']
ignore = [ "src/main.rs" ]
# include = [ "..." ]
# exclude = [ "..." ]
...
This is a conditional block.
Here it has been chosen that the src/main.rs
file must be ignored when the crate_type
variable is equal to the string "lib"
.
...
[conditional.'crate_type != "lib"'.placeholders]
hypervisor = { type = "string", prompt = "What hypervisor to use?", choices = ["uhyve", "qemu"], default = "qemu" }
network_enabled = { type = "bool", prompt = "Want to enable network?", default = true }
...
This block uses the same condition as the last, but it defines some extra placeholders - that is, is defines the variables hypervisor
and network_enabled
, so that cargo-generate
may ask for their values.
⚠️
cargo-generate
will ask for values using the placeholders defined in[placeholders]
before evaluating the conditional sections.Placeholder values defined in conditional sections cannot be used to enable/disable further conditional sections, they can however still be used in the actual template!
...
[conditional.'license == "MIT"']
ignore = [ "LICENSE-UNRESTRICTED.txt" ]
# include = [ "..." ]
# exclude = [ "..." ]
[conditional.'license == "Unrestricted"']
ignore = [ "LICENSE-MIT.txt" ]
# include = [ "..." ]
# exclude = [ "..." ]
This last conditional block is simply to ignore the unneeded license files, based upon the users choice for the license
variable.
⚠️ Note that
include
andexclude
are still mutually exclusive even if they are in different, but included, conditional sections.
Init/Pre/Post Scripts
cargo-generate
can run scripts in the Rhai
language as part of the template expansion.
Doing so requires the template is configured to use hooks, which can be used at specific times during template expansion.
To configure the use of hooks, write a hooks
section in the cargo-generate.toml
file.
[hooks]
#init = ["init-script.rhai"]
#pre = ["pre-script.rhai"]
#post = ["post-script.rhai"]
Hook types
Init
-
Init hooks are executed before anything else.
-
The variables
crate_type
/authors
/username
/os-arch
andis_init
are available. -
The variable
project-name
may be available.And only if
cargo-generate
was called with the--init
flag, in which case it is the raw user input. -
The variable
project-name
may be set - avoiding a user prompt!The variable will still be subject for case changes to fit with the rust/cargo expectations.
The
--name
parameter still decides the final destination dir (together with the the--init
flag), in order not to confuse the user.
Pre
-
Pre hooks are run after all placeholders mentioned in cargo-generate.toml has been resolved.
-
The hooks are free to add additional variables, but its too late to influence the conditional system.
This is a side effect of conditionals influencing the hooks - so placeholders need to be evaluated before the hooks are known.
Post
- Post hooks are run after template expansion, but before final output is moved to the final destination.
Why not later? Security, and the fact that a failing script still causes no errors in the users destination.
Rhai extensions
Besides the basic Rhai
features, these are the modules/behaviors defined:
Variables
get/set
-
variable::is_set(name: &str) -> bool
Returns true if the variable/placeholder has been set for the template
-
variable::get(name: &str) -> value
Gets any defined variable in the
Liquid
template object -
variable::set(name: &str, value: (&str|bool))
Set new or overwrite existing variables. Do not allow to change types.
Prompt
-
variable::prompt(text: &str, default_value: bool) -> value
Prompt the user for a boolean value
-
variable::prompt(text: &str) -> value
Prompt the user for a string value
-
variable::prompt(text: &str, default_value: &str) -> value
Prompt the user for a string value, with a default already in place
-
variable::prompt(text: &str, default_value: &str, regex: &str) -> value
Prompt the user for a string value, validated with a regex
-
variable::prompt(text: &str, default_value: &str, choices: Array) -> value
Prompt the user for a choice value
Files
-
file::exists(path: &str)
Test if a path exists
-
file::rename(from: &str, to: &str)
Rename one of the files in the template folder
-
file::delete(path: &str)
Delete a file or folder inside the template folder
-
file::write(file: &str, content: &str)
Create/overwrite a file inside the template folder
-
file::write(file: &str, content: Array)
Create/overwrite a file inside the template folder, each entry in the array on a new line
System
-
system::command(cmd: &str, args: Array) -> value
Execute a command on the system generating the project from a template.
The user will be prompted with
The template is requesting to run the following command. Do you agree? <command> <args>
unless the user uses the flag
--allow-commands
. If the user attempts to use the--silent
flag without the--allow-commands
flag will fail. -
system::date() -> Date
Get the date in UTC from the system as an object with the properties
year
,month
, andday
.
Other
abort(reason: &str)
: Abortscargo-generate
with a script error.
Changing case of strings
-
to_kebab_case(str: &str) -> String
"We are going to inherit the earth."
=>"we-are-going-to-inherit-the-earth"
-
to_lower_camel_case(str: &str) -> String
"It is we who built these palaces and cities."
=>"itIsWeWhoBuiltThesePalacesAndCities"
-
to_pascal_case(str: &str) -> String
Same as
to_upper_camel_case(str: &str) -> String
-
to_shouty_kebab_case(str: &str) -> String
"We are going to inherit the earth."
=>"WE-ARE-GOING-TO-INHERIT-THE-EARTH"
-
to_shouty_snake_case(str: &str) -> String
"That world is growing in this minute."
=>"THAT_WORLD_IS_GROWING_IN_THIS_MINUTE"
-
to_snake_case(str: &str) -> String
"We carry a new world here, in our hearts."
=>"we_carry_a_new_world_here_in_our_hearts"
-
to_title_case(str: &str) -> String
"We have always lived in slums and holes in the wall."
=>"We Have Always Lived In Slums And Holes In The Wall"
-
to_upper_camel_case(str: &str) -> String
"We are not in the least afraid of ruins."
=>"WeAreNotInTheLeastAfraidOfRuins"
Mini Example
In cargo-generate.toml
write a [hooks]
section:
[template]
cargo_generate_version = "0.10.0"
[hooks]
#init = [...]
pre = ["pre-script.rhai"]
#post = [...]
[placeholders]
license = { type = "string", prompt = "What license to use?", choices = ["APACHE", "MIT"], default = "MIT" }
Now, write the script in Rhai
, utilizing the cargo-generate
provided extensions:
// we can see existing variables.
// note that template and Rhai variables are separate!
let crate_type = variable::get("crate_type")
debug(`crate_type: ${crate_type}`);
let license = variable::get("license").to_upper();
while switch license {
"APACHE" => {
file::delete("LICENSE-MIT");
file::rename("LICENSE-APACHE", "LICENSE");
false
}
"MIT" => {
file::delete("LICENSE-APACHE");
file::rename("LICENSE-MIT", "LICENSE");
false
}
_ => true,
} {
license = variable::prompt("Select license?", "MIT", [
"APACHE",
"MIT",
]);
}
variable::set("license", license);
Template Authoring
Available since version 0.9.0
As a template author you're probably concerned about successful builds of your template.
Imagine a couple of months after your first template release, some new versions of any dependencies would break your template, and you would not even be aware of it?
The answer to this question is a vital build pipeline for your template project. This challenge got now much simpler to solve with the new official cargo-generate GitHub Action.
Here is an example:
tree .github
.github
└── workflows
└── build.yml
The content of build.yml
as a paste template:
name: Build Template
on:
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_dispatch
workflow_dispatch:
schedule:
- cron: '0 18 * * 5'
push:
branches: [ '*' ]
paths-ignore:
- "**/docs/**"
- "**.md"
jobs:
build:
runs-on: ubuntu-latest
env:
PROJECT_NAME: mytemplate
steps:
- uses: actions/checkout@v4
- uses: cargo-generate/cargo-generate-action@latest
with:
name: ${{ env.PROJECT_NAME }}
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
# we need to move the generated project to a temp folder, away from the template project
# otherwise `cargo` runs would fail
# see https://github.com/rust-lang/cargo/issues/9922
- run: |
mv $PROJECT_NAME ${{ runner.temp }}/
cd ${{ runner.temp }}/$PROJECT_NAME
cargo check
This is a very simple pipeline that builds weekly and on push.
It processes your template repo and runs a cargo check
as the final step. That's it, a good start to build on.
Contributing
Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as noted in License, without any additional terms or
conditions.
If you want to contribute to cargo-generate
, please see CONTRIBUTING.md.
License
Licensed, at your option, under either of the following licences:
- Apache License, Version 2.0, (LICENSE-APACHE or apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or opensource.org/licenses/MIT)