cargo-generate / cargo-generate Goto Github PK
View Code? Open in Web Editor NEWcargo, make me a project
Home Page: https://cargo-generate.github.io/cargo-generate
License: Apache License 2.0
cargo, make me a project
Home Page: https://cargo-generate.github.io/cargo-generate
License: Apache License 2.0
the ident_case lib has given us some trouble. to fix it i wrote my own function, but longterm we might want to move to heck
, https://github.com/withoutboats/heck, as per a suggestion by @fitzgen
When executing cargo-generate a user needs to pass an identifier for the template they want to generate a project from.
What can be such template identifiers?
How can we extract a cargo-generate compatible template from them?
One or more of
appveyor and travis
Follow Rust's short philosophy,like function
to fn
cargo-generate
change to cargo-g
maybe better?
Ashleys-MacBook-Pro-2:cargo-generate ag_dubs$ cargo run -- --git https://github.com/ashleygwilliams/wasm-pack-template.git
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/cargo-generate --git 'https://github.com/ashleygwilliams/wasm-pack-template.git'`
The project's name is: wasm-fart
Nice, I'll call your project `wasm-fart`
Done!
Ashleys-MacBook-Pro-2:cargo-generate ag_dubs$ ls
CODE_OF_CONDUCT.md Cargo.lock LICENSE-APACHE README.md target
CONTRIBUTING.md Cargo.toml LICENSE-MIT src wasm-fart
Ashleys-MacBook-Pro-2:cargo-generate ag_dubs$ cd wasm-fart/
Ashleys-MacBook-Pro-2:wasm-fart ag_dubs$ ls
Cargo.toml LICENSE_APACHE LICENSE_MIT README.md src
Ashleys-MacBook-Pro-2:wasm-fart ag_dubs$ cat Cargo.toml
[package]
name = {{project-name}}
version = "0.1.0"
authors = {{authors}}
[dependencies]
wasm-bindgen = "0.2"
let's have some!
to help make it easier for us to proceed without breaking things, i'd like to propose that template authors be required to include a cargo-generate version in their cargo toml, e.g.
[package]
name = "{{project-name}}"
version = "0.1.0"
cargo-generate = "0.1.0"
if the version doesn't exist in the cargo toml, we should WARN
if the version of cargo-generate on disk is different than the listed version, we should WARN
this should be fully semver feature full, so folks should be able to write something like:
cargo-generate = "~0.2.0"
Suitable for things like the travis CI badge support in Cargo.toml
.
let's add some basic usage documentation to the readme
@killercup if you wanna do this go for it- otherwise i'll find sometime, perhaps today
Could there be a repository of templates somewhere? Maybe it could be hacked in as a category on crates.io.
This is something else that has been handy from cookiecutter but is more questionable due to security.
Use cases from my python cookiecutter translated to Rust.
cargo update && git add Cargo.lock
for binsThe main question is how would we handle this in Rust?
cargo-script
?To alleviate security concerns, we could have flags for
I am getting an error while creating a cli-wg project ggrs
.
dinesh@Personal /Users/dinesh $
| Mac => cargo generate --git https://github.com/rust-clique/cargo-template-cli
🤷 Project Name: grrs
🔧 Creating project called `grrs`...
error: authentication required but no callback set; class=Net (12)
Hello!
I am trying to make a template for creating mdbooks. cargo-generate
currently analyses the Cargo.toml
file and then tries to replace the placeholders. It would be great to have mdbook templates, however, the book.toml
file should be parsed instead. Having a --book
flag could direct cargo-generate
to parse book.toml
. Any suggestions?
There is already a short version of generate, why don't we add -n for name and -g for git?
Example:
cargo gen -g https://github.com/user/template.git -n foo
make a changelog, etc
in prep for publishing this and opening to contributors, let's break the src and tests up into modules
cargo-generate's main job is to copy file and replace some of their contents. It does so by looking for placeholders and replacing them with known values for known placeholder names.
Where do the values for these placeholders come from?
If they come from multiple sources, in which order are these accessed (with either first/last one wins)?
Suggestion:
Last one wins.
I wanted to install cargo-generate in my WSL Ubuntu and ran into a few problems. One was with the openssl-sys crate that needs at least two additional packages that weren't installed on my system. The other was libssh2-sys that needs cmake. So in order to install cargo-generate I had to
sudo apt-get install pkg-config libssl-dev cmake
first. The openssl-sys crate has a guide on how to install the build dependencies on various systems. I don't know if cmake is needed on all systems.
In #47, one of the possibilities noted is
sub dir in a repo
I wanted to make a suggestion that's a little more extensive than this, and I think it's enough of an expansion to list as a separate issue.
A number of projects have examples/
directories with cargo support for running them directly, and there's also a proposal to let cargo support larger per-directory examples in a sub-structure under there. These are often good starting points for customising your own code; I know I've done this a number of times, especially with some embedded projects. That sounds a lot like a template!
I think is worth combining these proposals and having some specific conventions to make it easier, such that project example directories can always/automatically be templates. I'd like it to be sufficiently low-friction that neither general crate authors nor template consumers need to do anything much extra or unusual to use examples as templates, and offering templates becomes the norm.
This probably involves some changes on both sides, perhaps something like this:
example.toml
with placeholder values. Cargo knows how to use this when running in-place as an example.cargo new --example
?) so that there's a cohesive story from start to, well, new start :)cargo generate
can look in the examples directories to find templates, and (in interactive mode) offer a list to pick from, so that repos can be discoverable as either single templates at the root, or more structured collections.One of the strongest reasons for this is to keep examples and templates in sync with the libraries they represent; cargo should test each of the templates-as-examples just like today. If they're in a separate repo, there's always a risk they'll languish. If they're in the one repo, examples can also be updated to match library code changes on branches.
As mentioned on Reddit,
I think this crate is not very useful without more advanced customization based on variables.
This would require a template engine though.
Example:
Cargo.toml
{% if use_serde %}
serde = "1.*"
serde_derive = "1.*"
{% endif %}
lib.rs
{% if db_type = "postgres" % }
type Connection = diesel::pg::PgConnection;
{% elseif db_type = "mysql" % }
...
{% endif %}
Two options for a template engine that come to mind:
I set my templates up in one repository and was branching for differences in my templates (see cli-templates for my rough drafts); however, as of now cargo-generate
only supports main branch templating.
To me it makes sense to have all my custom templates in one repostory but have the ability to call them by branch, vice several different repositories. Also it might make sense for offical templates to have branches with different specializations or layouts.
Related to RFC #47
For my python projects, I've found cookiecutter's custom variables really helpful. I'm assuming it would be the same for cargo-generate
(including unexpected cases like #14).
Ideas from cookiecutter
I'm also assuming that environment-derived variables (author) would still be gathered but built-in policy like "name" would not be.
cargo generate --variable name some-crate
).right now, we receive a project name from the user and then force it to kebab case. a user might not love this. let's give an option to force, which will skip the case check and conversion. crate_name
should still be snake case, but project-name
should be exactly whatever the user entered.
When cargo-generate tries to generate a project, it may require meta-information, e.g. which placeholders to look for, or how to find files to apply substitutions to. While currently, this is defined by hard-coded rules in the tool itself, in the future this might be configurable.
Should templates be able to contain (optional) config files to pass parameters and meta information to cargo-generate?
Yes, and it'll be in TOML format with a schema like
[template]
name = "foo"
repository = "https://github.com/rust-lang-nursery/cargo-template-foo"
placeholders = ["project-name", "author"]
Yes, and it can also be a subsection of a Cargo.toml
file
Yes, and it can also be a subsection of a book.toml
file
No
Example from #51
Cargo.toml
{% if use_serde %}
serde = "1.*"
serde_derive = "1.*"
{% endif %}
lib.rs
{% if db_type = "postgres" % }
type Connection = diesel::pg::PgConnection;
{% elseif db_type = "mysql" % }
...
{% endif %}
Relevant tags
Rationale:
templates
folder), and that will not require additional git setup ceremonycargo new
already acts like code generator and features like --name
and --vcs
might be effectively combined and reused hereExample output:
> cargo test
<snip>
Compiling cargo-generate v0.0.0 (file:///C:/Users/steve/tmp/cargo-generate)
Finished dev [unoptimized + debuginfo] target(s) in 6m 40s
Running target\debug\deps\cargo_generate-4873338d5974a9ff.exe
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Running target\debug\deps\integration-1d803e56ff299d5d.exe
running 1 test
test basics::simple_cargo_thing ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
> cargo test
Finished dev [unoptimized + debuginfo] target(s) in 0.73s
Running target\debug\deps\cargo_generate-4873338d5974a9ff.exe
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Running target\debug\deps\integration-1d803e56ff299d5d.exe
running 1 test
test basics::simple_cargo_thing ... FAILED
failures:
---- basics::simple_cargo_thing stdout ----
thread 'basics::simple_cargo_thing' panicked at 'Unexpected failure.
code-1
stderr=``````
command=`"git" "commit" "--message" "initial commit"`
code=1
stdout=```On branch master
nothing to commit, working tree clean
stderr=
', C:\Users\steve\.cargo\registry\src\github.com-1ecc6299db9ec823\assert_cmd-0.4.0\src\assert.rs:140:13
note: Run with `RUST_BACKTRACE=1` for a backtrace.
failures:
basics::simple_cargo_thing
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--test integration'
Currently, cargo-generate tries to find and replace all {{ blocks }}
in all files. This is the most trivial implementation, but not necessarily the best or most user friendly one.
As written in #14 (comment) and #40 (comment), an alternative might be to instead only consider files whose names match a specific pattern as templates.
Yes, with .template
(Because it's pretty obvious and also not bound to any implementation. It has the added advantage that projects that already have .hbs
or .liquid
files are unlikely to conflict.)
Yes, defined in config file (cf. #48), defaulting to .tplt
No
The implementation should be pretty straightforward. I assume it's a matter of expanding this condition and adding a test or two.
right now, we receive a name from the user, force it to kebab case, and make the project. we should check the user's entered name and warn them if we are changing the case of the name they passed.
The https://github.com/rustwasm/rust_wasm_template template has travis ci pre-configured. We use travis to make sure that the template doesn't break. But it also works out so that if you clone the template, all you have to do is flip the switch in your travis ci dashboard to also get ci set up and configured.
In the process of moving that template over to cargo-generate
, the template's CI is broken because of all the {{variables}}
. I could fix this by making the CI script run cargo-generate
and test the generated template, but now I have two different CI scripts: one for the template and another for the projects generated from the template.
How can we maintain a single CI script for both?
$ cargo +nightly build --release --target wasm32-unknown-unknown
Updating registry `https://github.com/rust-lang/crates.io-index`
Compiling unicode-xid v0.1.0
Compiling serde v1.0.59
Compiling wasm-bindgen-shared v0.2.12
Compiling dtoa v0.4.2
Compiling cfg-if v0.1.3
Compiling itoa v0.4.1
Compiling log v0.4.3
Compiling proc-macro2 v0.4.8
Compiling quote v0.6.2
Compiling syn v0.14.0
Compiling serde_json v1.0.17
Compiling serde_derive v1.0.59
Compiling wasm-bindgen-backend v0.2.12
Compiling wasm-bindgen-macro v0.2.12
Compiling wasm-bindgen v0.2.12
Compiling {{project-name}} v0.1.0 (file:///home/fitzgen/rust_wasm_template)
error: invalid character `{` in crate name: `{{project_name}}`
error: invalid character `}` in crate name: `{{project_name}}`
error: aborting due to 2 previous errors
error: Could not compile `{{project-name}}`.
To learn more, run the command again with --verbose.
Suitable for the "repository" field in Cargo.toml
While setting up my environment and templates I noticed a few areas that would be helpful to have a {{date}}
placeholder. Might also be nice to have sub-date strings like {{year}}
as well (e.g. for license, info).
Related to #46
Doesn't work as cargo generate
:
$ cargo generate --help
error: Found argument 'generate' which wasn't expected, or isn't valid in this context
USAGE:
cargo-generate [OPTIONS] --git <git>
For more information try --help
$ cargo generate --version
error: Found argument 'generate' which wasn't expected, or isn't valid in this context
USAGE:
cargo-generate [OPTIONS] --git <git>
For more information try --help
However it does work as cargo-generate
:
$ cargo-generate --version
cargo-generate 0.1.0
$ cargo-generate --help
cargo-generate 0.1.0
Ashley Williams <[email protected]>, Pascal Hertleif <[email protected]>
Generate a new Cargo project from a given template
Right now, only git repositories can be used as templates. Just execute
$ cargo generate --git https://github.com/user/template.git --name foo
and a new Cargo project called foo will be generated.
TEMPLATES:
In templates, the following placeholders can be used:
- `project-name`: Name of the project, in dash-case
- `crate_name`: Name of the project, but in a case valid for a Rust identifier, i.e., snake_case
- `authors`: Author names, taken from usual environment variables (i.e. those which are also used by Cargo and git)
USAGE:
cargo-generate [OPTIONS] --git <git>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
--git <git>
--name <name>
$ cargo new --lib my-template
Created library `my-template` project
$ cd my-template/
$ cat Cargo.toml # <-- edited to have name be {{project-name}}
[package]
name = "{{project-name}}"
version = "0.1.0"
authors = ["Nick Fitzgerald <[email protected]>"]
[dependencies]
$ mkdir tests
$ echo 'extern crate {{crate_name}};' > tests/tests.rs
$ git add .
$ git commit -m "initial"
[master (root-commit) 5db8b7e] initial
4 files changed, 17 insertions(+)
create mode 100644 .gitignore
create mode 100644 Cargo.toml
create mode 100644 src/lib.rs
create mode 100644 tests/tests.rs
$ cd ..
$ cargo-generate --git my-template --name my-project-with-hyphens
⠁
Done! New project created /tmp/my-project-with-hyphens
$ cd my-project-with-hyphens/
$ cargo test
Compiling my-project-with-hyphens v0.1.0 (file:///tmp/my-project-with-hyphens)
error: expected one of `;` or `as`, found `-`
--> tests/tests.rs:1:16
|
1 | extern crate my-project-with-hyphens;
| ^ expected one of `;` or `as` here
error: aborting due to previous error
error: Could not compile `my-project-with-hyphens`.
warning: build failed, waiting for other jobs to finish...
error: build failed
curious what you think @killercup - not sure if binaries really make sense for a cargo add-on, but interested in your thoughts.
This seems to be a common trap for subcommands...
$ cargo-generate
error: The following required arguments were not provided:
--git <git>
$ cargo generate
error: Found argument 'generate' which wasn't expected, or isn't valid in this context
I created a minimal template for PyO3:
https://github.com/DD5HT/pyo3-template
This would remove the dependency on Git, and we would just link in libgit2. It would require less things to be installed, especially when you start distributing this as a binary, since Rust statically links everything!
This might be trivial bike-shedding territory, but I'm not in love with the naming.
generate
is very generic and doesn't communicate the intent all that clearly.
Some options I would like more:
Actually, having this integrated into "cargo new" might also be a cool option, although one that would probably take some time to get right.
Eg:
cargo new --template=diesel-rs/diesel
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.