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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! A set of utility functions to implement reglang-expr CLIs
use ;
/// Unzip a vector of key-value pairs into separate vectors for keys and values.
///
/// ```
/// use reqlang_expr::cliutil::unzip_key_values;
///
/// let keys_values: Vec<(String, String)> = vec![
/// ("key1".to_string(), "val1".to_string()),
/// ("key2".to_string(), "val2".to_string())
/// ];
///
/// let (keys, values) = unzip_key_values(keys_values);
///
/// assert_eq!(vec!["key1", "key2"], keys);
/// assert_eq!(vec!["val1", "val2"], values);
/// ```
///
/// ## Usage
///
/// This is can be used to accept in key-value pairs from command line arguments,
/// feeding the keys/values to the compile time and runtime envrionments
/// respectively.
///
/// ```ignore
/// let (var_keys, var_values) = unzip_key_values(args.vars);
/// let (prompt_keys, prompt_values) = unzip_key_values(args.prompts);
/// let (secret_keys, secret_values) = unzip_key_values(args.secrets);
///
/// let env = Env::new(var_keys, prompt_keys, secret_keys);
///
/// let runtime_env: RuntimeEnv = RuntimeEnv {
/// vars: var_values,
/// prompts: prompt_values,
/// secrets: secret_values,
/// };
/// ```
/// Parse a single key-value pair string. This is used to parse command line arguments.
///
/// ```
/// use reqlang_expr::cliutil::parse_key_val;
///
/// let a = parse_key_val::<String, String>("a=1");
///
/// assert_eq!(("a".to_string(), "1".to_string()), a.unwrap());
/// ```
///
/// Example of using parse_key_val with Clap
///
/// ```
/// use clap::Parser;
/// use reqlang_expr::cliutil::parse_key_val;
///
/// #[derive(Parser, Debug)]
/// struct Args {
/// #[arg(long, value_delimiter = ' ', num_args = 1.., value_parser = parse_key_val::<String, String>)]
/// vars: Vec<(String, String)>
/// }
///
/// let args = Args::parse_from(["test", "--vars", "key=value", "another_key=another_value"]);
/// assert_eq!(args.vars, vec![("key".to_string(), "value".to_string()), ("another_key".to_string(), "another_value".to_string())]);
/// ```
///
/// Read source code from a file at the provided path or from standard input if no path is provided.
///
/// # Usage
///
/// ## From a file:
///
/// ```
/// use reqlang_expr::cliutil::read_in_source;
///
/// let source_code = read_in_source(Some("./spec/valid/call_id.expr".to_string()));
///
/// assert_eq!("(id (noop))", source_code);
/// ```
///
/// ## From stdin:
///
/// ```ignore
/// use reqlang_expr::cliutil::read_in_source;
///
/// // Assuming "(id (noop))" was passed to stdin...
///
/// let source_code = read_in_source(None);
///
/// assert_eq!("(id (noop))".to_string(), source_code);
/// ```