matklad / xshell

Apache License 2.0
675 stars 28 forks source link

Feature request: Add a way to *extend* an existing `Cmd` with syntax very similar to `cmd!` #96

Open RalfJung opened 1 month ago

RalfJung commented 1 month ago

The cmd! macro is great: commands are quickly written, very readable, and whitespace-safe. However, when the shell scripting becomes a bit more complicated, one quickly hits a frustrating limitation: I have a lot of cmd! invocations in my script that are very similar, but there is no good way to abstract the commonalities into a helper function. The problem is that the cmd! macro can be used only exactly once per command, so it's not possible to have a helper prepare a Cmd value with all the things that are common across my script and then later conveniently add more arguments to it.

In my case, what I'd like to be able to do looks roughly like this:

fn cargo(&self, subcommand: &str) -> Cmd {
  // ...
  cmd!("cargo +{toolchain} {subcommand} {cargo_extra_flags...} --manifest-path={manifest_path}")
    .env(...)
}

fn other_function(&self, ...) {
  extend_cmd!(
    self.cargo("build"),
    "--bins --tests {quiet_flag...} {args...}",
  ).run()?;
}

But currently, I have to instead either repeat the cargo +{toolchain} {subcommand} {cargo_extra_flags...} --manifest-path={manifest_path} part everywhere or write

fn other_function(&self, ...) {
  let cmd = self.cargo("build")
    .args(&["--bins", "--tests"])
    .args(quiet_flag)
    .args(args)
}

which is a lot less readable than what one can do with cmd!.