1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::fs::File;
use std::io::{BufRead, BufReader};

pub fn escape_quote_string(input: &str) -> String {
    let mut output = String::with_capacity(input.len() + 2);
    output.push('"');

    for c in input.chars() {
        if c == '"' || c == '\\' {
            output.push('\\');
        }
        output.push(c);
    }

    output.push('"');
    output
}

fn looks_like_flag(input: &str) -> bool {
    if !input.starts_with('-') {
        false
        // it does not start with  '-'
    } else if !input.starts_with("--") {
        if input.len() > 2
            && input.chars().nth(2).expect("this should never trigger") != '='
            && input.chars().nth(2).expect("this should never trigger") != ' '
        {
            false
            // while it start with '-', it is not of the form '-x=y' or '-x y'
        } else {
            input.len() >= 2
        }
    } else {
        input.len() > 2
        // it is either a flag --x or a '--'
    }
}

fn escape_quote_string_when_flags_are_unclear(input: &str) -> String {
    // internal use only. When reading the file for flags goes wrong, revert back to a manual check
    // for flags.
    let mut output = String::new();
    if !looks_like_flag(input) {
        output.push('"');
        for c in input.chars() {
            if c == '"' || c == '\\' {
                output.push('\\');
            }
            output.push(c);
        }
        output.push('"');
        output
    } else if input.contains(' ') || input.contains('=') {
        // this is a flag that requires delicate handling
        let mut flag_tripped = false;
        for c in input.chars() {
            if c == '"' || c == '\\' {
                output.push('\\');
            }
            output.push(c);
            if (c == ' ' || c == '=') && !flag_tripped {
                flag_tripped = true;
                output.push('"');
            }
        }
        output.push('"');
        output
    } else {
        // this is a normal flag, aka "--x"
        String::from(input)
    }
}

pub fn escape_quote_string_with_file(input: &str, file: &str) -> String {
    // use when you want to cross-compare to a file to ensure flags are checked properly
    let file = File::open(file);
    match file {
        Ok(f) => {
            let lines = BufReader::new(f).lines();
            for line in lines {
                let mut flag_start = false;
                let mut word = String::new();
                let line_or = line.unwrap_or_else(|_| String::from(" "));
                if line_or.contains('-') {
                    for n in line_or.chars() {
                        if n == '-' {
                            flag_start = true;
                        }
                        if n == ' ' || n == ':' || n == ')' {
                            flag_start = false;
                        }
                        if flag_start {
                            word.push(n);
                        }
                    }
                }
                if word.contains(input) || {
                    let s: Vec<&str> = input.split('=').collect();
                    word.contains(s[0])
                } {
                    return input.to_string();
                }
            }
            let mut final_word = String::new();
            final_word.push('"');
            final_word.push_str(input);
            final_word.push('"');
            final_word
        }
        _ => escape_quote_string_when_flags_are_unclear(input),
    }
}