oconnor663 / duct.rs

a Rust library for running child processes
MIT License
819 stars 34 forks source link

Feature: Helper to convert expressions to shell command strings #79

Open anowell opened 4 years ago

anowell commented 4 years ago

I was creating complex expressions using duct and found myself wanting ways to easily print out the shell command in a way that I could easily copy-paste debug in a bash (or similar) shell to debug, to be able to do something like:

let expr = cmd("foo", &args);
println!("Running: {}", expr.to_sh_string());

I started with some custom simple escaping that seemed good enough for my use case, but I found shell_escape to be more a bit more complete and ended up with something like this:

use shell_escape::escape;

fn to_sh_string(cmd: &str, args: &[&str]) -> String {
    let arg_str = args
        .into_iter()
        .map(|&a| escape(a.into()))
        .collect::<Vec<_>>()
        .join(" ");
    format!("{} {}", escape(cmd.into()), arg_str)
}

Which allowed me to print out abnormally complex expressions like:

ssh -o PasswordAuthentication=no -p 22 -t -i /path/to/identity.pem -o 'ProxyCommand=ssh -p 1234 anowell@somehost.com nc %h %p -w 300' 'ubuntu@10.0.0.99' 'docker run --rm -it -v /home/ubuntu/proj/:/proj -w /proj -e KUBECONFIG=/proj/admin-k8s.conf -e PS1='\''\e[33m\A\e[0m:\e[97;41mproj\e[0m$ '\'' -u $UID --entrypoint bash anowell/some-image:latest --norc -i'

I could also imagine extending this to prefix environment variables to the shell string (e.g. foo=bar mycmd arg1 'another arg'). Just an idea; feel free to close if this doesn't fit into the scope of duct.

oconnor663 commented 4 years ago

That sounds like it could be useful, and it might be a nice improvement over our current debug printing also. I wonder how we would want to represent some of these more complicated features in a cross-platform way:

anowell commented 4 years ago

Interesting. I could go either way on displaying all the extra complexity, and I won't pretend to know how cross-platform this is, but for unix: