Alternative to `cargo new` templates: examples as build-target templates
bushRAT:
I don't think we want to directly pull examples from existing crates as templates.
...
I feel like you'd want an explicit
templateitem to pull from, which would just be a crate (either a single-file script or a more typical crate).
Yes, dependencies are an issue. There is required-features but that doesn't solve everything.
Adding a new template system also has a lot of complications to work through:
- Associating: how does a package declare a relationship to its templates when those templates depend on it? This is one of the problems we are having with the "recommended-bins" idea for libraries to redirect people to their associated binary (e.g. a
cargo install fooand tell people to instead runcargo install foo-cli) - Being able to tell what to copy over. With an example this is easy. With a whole package, it gets more complicated.
- MSRV: if this ends up requiring an MSRV bump, it will take even longer before people can use it
- Bootstrapping: packages have examples today. Maintainers would then need to write out templates and likely dual-source some examples as templates
bushRAT:
The benefit of the new frontmatter system is you could now have single-file templates, which would just look identical to examples anyway.
Nothing stops people from putting frontmatter in their examples today and in fact it might be useful to do so as people get confused reading an example and understanding how to replicate it. Even if we do example templates, we could merge the frontmatter in as well.
bushRAT:
it could also have explicit support for a default
Having defaults would be an interesting idea regardless of what is used as the example.
bushRAT:
If templates are meant to include extending an existing project, not just creating a new one, I feel like we need either a build script or a proc-macro to handle merging a template into a project. Take
tokioandclapas examples. They each could have templates for a new binary project, and ideally you could slaptokioonto an existing project and it would handle taking the contents of your existingmainfunction and placing them into the newasyncversion for you. This probably can't be done by Cargo since it's far too contextual, but I think either amerge.rsor a merge proc-macro could do it.
For clap, I don't think there is anything I would do for a merge operation. For CLI testing, I could see customizing the environment variable read for CARGO_BIN_EXE_*. But I've accepted the idea of not doing that.
Build scripts as is are getting a lot of scrutiny for security a and build performance and we should be looking for ways to remove their need or consolidate down to fewer of them. At least with build scripts, you can depend on everything and then audit it before running. Here, you would be running foreign code and the workflow for auditing it is worse and you wouldn't even know the version used.
If we have a merge.rs, we then also need merge-dependencies and the run on effects of that (e.g. cargo new time to compile all of this). We also then need a more native way of validating templates while before I was assuming we could rely on third-party tools which then further extends the API surface in this design work which is one of the things this design was trying to minimize.
bushRAT:
I do think a TUI more like
npm initwould be useful, especially for new users. For one thing, it could give you an option to search for a template fromcrates.io, select features and dependencies, etc. I imagine you could add a--interactive/-Iswitch to turn this on (in order to preserve the current fast non-interactive command).
There is interest in adding interactive modes to Cargo commands. We are testing the waters with a TUI for cargo tree, see GitHub - orhun/cargo-tree-tui: Ratatuifying Rust's package manager · GitHub
kornel:
For discoverability in Cargo you'd also want to have descriptions for them, which the package has, but targets don't.
Good point about descriptions.
Discussion in the ATmosphere