matklad / xshell

Apache License 2.0
675 stars 28 forks source link

Add a `cmds!` that runs multiple #71

Closed cgwalters closed 1 year ago

cgwalters commented 1 year ago

Basically would allow going from e.g.:

cmd!(sh, "foo --blah").run()?;
cmd!(sh, "othercmd --somearg --otherarg").run()?;
cmd!(sh, "bar --baz").run()?;

to

cmds!(sh, "foo --blah
othercmd --somearg --otherarg
bar --baz").run()?;

Happy to try implementing this if you agree; roughtly I think we'd return a struct CmdList(Vec<Cmd>) in this case whose only method is fn run(self) -> Result<()> or so?

matklad commented 1 year ago

Interesting idea! Looking at our publish script:

https://github.com/matklad/xshell/blob/cdd48d0a8071928adbb991f78b5e2bdef8f6047a/examples/ci.rs#L61-L64

that could perhaps be written as

        cmds!(sh, "
            git tag v{version};
            cargo publish --token {token} --package xshell-macros;
            cargo publish --token {token} --package xshell;
            git push --tags;
        ").run()?

using ; (or maybe &&) as a special bit of xshell-syntax to signify "run these commands one-by-one". I think we could make it work!

I don't think we should though --- it is reading nicer with multiple commands, but a pretty significant bit of non-orthogonality creeps in. The problem here is that we now have two ways to express sequencing ; in the host language and ; in the macro language. These two would ultimately fight with each other, and there will be a large "cliff" if you realize that macro-; is not enough and you need host-; (eg, if you realize you need to conditionally execute one command).

So, yeah, I'd rather not do it for xshell. Thanks for the suggestion anyway, it's an interesting question to ponder!