Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any interest in an additional convenience wrapper? #10

Closed
codesections opened this issue Jan 22, 2020 · 6 comments
Closed

Any interest in an additional convenience wrapper? #10

codesections opened this issue Jan 22, 2020 · 6 comments
Assignees

Comments

@codesections
Copy link

codesections commented Jan 22, 2020

I have been using run_script fairly heavily in various CLI contexts, and frequently encounter the situation where I would like to run a script that I expect to succeed. If it does, I want to do something with the output; if it doesn't I want to print the relevant error to the end user and exit my script. To accomplish this, I was writing a lot of code like the following:

let (code, files, stderr) = run_script!("ls").unwrap_or_else(|e| {
    eprintln!("{}", e);
    std::process::exit(1)
});
if code != 0 {
    eprintln!("{}", stderr);
    std::process::exit(code);
};

(Not with ls; it's just a simple command to have as an example.)

After writing this more times than I should have, it occurred to me to write a very simple helper function to reduce the verbosity of this code. So I now write

let files = sh("ls");

I believe that the use case of exiting on errors might be a common one when using run_script for basic scripting. (One reason I believe that this may be the case is that many people like to use set -e in Bash scripts to achieve a similar result of exiting on any non-zero exit code). If that is the case, would it be worth including the helper function in run_script?

Features Description
A helper function that returns standard output or (if the command fails) exits and displays the standard error output.

Describe the solution you'd like
This is the simple helper function I am currently using. Would it make sense to add it to run_script?

Code Sample

use run_script::run_script;

pub fn sh(script: &str) -> String {
    let (code, stdout, stderr) = run_script!(script).unwrap_or_else(|e| {
        eprintln!("{}", e);
        std::process::exit(1)
    });
    if code != 0 {
        eprintln!("{}", stderr);
        std::process::exit(code);
    };
    stdout
}
@sagiegurari
Copy link
Owner

interesting. thinking about how to do it.
what if there was an option (default false) to exit on error like validate_exit_code or something?
naturally default to false.

@codesections
Copy link
Author

what if there was an option (default false) to exit on error like validate_exit_code or something?

That could work, but it loses some of the convenience of a dedicated function. I guess the API would be something like

    let mut options = ScriptOptions::new();
    options.validate_exit_code(true);
    let output  = run_script!(
        r#"
        echo "Test"
        "#,
        &options
    ).unwrap();

which is significantly more verbose. It also has the disadvantage of giving the run_script! macro a different return type depending on the option it's called with. I think that's possible with a macro, but it's probably not what users would expect.

One comparison that might be helpful is to the standard library. It has many different SOMETHING_unchecked or SOMETHING_mut methods. Each of those could have been handled by passing an extra configuration parameter, but that would have been much more verbose.

Following the standard library's example, what if run_script added a run_script_or_exit macro that runs the script and either returns the output or exits the program? Then the example above would be reduced to

let output  = run_script_or_exit!(
        r#"
echo "Test"
"#
    );

@sagiegurari
Copy link
Owner

good idea.
i guess output is out and err tuple?
you would like to submit a PR?

@codesections
Copy link
Author

i guess output is out and err tuple?
Hmm, I was thinking that output could just be standard output. If the command returns successfully, then standard error should in theory be blank. In practice, I know some programs use standard error to print diagnostic/extra info even when the command is successful, and the API I have in mind doesn't expose that info.

My view is that failing to expose standard err isn't too bad: it's typically blank when the program exits successfully; even if it's not blank, it's usually extra info that's useful when the program is called interactively (and not that useful inside a script); and – in the rare case when neither of the above apply and the user wants to receive standard err – users still have access to the more verbose run_script! and run_script forms.

you would like to submit a PR?

Will do!

@sagiegurari
Copy link
Owner

cool. i still prefer the err as well as sometimes processes decide to write to err (strange)

@sagiegurari
Copy link
Owner

@codesections I just pushed a new function and macro for this.
it will output the output and error but in case of invocation error or exitcode!=0 it will exit.
i'll release it really soon. thanks for the feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants