Hi!
I find myself in a need of a simple cli tool when working on my Rust projects. However, I am on a pretty deep level of yak-shaving now, so I am afraid that I'll get a stackoverflow if try write to write this tool myself
So, I'll just through in the idea here, and hope that somebody picks it up and runs with it =)
When developing Rust code, I often have to run repetetive tasks. The example of such tasks are
- generate some files to
src/
(build.rs is not applicable here, b/c I want to commit the results of codegen) - add a new test data file with a specified format: for example, add files
00dd_foo.rs
and00dd_foo.txt
totest/test_data/parsing/ok
- check that each file with
.rs
extension starts with a license preamble - build and package a rust application
- automatically update changelog file
Currently, I use just
(a simpler and more sane make
) for this, but I don't quite like two things about this solution:
- it relies on shell, and I am bad at shell scripting,
- shells are bad at being cross-platform.
What I would really love is the ability to write this "scripts" in Rust...
Here is a short specification of the proposed solution
Specification
Conventions
By convention, all custom tasks are defined as a binary crate in the tasks
subdirectory. For example, the layout for the frobnicator project might look like this:
frobnicator/
Cargo.toml
src/
lib.rs
tasks/
Cargo.toml # this is **not** a member of workspace
src/
main.rs # this is the binary capable of executing all the tasks
The bare-bones way to run generate-test
taks would look like this than:
$ cargo --manifest-path ./tasks/Cargo.toml run -- generate-test --name "foo"
Running Tasks
To run tasks in a convenient way, a special subcommand, cargo task
is provided. So, the actual invocation looks like
$ cargo task generate-test --name "foo"
The job of cargo-task
is:
- find out the workspace root and
cd
in there - run
cargo build --manifest-path ./tasks
to build the tasks crate - run the resulting
tasks
binary, forwaring all the command-line arguments.
Bike shedding: should this be cargo do
instead of cargo task
? Or maybe even cargo x
, to mirror ./x.py
? Or maybe a fancy cargo swissknife
?
Defining Tasks
In principle, it is possible to write arbitrary code in the tasks/src/main.rs
. However a "shell-like scripting support library" would be most useful! Here are some tasks that this library might do:
- reexport file crate API to make reading and wriing files easily
- reexport other utilites to make it easy to read config files and env variables.
- provide a way to conveniently launch subprocesses, with few lines of code and with automatic panicking on non-zero return code a-la
set -e
. - provide pure-rust implementations of common shell utilites as functions, like
cd
,ls
,grep
,find
,sed
. - provide automatic command rounting, with a strong convention over configuration API. That is, be simpler and less flexible than clap, the only way to define commands and options should be via serde.
- provide a convenient way to shell out back to Cargo.
That's about it for specification I guess?
As I've said, I don't have enough time/desire to make this dream a reality, but, if someone else creates at least a bare bones version of it (basically, creates a repo with CI and implementation of cargo task
), I promise I'll use this thing for my project and will contribute stuff, necessary for me personally