evobench_tools/io_utils/
bash.rs

1use std::borrow::Cow;
2
3use itertools::Itertools;
4
5// (Todo?: add randomized tests with these calling bash)
6const CHARS_NOT_NEEDING_QUOTING: &str = "_:.-+,/=@[]^";
7
8// Once again. Have a better one somewhere.
9pub fn bash_string_literal(s: &str) -> Cow<'_, str> {
10    if s.chars()
11        .all(|c| c.is_ascii_alphanumeric() || CHARS_NOT_NEEDING_QUOTING.contains(c))
12    {
13        s.into()
14    } else {
15        let mut ss = String::new();
16        ss.push('\'');
17        for c in s.chars() {
18            if c == '\'' {
19                ss.push('\'');
20                ss.push('\\');
21                ss.push('\'');
22                ss.push('\'');
23            } else {
24                ss.push(c);
25            }
26        }
27        ss.push('\'');
28        ss.into()
29    }
30}
31
32pub fn bash_string_from_cmd(cmd: impl IntoIterator<Item = impl AsRef<str>>) -> String {
33    cmd.into_iter()
34        .map(|s| bash_string_literal(s.as_ref()).to_string())
35        .join(" ")
36}
37
38pub fn bash_string_from_program_string_and_args(
39    cmd: impl AsRef<str>,
40    args: impl IntoIterator<Item = impl AsRef<str>>,
41) -> String {
42    let mut cmd = bash_string_literal(cmd.as_ref()).into_owned();
43    for arg in args {
44        cmd.push_str(" ");
45        cmd.push_str(&*bash_string_literal(arg.as_ref()));
46    }
47    cmd
48}
49
50/// `command_path` has to be representable as a str to be made part of
51/// the bash code.
52pub fn bash_string_from_program_path_and_args(
53    command_path: impl AsRef<str>,
54    args: impl IntoIterator<Item = impl AsRef<str>>,
55) -> String {
56    let mut cmd = bash_string_literal(command_path.as_ref()).into_owned();
57    for arg in args {
58        cmd.push_str(" ");
59        cmd.push_str(&*bash_string_literal(arg.as_ref()));
60    }
61    cmd
62}
63
64pub fn bash_export_variable_string(name: &str, val: &str, prefix: &str, suffix: &str) -> String {
65    format!(
66        "{prefix}export {}={}{suffix}",
67        bash_string_literal(name),
68        bash_string_literal(val)
69    )
70}